From a7a742b165c825e7e4f87a054c9737e1f1883de3 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 15 Mar 2018 12:52:59 +0100 Subject: [PATCH] openvidu-recording-java and openvidu-recording-node --- .gitignore | 4 + openvidu-recording-java/.gitignore | 24 + openvidu-recording-java/LICENSE | 201 + openvidu-recording-java/README.md | 13 + openvidu-recording-java/docker/Dockerfile | 51 + .../docker/create_image.sh | 15 + openvidu-recording-java/docker/kms.sh | 19 + openvidu-recording-java/docker/ngrok.sh | 6 + openvidu-recording-java/docker/ngrok.yml | 8 + .../docker/supervisord.conf | 26 + openvidu-recording-java/pom.xml | 102 + .../main/java/io/openvidu/js/java/App.java | 13 + .../io/openvidu/js/java/MyRestController.java | 250 + .../application-container.properties | 8 + .../src/main/resources/application.properties | 9 + .../main/resources/openvidu-selfsigned.jks | Bin 0 -> 2268 bytes .../src/main/resources/static/app.js | 242 + .../main/resources/static/images/favicon.ico | Bin 0 -> 5430 bytes .../openvidu_globe_bg_transp_cropped.png | Bin 0 -> 11746 bytes .../openvidu_grey_bg_transp_cropped.png | Bin 0 -> 39532 bytes .../openvidu_vert_white_bg_trans_cropped.png | Bin 0 -> 22426 bytes .../static/images/subscriber-msg.jpg | Bin 0 -> 82734 bytes .../src/main/resources/static/index.html | 99 + .../static/openvidu-browser-1.8.0.js | 15134 ++++++++++++++++ .../src/main/resources/static/style.css | 399 + .../io/openvidu/js/java/test/AppTest.java | 38 + openvidu-recording-node/.gitignore | 60 + openvidu-recording-node/LICENSE | 201 + openvidu-recording-node/README.md | 13 + openvidu-recording-node/openviducert.pem | 21 + openvidu-recording-node/openvidukey.pem | 27 + openvidu-recording-node/package.json | 25 + openvidu-recording-node/public/app.js | 242 + .../public/images/favicon.ico | Bin 0 -> 5430 bytes .../openvidu_globe_bg_transp_cropped.png | Bin 0 -> 11746 bytes .../openvidu_grey_bg_transp_cropped.png | Bin 0 -> 39532 bytes .../openvidu_vert_white_bg_trans_cropped.png | Bin 0 -> 22426 bytes .../public/images/subscriber-msg.jpg | Bin 0 -> 82734 bytes openvidu-recording-node/public/index.html | 99 + .../public/openvidu-browser-1.8.0.js | 15134 ++++++++++++++++ openvidu-recording-node/public/style.css | 399 + openvidu-recording-node/server.js | 239 + 42 files changed, 33121 insertions(+) create mode 100644 openvidu-recording-java/.gitignore create mode 100644 openvidu-recording-java/LICENSE create mode 100644 openvidu-recording-java/README.md create mode 100644 openvidu-recording-java/docker/Dockerfile create mode 100755 openvidu-recording-java/docker/create_image.sh create mode 100644 openvidu-recording-java/docker/kms.sh create mode 100644 openvidu-recording-java/docker/ngrok.sh create mode 100644 openvidu-recording-java/docker/ngrok.yml create mode 100644 openvidu-recording-java/docker/supervisord.conf create mode 100644 openvidu-recording-java/pom.xml create mode 100644 openvidu-recording-java/src/main/java/io/openvidu/js/java/App.java create mode 100644 openvidu-recording-java/src/main/java/io/openvidu/js/java/MyRestController.java create mode 100644 openvidu-recording-java/src/main/resources/application-container.properties create mode 100644 openvidu-recording-java/src/main/resources/application.properties create mode 100644 openvidu-recording-java/src/main/resources/openvidu-selfsigned.jks create mode 100644 openvidu-recording-java/src/main/resources/static/app.js create mode 100644 openvidu-recording-java/src/main/resources/static/images/favicon.ico create mode 100644 openvidu-recording-java/src/main/resources/static/images/openvidu_globe_bg_transp_cropped.png create mode 100644 openvidu-recording-java/src/main/resources/static/images/openvidu_grey_bg_transp_cropped.png create mode 100644 openvidu-recording-java/src/main/resources/static/images/openvidu_vert_white_bg_trans_cropped.png create mode 100644 openvidu-recording-java/src/main/resources/static/images/subscriber-msg.jpg create mode 100644 openvidu-recording-java/src/main/resources/static/index.html create mode 100644 openvidu-recording-java/src/main/resources/static/openvidu-browser-1.8.0.js create mode 100644 openvidu-recording-java/src/main/resources/static/style.css create mode 100644 openvidu-recording-java/src/test/java/io/openvidu/js/java/test/AppTest.java create mode 100644 openvidu-recording-node/.gitignore create mode 100644 openvidu-recording-node/LICENSE create mode 100644 openvidu-recording-node/README.md create mode 100644 openvidu-recording-node/openviducert.pem create mode 100644 openvidu-recording-node/openvidukey.pem create mode 100644 openvidu-recording-node/package.json create mode 100644 openvidu-recording-node/public/app.js create mode 100644 openvidu-recording-node/public/images/favicon.ico create mode 100644 openvidu-recording-node/public/images/openvidu_globe_bg_transp_cropped.png create mode 100644 openvidu-recording-node/public/images/openvidu_grey_bg_transp_cropped.png create mode 100644 openvidu-recording-node/public/images/openvidu_vert_white_bg_trans_cropped.png create mode 100644 openvidu-recording-node/public/images/subscriber-msg.jpg create mode 100644 openvidu-recording-node/public/index.html create mode 100644 openvidu-recording-node/public/openvidu-browser-1.8.0.js create mode 100644 openvidu-recording-node/public/style.css create mode 100644 openvidu-recording-node/server.js diff --git a/.gitignore b/.gitignore index 6143e53f..1c3a636c 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,7 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* + +*/.settings +*/.classpath +*/.project diff --git a/openvidu-recording-java/.gitignore b/openvidu-recording-java/.gitignore new file mode 100644 index 00000000..950fc085 --- /dev/null +++ b/openvidu-recording-java/.gitignore @@ -0,0 +1,24 @@ +# 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-recording-java/LICENSE b/openvidu-recording-java/LICENSE new file mode 100644 index 00000000..8dada3ed --- /dev/null +++ b/openvidu-recording-java/LICENSE @@ -0,0 +1,201 @@ + 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-recording-java/README.md b/openvidu-recording-java/README.md new file mode 100644 index 00000000..b01e2fa1 --- /dev/null +++ b/openvidu-recording-java/README.md @@ -0,0 +1,13 @@ +[![License badge](https://img.shields.io/badge/license-Apache2-orange.svg)](http://www.apache.org/licenses/LICENSE-2.0) +[![Documentation badge](https://readthedocs.org/projects/fiware-orion/badge/?version=latest)](http://openvidu.io/docs/home/) +[![Docker badge](https://img.shields.io/docker/pulls/fiware/orion.svg)](https://hub.docker.com/r/openvidu/) +[![Support badge](https://img.shields.io/badge/support-sof-yellowgreen.svg)](https://groups.google.com/forum/#!forum/openvidu) + +[![][OpenViduLogo]](http://openvidu.io) + +openvidu-recording-java +=== + +Visit [openvidu.io/docs/tutorials/openvidu-js-java/](http://openvidu.io/docs/tutorials/openvidu-js-java/) + +[OpenViduLogo]: https://secure.gravatar.com/avatar/5daba1d43042f2e4e85849733c8e5702?s=120 diff --git a/openvidu-recording-java/docker/Dockerfile b/openvidu-recording-java/docker/Dockerfile new file mode 100644 index 00000000..8b97b5cc --- /dev/null +++ b/openvidu-recording-java/docker/Dockerfile @@ -0,0 +1,51 @@ +FROM ubuntu:16.04 +MAINTAINER openvidu@gmail.com + +# Install Kurento Media Server (KMS) +RUN echo "deb http://ubuntu.kurento.org xenial kms6" | tee /etc/apt/sources.list.d/kurento.list \ + && apt-key adv --keyserver keyserver.ubuntu.com --recv 2F819BC0 \ + && apt-get update \ + && apt-get -y dist-upgrade \ + && apt-get -y install kurento-media-server-6.0 \ + && rm -rf /var/lib/apt/lists/* + +COPY kms.sh /kms.sh +COPY ngrok.sh /ngrok.sh + +# Install Java +RUN apt-get update && apt-get install -y openjdk-8-jdk && rm -rf /var/lib/apt/lists/* + +# ngrok +RUN apt-get update && apt-get install unzip +RUN set -x \ + && apt-get update \ + && apt-get install wget \ + && wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip \ + && unzip ngrok-stable-linux-amd64.zip -d /home/ngrok \ + && rm -f ngrok-stable-linux-amd64.zip ngrok + +COPY ngrok.yml /home/ngrok/ngrok.yml + +# Configure Supervisor +RUN mkdir -p /var/log/supervisor +COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf +RUN apt-get update && apt-get install -y supervisor && rm -rf /var/lib/apt/lists/* + +COPY openvidu-server.jar openvidu-server.jar +COPY openvidu-js-java.jar app.jar +RUN sh -c 'touch /openvidu-server.jar' +RUN sh -c 'touch /app.jar' + +RUN set -x \ + && echo 'ngrok:x:6737:6737:Ngrok user:/home/ngrok:/bin/false' >> /etc/passwd \ + && echo 'ngrok:x:6737:' >> /etc/group \ + && chown ngrok:ngrok /home/ngrok \ + && chmod -R go=u,go-w /home/ngrok \ + && chmod go= /home/ngrok + +EXPOSE 3000 +EXPOSE 5000 +EXPOSE 4040 + +# Exec supervisord +CMD ["/usr/bin/supervisord"] diff --git a/openvidu-recording-java/docker/create_image.sh b/openvidu-recording-java/docker/create_image.sh new file mode 100755 index 00000000..e5c83d6f --- /dev/null +++ b/openvidu-recording-java/docker/create_image.sh @@ -0,0 +1,15 @@ +# Build and package openvidu-js-java maven project +cd .. && mvn clean compile package + +# Copy openvidu-js-java.jar in docker build path +cp target/openvidu-js-java-"$1".jar ./docker/openvidu-js-java.jar + +# Copy compiled openvidu-server.jar +cd ./docker && cp ../../../openvidu/openvidu-server/target/openvidu-server-"$1".jar ./openvidu-server.jar + +### Build Docker container and remove unwanted files ### +docker build -t openvidu/basic-webinar-demo . + +rm ./openvidu-js-java.jar +rm ./openvidu-server.jar +rm -rf ./openvidu-server diff --git a/openvidu-recording-java/docker/kms.sh b/openvidu-recording-java/docker/kms.sh new file mode 100644 index 00000000..47324bf1 --- /dev/null +++ b/openvidu-recording-java/docker/kms.sh @@ -0,0 +1,19 @@ +#!/bin/bash -x +set -e + +if [ -n "$KMS_TURN_URL" ]; then + echo "turnURL=$KMS_TURN_URL" > /etc/kurento/modules/kurento/WebRtcEndpoint.conf.ini +fi + +if [ -n "$KMS_STUN_IP" -a -n "$KMS_STUN_PORT" ]; then + # Generate WebRtcEndpoint configuration + echo "stunServerAddress=$KMS_STUN_IP" > /etc/kurento/modules/kurento/WebRtcEndpoint.conf.ini + echo "stunServerPort=$KMS_STUN_PORT" >> /etc/kurento/modules/kurento/WebRtcEndpoint.conf.ini +fi + +# Remove ipv6 local loop until ipv6 is supported +cat /etc/hosts | sed '/::1/d' | tee /etc/hosts > /dev/null + +export GST_DEBUG=Kurento*:5 + +exec /usr/bin/kurento-media-server "$@" diff --git a/openvidu-recording-java/docker/ngrok.sh b/openvidu-recording-java/docker/ngrok.sh new file mode 100644 index 00000000..cda96267 --- /dev/null +++ b/openvidu-recording-java/docker/ngrok.sh @@ -0,0 +1,6 @@ +exec $HOME/ngrok start --all -config=$HOME/ngrok.yml > $HOME/ngrok.log & +while true +do + sleep 100000 +done +exit 0 diff --git a/openvidu-recording-java/docker/ngrok.yml b/openvidu-recording-java/docker/ngrok.yml new file mode 100644 index 00000000..3f52cb9e --- /dev/null +++ b/openvidu-recording-java/docker/ngrok.yml @@ -0,0 +1,8 @@ +web_addr: 0.0.0.0:4040 +tunnels: + app: + addr: 3000 + proto: http + server: + addr: 5000 + proto: http diff --git a/openvidu-recording-java/docker/supervisord.conf b/openvidu-recording-java/docker/supervisord.conf new file mode 100644 index 00000000..6b77bbc1 --- /dev/null +++ b/openvidu-recording-java/docker/supervisord.conf @@ -0,0 +1,26 @@ +[supervisord] +nodaemon=true +logfile=/var/log/supervisor/supervisord.log; +pidfile=/var/run/supervisord.pid; +loglevel=debug + +[program:kms] +command=/bin/bash /kms.sh +redirect_stderr=true +priority=2 + +[program:openvidu-server] +command=/bin/bash -c "java -Dspring.profiles.active=ngrok -jar /openvidu-server.jar" +redirect_stderr=true +priority=3 + +[program:openvidu-js-java] +command=/bin/bash -c "java -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=container -jar /app.jar" +redirect_stderr=true +priority=4 + +[program:ngrok] +environment=HOME="/home/ngrok",USER="ngrok" +command=/bin/bash /ngrok.sh +redirect_stderr=true +priority=1 diff --git a/openvidu-recording-java/pom.xml b/openvidu-recording-java/pom.xml new file mode 100644 index 00000000..7ba8537c --- /dev/null +++ b/openvidu-recording-java/pom.xml @@ -0,0 +1,102 @@ + + 4.0.0 + + io.openvidu + openvidu-recording-java + 1.1.0 + jar + + openvidu-recording-java + http://maven.apache.org + + + org.springframework.boot + spring-boot-starter-parent + 1.4.1.RELEASE + + + + UTF-8 + 1.8 + io.openvidu.js.java.App + openvidu + + + + + ${project.artifactId}-${project.version} + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.springframework + springloaded + 1.2.6.RELEASE + + + + + + org.codehaus.mojo + exec-maven-plugin + + ${start-class} + + + + + com.spotify + docker-maven-plugin + 0.2.3 + + ${docker.image.prefix}/${project.artifactId} + src/main/docker + + + / + ${project.build.directory} + ${project.build.finalName}.war + + + + + + + + + + + + junit + junit + test + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-devtools + + + + com.googlecode.json-simple + json-simple + + + + io.openvidu + openvidu-java-client + 1.8.0 + + + + diff --git a/openvidu-recording-java/src/main/java/io/openvidu/js/java/App.java b/openvidu-recording-java/src/main/java/io/openvidu/js/java/App.java new file mode 100644 index 00000000..eda169a2 --- /dev/null +++ b/openvidu-recording-java/src/main/java/io/openvidu/js/java/App.java @@ -0,0 +1,13 @@ +package io.openvidu.js.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-recording-java/src/main/java/io/openvidu/js/java/MyRestController.java b/openvidu-recording-java/src/main/java/io/openvidu/js/java/MyRestController.java new file mode 100644 index 00000000..10d426da --- /dev/null +++ b/openvidu-recording-java/src/main/java/io/openvidu/js/java/MyRestController.java @@ -0,0 +1,250 @@ +package io.openvidu.js.java; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import io.openvidu.java.client.Archive; +import io.openvidu.java.client.OpenVidu; +import io.openvidu.java.client.OpenViduException; +import io.openvidu.java.client.Session; +import io.openvidu.java.client.TokenOptions; +import io.openvidu.java.client.OpenViduRole; + +@RestController +@RequestMapping("/api") +public class MyRestController { + + OpenVidu openVidu; + + private Map mapSessions = new ConcurrentHashMap<>(); + private Map> mapSessionIdsTokens = new ConcurrentHashMap<>(); + private Map sessionRecordings = new ConcurrentHashMap<>(); + + private String OPENVIDU_URL; + private String SECRET; + + public MyRestController(@Value("${openvidu.secret}") String secret, @Value("${openvidu.url}") String openviduUrl) { + this.SECRET = secret; + this.OPENVIDU_URL = openviduUrl; + this.openVidu = new OpenVidu(OPENVIDU_URL, SECRET); + } + + /*******************/ + /*** Session API ***/ + /*******************/ + + @RequestMapping(value = "/get-sessionid-token", method = RequestMethod.POST) + public ResponseEntity getSessionIdToken(@RequestBody String sessionNameParam) throws ParseException { + + System.out.println("Getting sessionId and token | {sessionName}=" + sessionNameParam); + + JSONObject sessionJSON = (JSONObject) new JSONParser().parse(sessionNameParam); + + // The video-call to connect ("TUTORIAL") + String sessionName = (String) sessionJSON.get("session"); + + // Role associated to this user + OpenViduRole role = OpenViduRole.PUBLISHER; + + // Build tokenOptions object with the serverData and the role + TokenOptions tokenOptions = new TokenOptions.Builder().role(role).build(); + + JSONObject responseJson = new JSONObject(); + + if (this.mapSessions.get(sessionName) != null) { + // Session already exists: return existing sessionId and a new token + System.out.println("Existing session " + sessionName); + try { + + // Get the existing sessionId from our collection with + // the sessionName param ("TUTORIAL") + String sessionId = this.mapSessions.get(sessionName).getSessionId(); + // Generate a new token with the recently created tokenOptions + String token = this.mapSessions.get(sessionName).generateToken(tokenOptions); + + // Update our collection storing the new token + this.mapSessionIdsTokens.get(sessionId).put(token, role); + + // Prepare the response with the sessionId and the token + responseJson.put(0, sessionId); + responseJson.put(1, token); + + // Return the response to the client + return new ResponseEntity<>(responseJson, HttpStatus.OK); + + } catch (Exception e) { + // If error generate an error message and return it to client + return getErrorResponse(e); + } + + } else { + // New session: return a new sessionId and token + System.out.println("New session " + sessionName); + try { + + // Create a new OpenVidu Session + Session session = this.openVidu.createSession(); + // Get the sessionId + String sessionId = session.getSessionId(); + // Generate a new token with the recently created tokenOptions + String token = session.generateToken(tokenOptions); + + // Store the session and the token in our collections + this.mapSessions.put(sessionName, session); + this.mapSessionIdsTokens.put(sessionId, new ConcurrentHashMap<>()); + this.mapSessionIdsTokens.get(sessionId).put(token, role); + + // Prepare the response with the sessionId and the token + responseJson.put(0, sessionId); + responseJson.put(1, token); + + // Return the response to the client + return new ResponseEntity<>(responseJson, HttpStatus.OK); + + } catch (Exception e) { + // If error generate an error message and return it to client + return getErrorResponse(e); + } + } + } + + @RequestMapping(value = "/remove-user", method = RequestMethod.POST) + public ResponseEntity removeUser(@RequestBody String sessionNameToken) throws Exception { + + System.out.println("Removing user | {sessionName, token}=" + sessionNameToken); + + // Retrieve the params from BODY + JSONObject sessionNameTokenJSON = (JSONObject) new JSONParser().parse(sessionNameToken); + String sessionName = (String) sessionNameTokenJSON.get("sessionName"); + String token = (String) sessionNameTokenJSON.get("token"); + + // If the session exists ("TUTORIAL" in this case) + if (this.mapSessions.get(sessionName) != null) { + String sessionId = this.mapSessions.get(sessionName).getSessionId(); + + if (this.mapSessionIdsTokens.containsKey(sessionId)) { + // If the token exists + if (this.mapSessionIdsTokens.get(sessionId).remove(token) != null) { + // User left the session + if (this.mapSessionIdsTokens.get(sessionId).isEmpty() + && !this.sessionRecordings.containsKey(sessionId)) { + // Last user left and recording is not taking place: session must be removed + this.mapSessions.remove(sessionName); + } + return new ResponseEntity<>(HttpStatus.OK); + } else { + // The TOKEN wasn't valid + System.out.println("Problems in the app server: the TOKEN wasn't valid"); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } else { + // The SESSIONID wasn't valid + System.out.println("Problems in the app server: the SESSIONID wasn't valid"); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } else { + // The SESSION does not exist + System.out.println("Problems in the app server: the SESSION does not exist"); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + /*******************/ + /** Recording API **/ + /*******************/ + + @RequestMapping(value = "/recording/start", method = RequestMethod.POST) + public ResponseEntity startRecording(@RequestBody String param) throws ParseException { + JSONObject json = (JSONObject) new JSONParser().parse(param); + String sessionId = (String) json.get("session"); + + System.out.println("Starting recording | {sessionId}=" + sessionId); + + try { + Archive archive = this.openVidu.startRecording(sessionId); + this.sessionRecordings.put(sessionId, true); + return new ResponseEntity<>(archive, HttpStatus.OK); + } catch (OpenViduException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + } + } + + @RequestMapping(value = "/recording/stop", method = RequestMethod.POST) + public ResponseEntity stopRecording(@RequestBody String param) throws ParseException { + JSONObject json = (JSONObject) new JSONParser().parse(param); + String recordingId = (String) json.get("recording"); + + System.out.println("Stoping recording | {recordingId}=" + recordingId); + + try { + Archive archive = this.openVidu.stopRecording(recordingId); + this.sessionRecordings.remove(archive.getSessionId()); + return new ResponseEntity<>(archive, HttpStatus.OK); + } catch (OpenViduException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + } + } + + @RequestMapping(value = "/recording/delete", method = RequestMethod.DELETE) + public ResponseEntity deleteRecording(@RequestBody String param) throws ParseException { + JSONObject json = (JSONObject) new JSONParser().parse(param); + String recordingId = (String) json.get("recording"); + + System.out.println("Deleting recording | {recordingId}=" + recordingId); + + try { + this.openVidu.deleteRecording(recordingId); + return new ResponseEntity<>(HttpStatus.OK); + } catch (OpenViduException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + } + } + + @RequestMapping(value = "/recording/get/{recordingId}", method = RequestMethod.GET) + public ResponseEntity getRecording(@PathVariable(value = "recordingId") String recordingId) { + + System.out.println("Getting recording | {recordingId}=" + recordingId); + + try { + Archive archive = this.openVidu.getRecording(recordingId); + return new ResponseEntity<>(archive, HttpStatus.OK); + } catch (OpenViduException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + } + } + + @RequestMapping(value = "/recording/list", method = RequestMethod.GET) + public ResponseEntity listRecordings() { + + System.out.println("Listing recordings"); + + try { + List archives = this.openVidu.listRecordings(); + return new ResponseEntity<>(archives, HttpStatus.OK); + } catch (OpenViduException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + } + } + + private ResponseEntity getErrorResponse(Exception e) { + JSONObject json = new JSONObject(); + json.put("cause", e.getCause()); + json.put("error", e.getMessage()); + json.put("exception", e.getClass()); + return new ResponseEntity<>(json, HttpStatus.INTERNAL_SERVER_ERROR); + } + +} diff --git a/openvidu-recording-java/src/main/resources/application-container.properties b/openvidu-recording-java/src/main/resources/application-container.properties new file mode 100644 index 00000000..8a4b7c07 --- /dev/null +++ b/openvidu-recording-java/src/main/resources/application-container.properties @@ -0,0 +1,8 @@ +spring.profiles.active=container + +server.port: 3000 +server.ssl.enabled: false + +openvidu.url: http://localhost:5000/ +openvidu.secret: MY_SECRET +openvidu.publicurl: ngrok diff --git a/openvidu-recording-java/src/main/resources/application.properties b/openvidu-recording-java/src/main/resources/application.properties new file mode 100644 index 00000000..a5cec57d --- /dev/null +++ b/openvidu-recording-java/src/main/resources/application.properties @@ -0,0 +1,9 @@ +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:8443/ +openvidu.secret: MY_SECRET diff --git a/openvidu-recording-java/src/main/resources/openvidu-selfsigned.jks b/openvidu-recording-java/src/main/resources/openvidu-selfsigned.jks new file mode 100644 index 0000000000000000000000000000000000000000..4a02ecc47be43f930bf2f9af4d4068880670f853 GIT binary patch literal 2268 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 z z^&i{7;OFL!i&WH<-o?MF$|U?hxcu7wWwjTU;e#OEk^iAfw|%th58DIf&uq~6m3`ll z+vv~sU(ws|L~J~V80GI655oUS{H_4L!-1#x4w~zmNelgx=yl(OK4W2E0;N`2gZaB-FQW#Z2Y(}YtARXVOz-?$ zhq`ST!m( zi)i-rQ~rkcXLa|*I`Mr#?Y$f-H}m%b?o0kRPC_@yT2a&0b85DL6Me7fyL#Eb=7)Yt z<+qnctna`%57RiqCFc1ItiTf3xEV5c5b-Y7nuT@a!Z~{y<30WkGz^lziwzJVMc>6e TedKQfJ#jzGxv-xC9?I}vocwV} literal 0 HcmV?d00001 diff --git a/openvidu-recording-java/src/main/resources/static/images/openvidu_globe_bg_transp_cropped.png b/openvidu-recording-java/src/main/resources/static/images/openvidu_globe_bg_transp_cropped.png new file mode 100644 index 0000000000000000000000000000000000000000..e0309e62181608cf3543664ced79b6355779533b GIT binary patch literal 11746 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 KVuQR*wOeuWT3;&BESMc5c{Qzs4Eae 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
6<-acu z?(RFb6(TP*7|u-mcSmArh(i;&t{1;(_$pdKICVPgw9-%(o>^j06y0uHlu~t1S|FtP z45uAZ|7hi6SHJp)D?B!c+my;W8dZ%oGLrs3_3bewQ${ywW0SrJ!rdBu zFeqY%GT`Yv8tVSaV{O!NZGBx%Z?Nf!sYY7eRF5_h`=q$B(9h3Kot&JUP2}u58b@VM zxumEUHX6%}`@aXUchb_`-A!G4;1s15 zs+irRTj79L*xR{g`(c=_vmy>*%7qSseW zC|iv?J39jtJVY{Jfeb4VvAXX!{iokwm+3jT;ZmsYVLrO{@&c5VEvhX5iq7nb97e_IK&wke@veg2bs&7YFbM2^(doa1*Mz|RNyay7_@ zY$bjoS+Q1&_wzn-A1;1~i7&59@#j#BM-lq6 zjpx3k#4lu$9A)R<{pgPQ@;?RG8`$d&LLpl*QZXw5jg0VdZBuk=^EDj}ZXfa%h~$G# z)P~$8svB$aoUP?l7tM&~jx5U$7{r|j=4wp_uU9^DbRn9n`V`$A%%wJ}{)l%a{}b42 zPB#J`F?D9?LghdO_ZYwnG2pZ|S#4hQ&@DOs5aA+?dE-wjSPGKR3&sq#E$!{?PnsLme)D{qV;bww2S=(=dk&OU1!fsThUNPE&P`59x+hzIAr8zFv6ov*&1djF4o7 z*2|1R@r5(F(xlBM;mku`8kQeEy0=G%zdd`FI!H0=4fp$F_#}TJ0T9>3Ps^i)RZde! zHK~49B2hUdD@6tn7RMfPpN=@xP>rFxE|bOQyDd{Q0K@&fr2)k`y{HxeSNh!irZI{zNQ>v@&ZpgNfUY3*4Y^Tyd`hvnZcsTd(9 z1_sMrjRerqd|(eL&41<-QXi-`<;&5-xp4*`%EuleQz6LhJTKK~b-_OUL1WLMMNhj0yI6EKiHgL!M3RRptet7?*X|ZYjo{n0teB3W$#iNw8 zXpIMZ3#5&iA;ABcuBr2Nnk4*7sD^!Y15g=zzmy?%2Gav16XQyB{v9wW5 z9#=ruVwfI&RC{D)qZ&ea#=bUmHo<@L9|LpJg4CH$q5cuI+OozGYE-;8o;hCd(}-O- zkJ>*BY>vspv?uVg?{lmDOR}jl8hqq&pL*OeUf!5LF-ARp@v~s6*AG|(e~8%q8uj^^ z`BxI+>z+iOw8fv<9UcGC{dFLQd+;06Jug})hM z9psH_Ox{hG&Zv(Scd20|qo8o^_R)T*7QgsTDrV;9ibs5jZe!IN=DMkcO=mdecNZov z)27JM7McY+QbSx|^IC@c+t+&OR0!VXHZD_|oewzDP)2Fp@l9F$O*l2DZ zp3+RG*3rZXzLOW<08qFwbnCPx@2;9#gVxT@>?a64)Yc|Xb3jh&^u@S(wHRhPOEKU5#@BNjo7(XqHZc{SOa!wyo@L~< z%9DywDM~5dempXK6K+%$8inY+_0GMeN5!7*GLNOaa=-*0=(10-xgcB}M)@w{oG>#N z%oI-LMzVT?^;{X;g*(b+?N7$aO#8CBw8o&u=MvR7DqXoY zo`)b^F0o&>Z;K&T$Q+oNQMf-CRNsUebgf*WFc7P6n<~9GwDTR#Y2S*H0_HDP2Y+9W z6dCrHV%9d@_xII(Jh+{I_I!vhN!Y1;R4gGaFF&oN`o!Zc?q_B|ev@M3S(W!>qMFsZ z*gY-Jd1P((JbfBFGeST}=nD;ully*$7}I58K)}zjJ>c_Dfb^g}{qdh&CFtr8-|barzp!9AYSKUR_?hz@pZ4WyBLORd;nOqz4qnB&z>?TduY{vOdaoimipL` zmxdp@zoxFb_nsAycXC+yXq{h;XZ@F+P;z?uNmqM2vRcBd4_Rw+_A&3i{btpT)4T_~ zpBVnvX`E){n+TS^b+66y_B~<}^L;RAr`=%R2v7UmqS$~j(Y^Jt{O)BjFT^d52UsR7Y^w909R(|9KliVE)DXvLbyyAiF*t`;nlCD+ zV@T3ACUIw;oAfj}Po~$QA=gJ`&{vljrHEHUJ=71%NkB=UAfYuR*5mMj;W)YC55>PPd5k@OQhgd4-(6L% zwZtuMSP~zGW-L0@rPYhE92Fxy8}9pQTvKc-gzO;&6#;q^Q?s+P>C7^oe)k4duQxoE zq-fF@>{KG+e2AGUHYhRiMyL4S9kln{{^_`J)?rt9#HY=eQVSBIuV0~^pWP_hX~m>_ zc%9=qt&pF^1y6eGp8R;1xYV1re_JiEL=Kz!S59qtkR<0etjT3fEiGow6?!j)M{nwP z!teRi+MHE4@~;G_?bjX)_587o4|r5G5}-bYS6I$a2nt4FF&X5b#>g1A+k1u^+e>Qv z>Z!U5k}ADDEcb_YT*Q2br&xJuqale$B_Ly0Hubs}JU{{Cs!uhLpvlalJU|sso^iG> zD$YRNo8%spcUr(25XA69Ku=u$;{DoVS~2YWMy!gCdse-(>%N&m(TGef+k`JOeZYyr zkTLDMd(zWAkBe03Mbo_2B-QGa2DNl(PRkw@JI%&E+?U$?y6q$3Jnd%Jd*KKYU|_U2VVS z*oa2C&4tOiuWs}!Z_*D{b)Teqp|nOsU|e1Sm!tds8f;m~+iC?Kp3jCKzH=X|INNsa z{llP!>vDP$EVpDq^qaH0h7tO2=ZaXGv(5I@sj`j1^ZnZRo*vJ4D5T;K*OUe9 z5$CCi`F@|OzBeJ-Fu5=9HDhh#)t@1=znrN4tMKMB0Rr)_$V9LS-fS-Kgo4(Ps``h) z+>Fm&tcX1Wk+lm!+L8@)enbCn^K7=o=>2Dm=44=Su%2-*?MRq1L#*Oy;GXj9ia!{D zpy8VG9}vyJu+!}aBbZUt`+*tEcp~+X9n3gkdWav)n2_Bf4`wJ_=dcGe9M%ceff)@k zqXrG)Fv>8^|NIf`K1=5xjbXPhJ^3hizRC$C((ugwG3XvEMXL7^Gmq-i@D_b;~a}ve)`vTKn7L%;ZUS^S;J_q!`|w-=xQIcjf;5 z{}VjTcmF<}_TkH{CB{x1uQ$yDr@aM#fqG|lJpS>}#Mgg9$>}(|(rgjeS{86JY_N4b z&!3V8+}=2uUB2eS_UC72ewH?l)>-+TRc@ZwE|acBo88^r-=El32C~ZGdBSb(TZcY9 zJq+52FuU_*S>|c-;I9U5>|3szvwwmfI zvVmf%C9V-ADTyViR>?)FK#IZ0z|dURz+BhJG{nHf%E-jZ&`1}^FfhnCz40iDhTQy= z%(P0}8YHK2RsuChf@}!RPb(=;EJ|f4FE7{2%*!rLPAo{(%P&fw{mw=Tt-R!37A z6CCeeq>WW5UbDLMTquRMt|&C&tCrYkhDd^x{BKjQD_4q%gguHI3!7`e{oxH1K4j>y zyoq^o8Qp zL6C^EaY?EoB3tH@s~YwUfBhf|sdAI`-&Nk#{Q|7<8bQ>W{h5LW)W&Z>x z&-M**i&BY~@IN(3zoba5kDnqGs$Bfv1BnDETkLa>pNr?8N?NdJgUc={mEFh}z&|lI z<$L;{sKuG$&>!So+PtpUMHQnw{2pg9lM!l#Di{810$TQVC!Go!eLk;;oO^aypy(S z1^-vO+%g>r)ZRl(BVx*FILomXq4m{O!wF+?|J64LTef}CBk)#w+v=rY#=h*MnY=6& z`v1u`PB_&ZkuD98e72=JrLmU2-U= z`LAxqufc~R{c@dgfJmK|F6Rr)_!9nmZGrwsg;mn*=7t9-+qmHxOPy?jW$6ZbY0SuE->QDGcZxw z7US)o{$IBPFBEG4uVQt6{PorpPPpp5zEzvr%pU8{|t>6)cF`b4CZGTZ-J4-o0U@%OzbVRJgc zf3MB_XMpL%a|R1txG{~$b>ly$$t|K1N|ou>V(ywQu4QqICm=j@80NdLbQ_0`uGXf z4(k9@&|D^WmCUTuIJ+tq*Z?Rt(Mh<+1moIno z*CU-o&naPHyTcuEe27iLaUX2|#UsaEG}arNWOL$eHm3yF<#F;+T;#o&Kd#UMhT>Lbs=G4q@p@h*At4R-GA^lzHZjFnzOhxE1`4`$YuWm2_& zgf-*T9QjXn@SDnaD_Y90s_8e7Dkp6NY)~g0K8ljJ87?I8%x5fHT=|;Ns3b>#iP!ax z2Z=GpjgIYs(W}2&CDUKNZ&&ls(#YA_8UOhW6EWDAtY76|urec`F~i4RE5@!IbqX!- zyAH_IU&Sbqhu)0CdX&@M4zZ&#TJ%%J5mj-O6(7P?7o$3uh#l!DlN!=?(r4UDaQSEV zh+v~WSHeskJ$YJN&3||236lX|R%qFl=;=4n^Nu`j##f^4=t8M}C%({wQ!T`0%NCsF z|I`vcLl}VTo0vv(1CkZ9Jq(M^`GF{6fzu6+g?pY<0tD>?vSq zl9CL(HJ*A+^G+syN<}u&!ky?Rm5WljLYh(^PL|Ml2r-n4K%oH})_KqVkZ=moO$$HL zTnwKZygf^enU4`0{v{#m5PGd|rbttWl{I7hx6=Hfts`A2|IKHc1E)CFfX~mAr`3^Y zqAC_s!q3Wzx+)B1+~+(#G~Y6rd^4;-2s~H9tZy4vCpQ_mdOChJPcC9%Y#vx!26ea% zrnwJEQkEfPSD&)Rf}9cs5Z9ugqKYTRcThsaMMNm$C0Oihe3RfhnfQ1&QWEeX-X`Ky z%|WBRn%H|wR)E%e^91lGh%uUXyl^KvYssS2vN+XUIXN_4oH!5Dr2}1II(?nC5-?P& znq-|a_-Es@xPnaBwb7}Fc!9qD?7X*2iokeFE~yE^^j~xkJDk?E#*8;4kdUjMVNv;? z7;6jMVJw+3cXiy;fUaP}_>5}dg_1e09p;Hb{vXLDr*^Rhe2)QPE`G#)qMFbRtrI+K z&i7X)X|U9K>Tu;_m1Sk!2i`SN7v$NsV22T>6~DNXKW~UZ*;c)C(~lzphvfJS%V)Bc zy?;0V=P4d5tJWXK0rT!EhI&`Op=$=`n99_RE1(`f)2aJT6|#$anVc{sy#5NG0V^e* z*Y&vx-)AiyO}!J{UT2cVi38W8g_i=vAwR2 z&Z|O{3C#)Th^~Nh;n;$~ATg0DS2uKrc{}}vD+Em*+z5t5;&HA%Uy}@=FTwq*Cb@|g z5mf~$=UIake)Nn?moVS@+aFfUqDc5zUGW2}mY^(~Rl`m+KVwi$ReeHT}dseNzOyX5k_q=08Wn7%b&- zZmNAhj2u%=mtnAR|1HFV<)+T4ITD;$5!nka(=|l9t$~1s!3C%e277^#-bdK|^1eIr zaHk8C!bPe5Sl#lzD?;9X+vh9I|6ZImzBoA&|G%M3s!AP6GYZ(Jb%lMkcZDqg(aztt zi?wQG5!oi>H|9nimz@3W-kJQJ$oA056onc-LUhJh{JY7xjLpU|J)M_e@3G0WL-Rzz zQFYJ5u`7RUJqXp|8m4J3;ZIB|E(1g33z|Qa-@35s$n_DZ z2Wawfvcvt|5@3zo-mo5)Ls$P*`EQ`*uav3pdTW($eMkOlSQfY8I5z^U$1rl1Q_4E& zI5}7Tn{Jf0p^j|=63p~UXA5`^r`3lYWBuEYH$$m@v&^*iT_A}IBPVAekz#v-I>r1z z!?(*;pF^L8wIad5+pCr?zlIbYcamn-EZ%f+<4cRyh05Tn%Y_+ zMO&~G3EKKx6)L&?znTm=_zLVZRtE`szru*ib@d*%eDy+i*n<1+6o(UtglH=GR;Ef8 zY(n*K^sy-zdB0h$7AzCE4|$$m#%Oj%#6xq7S{fw%$_B@NE2C+NWJEnceT%-ZF%El_ zK&O+Br6deb>vXSdDnlrOVT50^yG!>Ic9){C&fOG6K}sfSIC~2uJ?gkJfJXQWO$mVP zGa@czxO!&fdB7a*(QT4C;_k)0N$8rbgYCn<2ai3*u$*~9bG81|AugzZAKO=WJcGSE zcdOg;G`d@v^0rVEQ8tLPNEfArD>^IA`C>oabb38N?7ILnI_|}lmZd>H$l^1eUvNBk z0OF>zr?nq_vG4{63Jg9FqGf8uY8mETy_9OtfAxaJzQ<_NsL`r15~vAoFbj+HI=+@j zy7_2c=1O`A>hnJqcuBMei-S`S=G2`fw!zy^Q6@&}X_ndQvUcYt)hM&`_+jkj=ne)o z8UhP}iQoZ~F5!0*4W=46r5)JG`BEXF-gX5Ga%mJbOYcD*PbMu#$Ti(lq;l z$fba8HfI5|z_;i&*uT+U8M*6$OQo6>_50Y4H9j3%BEhLNWzoFvpNi4KPcPP9nvd$Z zG>>Vd-@;I$u^m_@EFWwf718c7FjN?O6?_JWs48=hFE5fX?&zak+>Q*nZSn9ak^$ls-znC^aw_Ut^Jeb!Cz) z7-01(chGNuae>IjZIbg{LA2{kXSVATqy7aa}`f8FaEouLT{cQ!Plf_NRT!p1SjbvasP_Q-cOW z|JVkm9gdksg?t#kQM(XZv%|Mi%~Cjj5Ns8^OP9X#;PHMDI2ku&>~ut-5*KA$2$)lw z6M{sF?#X&9kTj?#1t#Nsq-Gq?oG|3E5N4{s#qS1@sjw>ys~ z;xuB2$hEStyYya68$=SksL=tavrI$ePJHkz;5^~;0wYmN%O zi!$97yC2FIQ2pPqTl9@gGiH3o4jziheIQkf!ri5d-Ii^lx%iOs`2GQ6AsF{yVEr3x zKWHsjPHDLWvC@CqEXQw+!--g3@Rgo(an96xMRj#>Bd&fy+#45E+A^v9?V0qt<2#ltACTt+6hSg{UNc8sgyCtSt@<%;a18B zzWz1f0Y0J^KT9Tf+zA`ct&Lh|g`XOQFN_!u(Ymf#ZETXF%~^`d>RqSk^ul*17;g=Q zd^=kktuS6XN5ZgXNnJLYbZxujXJC+J|ARD8%q)`FJ`oP=gWGi;7W{^*R=oDsK#W2n z2fH*nBuM_mm~9>c`iP}9sQi|7>#S>eA{hA;!xBnnXZYr^UT_(e$@>1M<|=9S%eYSy z2Yjng9Ut*%xds2EwrZt|aNO;un9zjeaF0Sh$N4mM;Sb~35p|?a-!tKCqe#DWl7KV%?mmL05>gwGKspaHErPVUTyd9jndp36+Ye znIlb5anTqRr-_z1#Pt!6DJJ3hFUb+5v1?ePm!5vRq2x}*-fYBg!V? zLrxhr=PQLfyMILkp~NeLl6vo)bQ*msligx}g=Jw02JQutScRt+?@guPlL}SHF=OGIR=Sc+7A#7CTrG=GAu!AK^Tm5whDLom^jg& zqY4a7wW%K_gmd{C(|vN>tr>p%G4>0sQB3~QpQhfuf(BXm))GlmWaH+j;rh@xh!jQ! z!cp^5KZoBo300>l{XAt5X&0l->4*f_Uwb_EyU|<@o(Z+hgPi>mM z=?(w@LxTHau-xqEy8`a>d0V8|aPrj5d6=$&zJBOPcC8$mv@b*|J@SD>ith=&vf1a0 z)EwL)BPRssjNzxg`I=;N4Pj{UmFOx(Iu?9h*^|Pa)zr;lp$=bl-rL21SqXDK?=l!t zG0oe8&h&9~hq#|GRpzK)+( zO&+=)K=ayuI!3*RR2}?aQqj? z%sK6FoU1id6D9om==)>`di1AdGd`nUOS+RB6?*6`C|mN4*Keg0rCK=5&TA$YG83QC zMl|jXC5|Q#jzbz&vNf?c67uhkL-`E&ZM42Y;t;6xhZGeH@p|JU}lwG>^6!6-D?!wTp_&VZp7G{e)qARZS+Fi!H)-0e2Nws2x~0 z$-(5Q&BbL>bX>G++f5_?`@v))0^&8u<1Z94mh!j>{N@AS@!?GO^iJ=U!uhf0ng#e4 zp(oMdn|Y$}FU@*k1upZ=hue~KVsn?AFUv3-2&TGRka-@&s-Z?Hf8Vm!j%_4$W}wvV z=65~|W1e?$PhJ5uB6*JRvLmpjlo@7PpD$MZc8c$|2y4?$4C{kS57KKt_TKGQXgo&f zB6{PN7<@M?+MxDNpI^hbKs7>mFKC3^o6+eS>{}U7WY}5(1B>Hkw{i%phK7@6BMDCL z(m$;S+c$sQ=az=s5QcZrPTuh3Dx_|rsWw#4vf0qShRB=XgK?rSmP@u$I1`A7_Xf{# zAb!D%kE3}Wusz5Oik2&Q{&UUj04Hs5z;7cOxbP1@#p zt1bKCz}e0WF%9)FYavhzg(uxI3N2lA-7R9ZUvE?klIWJBGGtyhN_Y{R;*zHivON*x!tRv zk4?#_4yzGaZv%z(6(4QByc^LsC-c{AwVyo^Y1SlrFQ8z zAtJ&5aFH<@F9lL3r^~o?7n{>^wDym^>)m^I%!cFK7-;W#ronZc&pDfQAKDqYgI^)R z=Iq41D| zvUjolYk_{}Hdr={mARw`sA7lNge?qJH0n(I)3i{Ig7)o1;|Gj~T5o|Jj;1qB_v2|U z#Er6*8p9U+jLI}~gF=1rxN^d|i5sD;uy=Vh_Lp|yzOZlfW;eFzV)BLIO(GJjQ_1(M zQI=;tK&Cu_-}O1Mjtd@w@2Fw!*^U#`>`R%U6;g!ooWVJd-R3mzTgjR%fb1 z$%D8`DYG~!8dK5J%2xmk@um$NLx^VRrsPcMbhp|^deuZk8#q-N>(IpGC?^#D zMM5HX*FcK60R3gdoG>9|st?jYIO``Q!AYWx>-16#H60WFva z@L>;oqvyWZrrSL#99Aq^_&f zdBR={ZWux+)GnWf7_bR!pX&Lx(QJR7{UGrrsBn2~xbB{Hv0E&`Z9Jbm(_dM?yCe^5 z;&Smh8D@YyOKG|iWX^EB%tub_5vKja)|6C}N|R(qlAXeRIVkXh+L%)$w28$<#4~;Y zFkTe?v4`;Q!HtIy3hNu0W0!=GX9gcb%dThIz8`*+*ExBjR(oVN2|r<4Epbo2yRM($ z{ag1BBB-t_4|QChat=TVzT-NLS`JRxgM0tLRxZG2J2rylx`~=hNADA=MOoQQ2VUW` zaU1)7Wl7p7{4s3b1ehD?43M;xrff`XV?sR2t1t)3OO{{+Qn`d}+Y|6T0u;;k0SkVpDk zsyYl|tcW{2{9|>A!uLN?wQe7xJI_RYz%|`K+g0!+p`x8(Wo%j4la$&}%i_M!#Ou(f zKbx<`+WZ)JYID-Jp)zY=JV00CPU_^?K7NGhc)AUytiTi+*JM$6J6O2Py!Y}gV7t8H z_bm24NrSs3=|>sPiT=DIdg~S5_ukW9+>AWhjR74OqrbyY?bI5HZ`54=LR=BPJS&v_ zxZ}K^FAM`S8oBNX+d|>*0BEQp2jRG|p1Qf;<8f8GWXp5~eSg&pbBPrQ8jjnz-M#;f z%!QYCNgf`(mtM{bzp#c`Y_v3KQl5DkRDfHDLNI?L1l_DLjk?cL3}{g+1@wT$vjLn) z4jxXARz7`ko!MK%5NTj8PPTh`F6&6eElV@YVTBi^a@qS1N#nVUeAl~>8TUDH{NR*$ zd7mfj^z1lYjD>UaE-S2j?1KP3#_Hmd?i?D{WOc7U!v=*v*m&X}JvTy)DWK!dKOQU# zrFQAdDYB=pguy06`ME&&^I5~xvs5W<^G=tQ)H-5 z3lbuuQOC+G%+k{w*%hgQ3cH z6XXU9fOSzTP^B0)MUN1hP1G9RCPzNfL~|jS1~0X4 zl&w4yKtu*SjACEdWvRb1p{vdThJ^~hpE)b}4nr6B3|IMC^z`u!^Z>oxP0mKu57PA| z?3p2Cs*8%MpBNNl3u~q=Tk(&lwG#Hox|_%y2e?!DTAjNYI9A`jt~Wi3K57V;l6U1^ zi^NEy)V6_^LjjVn?@KEsXzuf)w#b)3ol!Eq))C#fY7xIngsDJuQpwST;|h(s2@yiK`#cCdY}?&^@nDJIi3T|kl&COU~> z%|yPT?*mbZnH0$^K$3tm3*5!g={UeVze`;mbyr>YJAbk6qL-}phv|!*X4g!4E7%WQ zEziB#E~?a(MWgAbRk>u4q% zmUp7{XIA$wHrt!qJ_UTBuN{kRCMD}swoIyxD_$j~@>FzFP<*`2o613*e#0H+;dg4o z2#HMD2G=Gz++_|X-)J%+WnpSSQ8kF_QW^}(W`pP05HRjo%ZuoH+ngkg_wOf(9nvn| zc9s1J!*&)N4svKX{T9)JHWcpneSnW}47rHT9ej&r4$G~R7qz)ER~6UH_>*)S?gZY; zK^P^grf>WtowMX?z|y6#AI>$45&S~fF#OC+@`lgD_tFJ6 zJ%_(&yP0)NUI-o$F&RX! zaub#oN;lR@2(wDPFOSYPPZ!m*wEpvGEchSZZsIXN6W{R2SzS1F6u6c*A;Hp>ETvCn!P(24xqGkSwpxJ zXw=C3Jwiv)A1U=afD&sfJM}Ff=q{?*w2jg)yGwZl=AMfq_R~bG3Yi(cxW`wgX8mDi zcew*0s%Mgj*H6wsFjw|>xWzmB@U_2_VdJ`5b?kmQE!P@IZp=Su4dH8=gV5w`}&0 zxynbaCV=nDMqi>S2`0bk;o6K$tL=3XSK>K{cRwvQF~U%&x2>-b^UO5$P145X(rFDlykxRgjm?)It57p z4?q1J!2ebkIR%34Q_Z)%Y3e1G*aBwRLM15fnMI=DUXyh2N;3;RSHI*{yFz}|(q4vX zk1TH|ZKjv)d9^PF50DF$2`H0+G^ii#$tY6KW~XbiEA=g|GKrYu^AT4H($@(`Ct~_E zHuG~k;$~PkHH-PtB8+aZ7jc0=3Ac;t{@BnJ(x*Ttc={pbCoA0PX^VfNC>2*GpJ(bM zy|qG72Tfvw?Isrl6Mx|FrdSuqpqO}D&py6HU=0xvmXz9O=ufxXe8O~sSt8!cAof&q z73NNoN%jy-$0E0Q=JysQ<@(%wLi7nzn~>PDo=k_ZeAT$;1Pi~kU6UlWOdBqyjGG)L zFu*ufjjF=yg)O-B!`UPKQn~wfZyH}&eA6Q=9kB)yge?yW4_Z5`XH0JGbTv+qH;mIj zzu{m&Q@d-UPnA&5{FqLYlB67IOaZ{3jqldArmP9BFA?>dBwy+Z{m>naHw92}mE@Kw z>f<<~QHtdLBg$t^I~b(mh0t_%Q|A~_(}ds|aJhGEu)Jc6y;=R|3NbopP3wXab`N_a zejqEhhvf6NL_z&IN8htUsh`woX6kA6?wH?4Qel^o1xWDd%YvLgJTKZxOPO!2t?p)Q z#=5{HDSes#=c06VxZ)92hK$nt{~Bf0wAZcnOK3M2M9s{Y+NYV@g^d-;4fFW8P-ui^QoXN>$!8`9TmkuP6G$nMmKry`)LyOoWqbt?ms z<}8BZh7Y}UxQ-DWhUaD5oPGC|U$myGdltTm0C^1XH|1rkFhh+1tE56Ui;2_hh%{Q0 zDSkqT)^OfTl9IwP<~7MdcxluwkLb=rk$(C`OG0f*1Gt&%D%C3eDT}=l{y#wql1i01 zU5~Bed>PZqs-=Vi@OtxTXuU^>tlfDh0<*kez5m?Sv!6l_kzjVrV(CkVfchl^jBcpx zTSQ&si=2@CZ@{)@jp{Bq-0GV5{lClTVfd6%c=V23X(X<(w4v4{N&INs)G1{}ufbuE z$R(vzFv**Y{`;~ano`{c>5V6n6<2F*bhtcU*?8XB8AG8us0chGy-$P_8d<+87Ih3| ztD{|;LX3Qxsibup1Xf8ESr;bwZyM)U#J<8;2={!y4@79SS~^^tzfoPOwNH(vUILRt zF5u5xutGHHjN{g2fVog!VbSUAuL%=ke<}gYUU5+|r3&!lrK01#W^w4Jb@WTRDL^;ObGx!G zSX9`?-|kVZ$q}|Q5w`0L(_K>n^8x7A{!H%9mBh|)X4Uqf>w#gW#(ZgGcE(iwyykRH z!jQ;kEv`u234=+cB7b9-URbD$&U7YGz0_+~^iPVH>L*;m_3a$F_%8hhJ`zdS3Ei6~ z9q3oaa{+JOnJCnjq&%*xl6ce~jEE+7!0&u$p?v8X^m~wd;J-Ny9UF>;?Yjemvaviy zWuWpn|EErhLT}k_89ZRVxcTIRD#SIV-iSB3739^Yt*A)zu*|IQ^14|N`5~g@YFkVB z=lIbx0V0H-)@eX!l6kwQ?bkf3|4JA++$ey`Soq=xzcG+A^amq($Z%!g6T$f8mDS^X zX}26ansg%lYgowk%w$$e!Yt0U`B)wJ%o1qI%?SxtjafdWHKzMh%&hai3~>CWTtiD+ zv%}=s_JozP#!x;zvD;1K3d?#JzGmY#rUTeeldj`$7SU7OCuk4HJwFxLeilYkJ4YqI zk3I#8>^WjOFG_mU!T0R-YcN!SSFrTyx3!)ThGY}tCd+6G*0ybmO)&?HD-J$azZ>X8mlquOC=Q)j0C;dp>+ z*7U`P@w^s+^PLLO$Orm5(?v5F72-i-yvMl>UvA(zQyFx&g}~D@u0z@4FKg|u*Q7G^ zFSUnX_Y&XXL%d<#?90Jleaw#<=L#VOHZNstYLJ?&ve}y&S}~eYPb3R9QJanjwCSb~ zg~OCa^RfVzP_@&eVb)UQvTSTqm>a8WK-0AUv)}p!NnUn$@4F?B(Y+bO**QC@I4O{X zo$n7d(I99oSU^~u2z9n@=m^VX1>*MI+Qtak*!ayqt$`E4%>ZKwT;5mO{$)n`v|zA6 zHA7WIJ^yc98!t4KX2KW62vf*!k-U;>i0s*TK3dHsBisKbXF(lZG!wgu5=w6#%4Yf! zp7>CqC{-oeaVX6%*4fw%?sRcd3Lsx3@J$uVKGY;b5aD_1XRjz<_cxG-f|IjLyFT^@ z9>;feMyfj8c|5LrBEC%hn>hAC^fz;@HZZCVzxxQay@Uoiv@yQMJTX7tP{7A zpVSm)h$LvY9NJy?q-2mfQ&39|j~Xjv)l=n2SJh3J{Q9H?ouIdu zNb=pas-fhl(?KKay;V1*1>!V73>E6NM>OqbJL4u(+n{MSdNQ3Yw?^)|e&UNpXK@%> z_MZB1pkAgN^5#7Ma}#_wao3~4&l0DcLA-onWFPx^V%$9U6O&*pQNiIVbQ<6mT$io$ zWz>vax3!G;b1mj%ywP}XXzU7f9ausBE7BiwcngYrz&-8o%{I*gozM9mQa_Tz{R0lB z3>>ni8`eFU*Md7GzTg)%6G0ofo5(Q$VMuCmB}#uSm>&7`O0>v-##XILu=I0X!5Kwa z$>t36=t=o!vmGJqnz0lfz=*i41r;|ACV5Q{t#s$q^6PsL zm0`?fDjHY$sj1y&cszTB*d69Wb){j~@6p|c z1zch3lFOi|aSsHoCE;-{3#M>kk(=FOk)(yf?YznhZ#ags+=kBXvtILqyfd zJV6F)g2f*BeE1V=!4VRZ4pK;YkWWrB`bpo;G14Si^8(=ktY>lA>UNg1T+*_o?u2N; zTIaM@92W6OO&^IJe8Y(!`<;5$H61@DVvCLv&Ww{lwH%w{_elD<@5@sFSaTDwSkj4lm-;3CetV0_}z3YdYLLya) z{BdbIgML*>O|pHFY4yY1s>-jVEG&(am-r^ciO088XD&80z&&3&8Et)E-3tEcyHdLk z(Omq(z%n;AZ@4xu{EMre=cWO7L$3VQDUD2(0~}8|jR9B$`pZ~Lc5Er|HHSLGW#&o` zn97j(tIDCCR$!URl*Qtj7-yt^$v2FNIO1B}KaPE{0ur@?0n57h6_Ogu^(UE^Ev}0% z`b})I(Q^d&%hs3)4D%ej!Cc^5#7i#@dZ#Du|4~(xZS}QXdy^9N2o=^!`L@{QJ(CyY zHfq`g7~E{$<}d;gS4pgIT-RxkT9WUw=Q$_>J4}hIi#2p=mj3o6c6R zF3)yxU;5!>!I#U)9x~*}ZO!xmyeD|Q!9r*HI)B>|3OY(v$waW%in{kD7reU9?bB+K z+UlnroV>rP5f7Q^c$QhH@k$^aqs_qPeU?S9f%t_u?XCJP11rS3DPX9MK=~D_AX2K# z2nsQ}gW!ibMiS z|4b>jk)2e4T!>aC!gFD^vAO!)q!}b0yY3v2q)**$eLUgN3>Y!a5Zzbm#T@#w%)?D2MUE{f4|lu zRFryxJBbtyx8jv-6a#!wq}Y$FRfQKh{u8Qk(*w+3agHFz;gQf=Z~^o1D2^|x;$gVF zlRHo(XDG2pUuk3S9BSS{Js@Ny(G7pp%6@p1+BL6f;kX*CngN9RpNN10!bzP`Yr%J& zS-SuHXm^#W|MK;m(zUP)9C#jXo{`RWKPQ%KaWmx{hI-h~>qA0z9}Q+0O7TFCJG)3{fatcxsBuOeXnxXOu1_+Ks1qr-vW^d$q9=)P&z`YB01+I)O4Bo>tL?+dg*o_v zayoM)F)6a1d^sp^O$+zw2X+Rl4CKfGs)LcWX#PYh%<`wyP1t?`#>woY`{_CAS&-@V z8&a&^d8ol4a!A};p*CfZ(kPLR4JNs~ghiF7Lo51c7S18IbV5TUByX_0Sdu!0f-$nn zL5`2FI8hxv`P961@)VOUgDzrhEki1@Moti#v`A7$S@6Qp@=JZKVWaGMN8_3YQx%@U z+ZCSo2`%ESK}TJgf*D!vuo`wn^=9eqU4Skbj~TvoH2Cu&?L@=1(RB1?u-$i-tJ6-m z&FulguBL4xRLAEkz`O)lqNy^pF+n<-%_uyYb+aV0Ze;^VMy-s+U+ahVm`EXac&Xm%ARpH2mhjH)3J&BO*oRVY5XNh z-QZ-?P4ky8JRP6X8BT~+bk6=9V2*=zsCi=I3DL=Cb~u-Ueu*|z=S@ok7|AF*1fZnd zu(|;Mb~Y$N{JUWg`Ci;rAxvxEU)J4#J#dyH+mufyqyEy(GTrcyE|j{XUKC8>Qj1c3 z?lG}LxGXSL?#(0~tVykq=A}v1BDbgI6e0uh%P> zu&7Fb9r-n65ZNQAA7sP|n5UP}$yG+%y__@ymybC*T{LdY1eMWSTX-z@y?9HK$70rE5K;Bk;os{4!7tn*0h#pB| z*H@f|ar6aS!X+#wBl_|NNjA*W=Zd&jtipEr=js?w82kIQSzG~4^#J}z93aTPcay@F zC;0d6{v45LBq71yEYj_ZEn(N7qY0+8BKrGv>6qs3@%k>&YHM+~)2v2jpHZ zeh0gs5glbPg_7?Yz*j47_etCtyGV%Uo!eE;jlKE6OUa7J_q@EE1!0hX@Up$%5DFxi zz-nU2VG)oC(O|Lwh{EypJJh6!V_}#OJus%#6GV2w+VpT)oSKAd**CE>{&Zvik<){NNX7#z9mqO$48UIAA$3B($o~FXh!75G%GYa= z{+R&`Po2e>u5F4qbo3=|!(%R+HdLOzWrnC|pk7*VpImdn=l#VyxeM1IzMnjD&QU1> z#us3E=vc}eY+<*l+b9md|1qmuwwk_ zDLj|vch-HgmExGt)hIOnO~4Z-#+HIsp?RR;Ii1cg@jYDcIYvP1L^76YsGoE$q8J12 zUoU4#00u1qAhbU}N~3YS{<`oA_8H!?vN21t?vTAV>TuQz##O>^kkM4{o@?ce&Y z*TF2;9@Pv?jQDbv6a$CQXLi@Z=*^$j+}<$n<^vdh(WfsJHAoui7y%Z7*^xpQ1e1Q* z>AL&`i_%A;bpQ2Y(G}7$;n-c930Y*SU=eo$j!s~zw_*b$DcNE(6fg9m}r zUVycqlbtI|n9?P#3gT+ZdmH>R&e|Ku^Qz>z!Sc)LrmJxqm*&=K;TX~FVoa>?cTO}( zV~lu8P0-7^XZx}b5m?IojgW)yqL*KFl`yhaX$(n`ZHWwoYsSgM7sK7*0I4BCk9Y8d zr71O%-Xck7DmT8%Cijvj+m&gy2Z1SK*AFwySPSZjwqbWBHqQF9baU;IlLzXDebj38 z2TPxGdRxtDl45TDI5RPheT!wi2-zcForR$L%%Ay+IMEbH)pjv=kG7VfQ%RHO%Ipap zHJI28nUX`-?p}AZXmO*;B)P|x+q?IKyPg6VcRvb$h;?Elh10*$o8pF_YTxT;gA4p1 zo$4Pj|6wDVo&W5{HqYa2&f(U->h-!$*AP=D=#qRWP*GU}oHU?O^mI$=Q1~ON4EN02 z6nI)Sz^g>I3X{=U`!Z_>Djby#<2Jtl!DPBN_2hpSNhnWNY@={`%slW^^rEmLuX0g) z+(l}B#{IH12;@v99V?y zLp3)^iER|@^-l|=0Su)Mi^e+jYlf^}l*D9+gjn_;&wkf7Qq3hQCRccm`tXQbn#A03yJI{9OlC?z0;)I`wI}- zP-SK%!L7=_1)Km}#4@mDv*eyw;5J5)f2!YxF<>}}Dj zZzYHkJaDFbXOB1^3=)Tf$b%^b4nIiZ7)mqo*tDCyUx3O;2iVEi#xV5VDwa4cCge+> zzKTGw<=_*sLodlOHQLsUzuGYA;pAvS^hkTY$842v3x$<*0-8TdQN=wxbbDHe!rKV% zIb4Has197Th?0g6ly(H*n#G?zYDk?ymJ_}bF7N`O@PVMYn~(tqolZ(>GV{>uRDs*L zeFGtrK2fIE>(6w}6Gz^GeKm5EQDGhfcLP9QrZ(M`yOU3>;jvjV{@a$_8|h_(e!uc~ zFcj(p#sy!hTu;q=7yFc1lhM!?fQ2Ni$uz;Ml>s({@X20PN1=*BBGzq;31MTMOIQDLm>o{QFBEE=Yl6=Oyu7 zu+7_9Kb&7ZW=m(1%KbaiDWG*@MI0XsZ>3Zucq7=+g)_h@oEPc6^o^$P!}+#LUiNDE zy3)J&tXjp1kz!a}>}Evi&6FKMGX;A}9?4ZD^jrZS`+wpi}s+b^3eueivb6Q#I@ZcVK>a*J8@u-(= zYZ0FG4mC>!$Jt0&%-(ZUN4C0HD{#hA`qLUH3m3EYBfuFB$t_TM{%X}M$D|ftc{)cD zU_-JC2)CG{s5b1H{pm3~eA;a9Kl{IrbftP9IXY?K1|YDb^pHs0--AVc98e>FpD(z8 z5V8YfQChN|G?4KqEF&9w@{p$+Ou>fI^`cjV3*}m}~ zE&#ZpZzoFQ^<_9wt_aNq;kU_jRm^?&G~hn3GpvR!i=g&WB`cwtMx#RXArtS-mK{@+ z;3{=z04%#$gIhhrq2cn)ocGg1pJ+}E`4SA6J-G<8-x5lK%`ITzOxrfE-z;5}TvT&j zskAiub^|?us7jjMDIMZJtKkWId@;3s1P;bfu>z=zy0apc#AJG(bb=b#L$Q}n+WOqehNLOtZvC%f;)3}osK zOIHL&HgS%iMI7_x-DoCKt9hyRauRZBfbq6(rPKnoK$sYgnSS2^oV#{|+D5@zCBQS} zI<#GT6ViW0y{w|D%5O|FM9xvph`^!%7qCj-L_ zO{KJu03H;yKe};dv`g&?{K} zmDR6|djmtsP8_-hx9aZ9XVYL_8a^0Q!g$o$N%{u%7cdOt&Awc9!Q`KDLLWsMiu(aU*5PD?Sbeu+S_17XhJ8D3cA^J`vE9PaElaHl)MPBxd+8Qpc~r zEr*^beRK!#QkY}tM+=!0Xsg?p;Mmltmb}(33u)|D!$Rb6Vn3=n^m z$?${7?%@*X3>Mr^}TS=3^clc%QuK~y+tk|agkE5cVty`jyxE-h9u4`GVr_QY<9z%7~f zl{O+OJFgV4*4m9)kosO%u%o3Unzxk|UTn=S&#ki}!6t(t4r)e_Bm+Ni(!6|c?OKagV8w;hQ10<*auu*m z{@z62w(o#&Reh!`kXpi*zrPI!^P^J3Uw=OXT~$ z72VYhM$GO@LU&1=?f8PFwn5Kw(ZBPl zTO-$v*F82esdgDHWGezDie0P7E7lJFEo_Q?<%T|>mse&UU;+Zf2KWi*V0F{v(Myop zHGQxVdjs7MHHR1i8V^r@SCbT`;OIqj3~XAckDc)>+2V$$t^ptBP zUF+^VwKAJFa;emdU_Z^+sA(%$B|aPlV}j}IN>^a4oqjC~b&vxX<>^X8#&6!tV#qn>WMcxDK>LYiL@yl>7jqp#(=*B7}Cs-mnV z!85H?Sf8DKHl>d`_2K80xi*FjFb0#Km!JwvO_Oj(UTtic00YW63xaKn>M>QX!awc| zFA+vIkjW1X?DNg-KCJRT9}%V#;YVF%do%$MmA4brU(%q@TqAv>fO#r!!7i{crruC0 zMPq&*7Z!_C^~)m&+Z3Ay;cr?Xp4y3bLTkC$$SB4wnyq;th?bok8{TDAK0d=d`#f>e>4jCzVSc14Q`Wo6bFnhiHOU*_>nbNeNmOeyoHYdF zK%$5zeU)dPrZKRLcd3Pep*3WDNeUBSOsPS^FJR9dNiyt|cAv!r=uv74m)2~~W_Imu z6F+fdc2h>YIm1rJQiW25QuE5<#GUF5#}{@11(Mi~^sRuk8G-Q!&^ljb2ZCUoi1?cZ z=9)<|zoDv~?j7$_k+YqZTvK@o*(S~&2<_ePd}c*A{H5Rx?63~Wfk&LFC1baxk>sXk zlh9|G@CN~@s&W&j#%abumX8;*f{bX6v}(%UO_0}&RM!Nr6Ci|-{%Il~+}BSRnan@2 zr$5rJ2@1_=8S@ZbL-6g3mnyxC?T!|1T4Etd#E5R+$e36f>AYwWu;s%v&(+`UPqHhn zsWatYYvjYpl@0-stwtmTYo)TKwdJ!%v8m~;Z~Q?ZNRvL;i+Qb43di7^W#BDZYQ)N- z${8%qK%H@>U&-bSb1|oP@wPlpS-@UEH8G^9m^^*svh7xho~2SbvudcZ;$36d`q{a` zmCv5AP@$c4Oo|F};j#4n?s}~x$!?|GG0Kk@dtJTc7|~`M znq?Z)dBwK9$f;8b;|jEoE3w6iN#H&e z8?0eD-Fj3^$W@pKOI_sQDf%tR+Z_`!E8Y<>_r54fs7U73biY~d4`p*y#0o*z9Fk1%=u(T4n{Pj=J2fCqpwL5W-^Eh8p z>6^%nmYiI)s8 z45xZfr7?z5fv);APJHL0t&f_v%-?yrHE5n5(HXnH|J{^bgVIxzKJ&Z~*Y05lJH?G zbENq`hk@J)U@1ouFO2*VVbKz-vP1p42YY%>pdoePfV(wlJa)r+Jz_g!B(Q_=`1^L- z*L606ntzz7^2F%F-N2CV-}w*)!qu4^)W2~OIfx-)WCsp{Go{cz=?XP#Sgfh==$qwN z**yCC3?6dIj5~G$RKwox9#M~_0)u~=FQ?dxY@?#nJg$oOgP0yAAO!afF!t*|9+2?}@}~Sje4C z=uul@Hk%ZI5{7>w1i8Ro3PsnmZR>?oUEQVvhqaC_tc^rLb}CrXvI`f-NNhw6 zw_=)Uqa-JKv#e0_TwBiOg zh9xt&*!g;We^|hDZqMaB44^q=E!C$O3pNaJAll2a^8m2~1PB7;v=njO`q;NJG2;A- zb(T14JgpCOE2Qc;AHv!irjEkiUP?mY0Qss&OBmTX3;8c`j_$oMvi@u8q)JY%oZRj= z&@=NWtXW)=&5hx3NdSfeBx?&{BuJn&jH_?6ElkC6>}g_^WMD3v_NRp}CIbL}Vl^X> zlh3Pz+v0bRlpsDOK>ByD&5qoCj!m|<994JMw$ZTG$|da+w>b=YK)c{Npqk3#zopOtRB^HECt=0@hs0Kb@|#eQ z$!{x(WVNK6y9SZ;rtE$ffCsUicbUfHR-j8Exy-K1o5 z*<_gEiEGVC3*xVWxlJljwlZDxh%b|&T5Xe9%8PF{}z)ghsC&ngm~gOc zJ$jRMVEi9DJeS>sX~tfZ7c4PR9Ca@y%?Z2Fmky7D1xI z$OUIEDt8l~6`(Y@9fiJEdKkKPzY$qodaYW5=}{3gZ=~x)+fY9|aR4zL)yEe{Q44nz z=gOHjK2DwU^Dj2^N8v0MVp!tx`D;(Cbd|4)Af0k0DhG#nh%?fm2=rGF-*T?-FF+TN zm^d;a-ubkyhp+115Ah&N3WOE&{=Ft@IS4)ocaJ#_?_E4QXWYk^XstBgGVka2gJC=` zX2$iOI^VO6)q7LKI8jsj|E*j6@X1(6oz!pnF1=Nn0D_n*f0S(gs^yyX%GLQd{Ibh7 z*(53FelE?O{G{_9;Dk!^bc>z8&VDV+-mQ6RXJ*l#I>)hJO({SLuHFpMv&XW&|sk;HbEhsXkP)Bn%3N;#%Ihz{Cs zW;6s?v{b@=T9$q{9sOM3&OR={fl3A{tsntakdTqPE)9i4W#CXn38*X_3O)6{2msjr z*9{(CH{CG7|Mv~S_c;cD8@PXYF!RFr1v>h;Pz44CO1gPseVrX~E|Ok8t{H18Jb)1u NQp-@YMBO3!e*nzNs#O30 literal 0 HcmV?d00001 diff --git a/openvidu-recording-java/src/main/resources/static/images/subscriber-msg.jpg b/openvidu-recording-java/src/main/resources/static/images/subscriber-msg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1666fb4099a9236147861e734e61869e37267767 GIT binary patch literal 82734 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 pgR(+GNPdoX zf@|!8C7yRdNd;jCc+?B>7qAB|4qj&gT-bW*{;}$xSu%6FxpDqKuIR`ULIP%qBe8_( z21WTi@lUX+|M|E}o8rH|{%Z~XYYz~!FvT>PN++)g#B_?a&=zBQRQj$?GUepDBZP!~$1uIZi{6e|qj;>e{{V7@a6paQLCwRIWlohtUga@LCYjO7nHG#>QZU8^p ze6Fqtk)Nc#l!3@0Z103anW`&AAAwiRcWh{K&+iTXl}I+h0!u|9j5IY&hrue;l|kji zRTR9ip*8MJ!))X3ZLiXC3uCHsmXn^wVY7YouW+vwy4L?CwH;nAJ0f~K%TGh&Ov+g~ zJ$8`5XoX8xoOuiWE>L5k|p$=pYDuGK7*QVwj~0!t@upo$nYH>8H9J&2%_DroG#b1Lk)t ze!={uMqr{WZb>%{&}D6N13v;8-n%LM9K(#>eAnWDg2#IV#r z;_6M=#xFYx8JN=EQ?Ul4WfT~PXrIE6HpbXohS;FFM@jipdVD1P^|)5 zHEyCvIRbvd-}m;ijG6)4S1yHTHg}yW`&S^n2h&zNYVDL&; zvz7O@ux5)=?eQo_|g^74C69x#<2iE*b=0SiMhvys@FTEF&{?3}PYx<~NvZMTnd zs(WCUEFlggKJIV3F6#visS(;~MVQGvlJtt~Oi$(VK>nxFl^vy;J(itn+Fm})O(#o0 zZd}MkfEe_Vb|QrKaD``WO~p45oji&Q1IhL;w0`}aT_ZlCr?H!C=^tax4Co^+1Fcf^ z3AmX40f9ZakNdYF#e~W0@ME4}J^DRJk=o2D7%0+|<8Y)cQW7 zEh{L@W&72l)6wPnl`7K<-PPoN{?Z6TvIvlUcz+M5TY;hYkY2P(7x10 zR`{GFC74ssbuXk1&^N-5C~hx<&Y34NeaIIWoeno#YO!Yak4!-Bb0=oiqXW8gv*=GD zeD31mP#r++*o#Bt7~vpS100Gvpbc^E6X?c`D$H(-mYV=G61Fply~fD~6PI$d{{GY} z&qH7f#03vm2OuNhy!0$pqsKaf!UpSl`uDg0>@w3odUn=mzkKYP?mOs1pxtjpGl~C6 z`+DWqI^!>I$SZAkB>;9kK&at5#KV7c6PJmq|4e}+Ems9aJ3F5GK}w8nDMBZwViyVE zNrcvMz3b~XBidNDTT{87RzzN2o003*h~b}`|66-+8r4+Vt&3V^FDeQGicLxsQE5_^ z0+uwXQV|gmJBWagvOzjArGj)JOF=+Dq-+3@(kKWhjgdA=lSr>1A|ON(AP_*>kc1{I z$jYiaseR79XMc6Z*mvAB_Mbbx9}a&2D=Tj^n`b`rnXcZdyKJvy#!kK(8ZL&pNgctV za!Wb{{PPgk)YpaRD?cg)`|x%7GaDF9sD&%TKR7Sk-#^5J)lF_7V zc?PK$|2W7}txdx1uHmcCF{1~5`=451|3{$FtE6(qat!HtGn(`cU&zINiMKHS!gEP9 z6WlGn)`1@{1d2U#%I2!!3|#GbC#A;W`OAnx;c$`caavMzjB1^RpVe|jX26sm%gp0h z%J|hP(o*_n|1F(s#hNs8slg5J%Q^{5c~9<}B_Hg#mU%F0O=cXE%Ru!SqG&srn1)1~ z9V#@_JsM9`&5vE5-FqdM*ycL@I(q^e9@G4fI`H2XYU}?Ha{2H2AHM<0>x{8;f~BNk z!3iMHJ#IlrhKjjJ*-lb#4SO}hWv2sO*d)W>j~>P9!|W-r zX2T3VLH3(OAlfI1I4OziNG+jn%8MK=F?;b-Oe;5vqcsXc>8Mi<2(KP7ktHNJ27e^C z`YA7~Dv92F`~cs4)0WzdN)?`IwR7DenL3A7H>iZPJV~gP)>Dv zBycr-G3EI!SLrJk`1pe#DRf;?dej{x}LKJoAAV3Ei~h9@52H8Wdu^G7};U;s+L-p`q_GXxC; z2c*o2(>q?!Apd@lGNT2r+ZD?g^BV+?H9Hl$<18E)5_|Eqspu;Hu854^%7$5F{n+Cf z;3&OB296zFIK&dANcUBNSL0kDt)tmU)F!Su;t^C2{XfTk$gj(?x&8EEsD z-D;jF?pT2Pgm_=77QBD*KJT}Kjp?=0JK13!lypRmzQ$jtC$=Knse39Wf51>*^>o3G z_~}#Cr)c*p1?7VknM;7dFmp^1$7D|0wk32MJ!=CwaoBQ!u=D5KXnpka4Z^3X zDkNeiy__29vITX^wkn#c&@8A<(0i;-*=}!l7X)g*i;%aB5+sKO)8@o5AV^4GB7?7n zKo#Q5vInHXsmh7hbL->>9>JW8z``WYCZwltkkpmP8KY5@fOgsg)#7I7mO1oRdMjtl zQ?QydvUiqa-p~B@iSxXH$Hi@&dNdTbTz-JxqfKIMO)F+6`eshWb21L$_FS<(a`M5~ zHtZ97-l<)lOuR;oBmbHABlA5o8XN;TmZw|wM5~CT z#J7=L3eom03>~@be7b~E-ekRYzoBC4!YYiY^8=hVqJKw7udzmOwEEi=!g z8r}UsX6I46_1K!+?gFkUQJ6IEZC>%M1sk<(Bpts9$}6@HwP2sQBeo;UrlkXJq z*tRZ8v_L(}2U+31EWl0XmE`nto#XVVg!Vzz;QKvHN_Wcd?N~0_BVjnBYe2tkc8;xO zLWx8q=S>%1%aZ;EvmWv)-vhH(Zu}pbyqo?XP2O>3bQ`Nm86p|Py_mECTPw9=-P*+$ zFLSVX;as*Vhsi%1@1rZPvj1z&$=77CnSYNSrvZL<7E%isJ^l*;ifN~S^J5BO@ELs_ z;QVZ2mendCoS&UI^uV8qmpj_x@s^ZOkQ$-DbISCQ-f4Ut@)n9;gUMs;<4hQ45D(`L z&^A(gD>Bg-uopU1={(Mu2T21NvHb$&vVG+7NJ^tXlnI=p`%*u=QUR7_zag^w!A<(7 z|9C4t4TAG?r8W2;4y_58+FDsQgyK7_B`|6n)Em8bF;OcrS@RFZk&yn6a?)2UDep1R;bmN7L`%r4PgbMe7(>)tObMJgvWB4jlRvFrQ5?2IkICnbpot zxY9iumMisr6^`zD;MZ6&P6UQ34pv7_BOnJA}pFoEiH%S9bo=dV=BUUEn3y_q`^)S>U@ z+Mctf%Y90O>lecqOv(%9=h)d;Tf72WgB}wyqY@}AP--*le@gwyUGR zQ1EIQJqS#qOSVJ_w0)RzEC1L2j~or8$E2&2U~MkSZ0O_R(OIeT5E=gsd?dxGx$xKuAKh+$yXtt})e? z-mffVrP9e?yuJIQ{p2rRK>Bb4mUnuwMX;LuC|*g@B)LYv7&Uc1vplmqGm%#8jMy&y zY;tb&ed*atCB}e=?wR$P!5`!h1(j{bchW94dehu`vX2nI_oqwktxt`Lcuw+%4bnxq z?Bj9{X#{kyXvP-wigauxsjL5MVVyLnn&MUMr)ST$7f;bjgluO;8iYl0oYm%w2FP?H z$%dB%kZe4kt!a{$6g}!lAZPR{Uazi1SOy<%D_5si>|u#wy@dRjokH#Ou!fs` zIb;pZtIokGq7BH@d7ENdEJpt$Hh$~u48DsTRA-ba|H0pQuk=o;)Tpi!q6+V{tQ8*K zUVVgZ&pX~e_ZIl6jcG#?+$hLN81Z|7f2D7h5+ZhS);al~!OYI74O^K-pN^cW%e$n; z^$sM8!0gWZ+6u|Oa+sCW@;GS!3wJ+n$)3n@Tkt^kacSlzYI_q08&i0Ey=JbL90jfP zj*9DSL;9D?I=6ft>X-c7z4^hW;i7v+ACQtCZe86*L6?kA0XIJ+N`W*YU6C9mm8uh! zl-0BohMnzs4o>{44dN;1Q`|?hE+gbef9AfX{ucI9nx#$PDUB-bnT)f!?Q}?7xe*Dv&LPWy#?***;b+>tF+QM(A@1n)q>>9%oVvy zQ2ddNPXZ?N4enW~R2N^Ao>G%sPbw!y2S$7Tkv5QB@+(!^ymrZy zpL3_{v`#cc8qrr%mO1lz`Bw*HeEX+gd|cZXXQZf|qc{Qw%m=0ZQlf}vuRh%|5J+n_ z3+tTTTzKHxUvq5V;Cke55Udnd*VrnUME(5X-TKd9wfzpCS+`^R)@e$v0uW!I?U-Da zldxqHX1P-7HM6snW&HZN6w6D$sfwRCTz#GA{ns1^#n7~$4E#rkyO*HAvO1E!9r7ae zEK`%EMc&yFU%xeN=*v?VCta!KbV38wjP4hbhjIvukXKU;;>&A`rSlxy+3UT|drgGC zcfk0k(&b4>)R_)W5b9MoxahxIHBonF0lfJIQw3nS(Mlq z2oB2)9~>G(ba3lO;Q-@)=f|v+^{;2I$@(;-dV097_Z&hqA_vI zWubf*y$qSlaUE`>S#+;e>Nr<K(~v%2nV`6x&OfH+8|fKxY^BI36O>v-S)KOUZGPu#NMPeH4kU^7Kytj!#MwC*Kfv9F!4Rhp!AYBnPlYob*&7uE^l>IuP?^Vgk;Z_DKRTSBb zX1?fjbkI|eHxiqU3Gt3wCv6k&w3wOcg3n$v)gw@>R3;$ZJA(i`&73hrbEGEal=(Qp zi=b+H^{OE|;+f?t*1dfi4~Ljq)x~7a$6*S5mx?ydxrUk5v#kdq_d$diRH!0Gx?u^& z&}k{B+DQG$X32r{>Gc ze>4iy8M74GNN)>!2l6#csH`w=CP)C|^+mtC%)DJe~Kq(#dz^Sp*;s z%Vu^u;xD)5g4t zt)G!^i6w|58M2?fkQpca0MQ)eNT-fOe1mO7+g&Od%_@AAV2l zYFtfdqt$fRU8AU?JL%s(i=R{5k$~*JVT~cq2zSV~%og1iF;XlI*9~%N&_K%9XWNV! zF<#+=#(*AP#xtq%!^a;slm%PbvYTG@H5XVf9vOY=om*z=z3whceyC$RtQct($&Cbx zAh$lpVcuQd3n{Fk2nFF-;r{Uu0N-_Qu^}4z&J$xQ@{q2F8}w1tv`)+#-RI{kL>4-Z z#*cm4zYIyU1hT{fx=fo;HI=}oPr^{3cP)QYXaTmle^;8Ihy+7182p$XL>{pHd&rLE z|2kcaQ;Z6i!B{87xtB zHg%zYw9K0$)qc#X5U-@|dCPS|+ESW`SUmzVXgp*}kC6KF5 zk`yaiFd=!uPwok4`8nnc2{P#fbs;%{XeUZ&T% zH>FRtxZ1TBWJ~tp)|S^vBknK;K4TBK!X+{CeYCBLXY5TV^c>s5u!78GI{V_AhHN(q z$NB==La<>4Z~9zU1Qs7V2l?6vv*Azre5Wwxj`4-W>D2|484OU+~l>gFI9 zynth8zTImk;wHY@zoKf7l|^Zz&-#7G3iOH->Z3Y(PsdI@Aa@Z)z+CFYf*-10&6!xh z>=Xbfy%*nvd`-=SJGd?%2HHn5R7hQrnB{YU-021Sy5tw`HYsRS{RmZky}?#NEw!{D zvu}2)!&S00;?@LnF&fx7T43fmwpM93IV-Pr=oVwDdC7Yaoa%bWR?U-AMX6nzzif2y z&W|k|`g9w)qvYTSA;9&zK4WYF08wq?wpdx9Bx0md5^ITib-y^flV6!PG}V2rR58AF z`~uROg4)@0e&%?JQC(ss6Fs#j{U+iTlx=cIg5SNW&5)JEXI?dbT3h9KQZV+M($V8f zzfI?w?<_`xbR!yAvE5)8WhP;{r7dpe{|KP~6YH6@KlnPKkH-45(A#b^Mt6sU1+%nDM$!mP z2facmhuK9}F|zW-7$Qz80;!W?aMb-KZ<=O`?86GS+Oq>$ypDjW#`ZeaC9y@+yBIri>@AO6_j}v+x)PG~u zPYpiW#f6Kuw8$d6F8EoCT9VI;`l)k{k|o;~;g9e|{z>*yMp^84{tcC?Sw(5Z-7&-y z?7PQ~xd?+!^~Du3YdI#y-*bq_MGCq#R%9nZWDli+3K-|x45P7qOujzN3vpI&bvxXn5#5T zxFB0+(XTFz!qU6~WU*iWwKfh?defh0lAP@!)dV;XcZ zLA>kbxWiz>xYIjMM|+Yh;>X7f(U)C_GC|#+UxBL&SaPqE1+UvlgIO62xglcPYGm}t zIfniC%#wZH9w7YhRi3;(40>Z5nCMm=Y*o-{1*7CNeJQpk9GabZ@9qz4rhf6-^L1Ay zd-pwJQPaikqGI`=n4>oy~1MAN87aQrvIAL zSx((3iiXhMpI2Fhp?~vPID_clzNKB^=47IJDS~)Ofl4YMXpb;&6)e-#>PV?1AL2|KQnn#w z7qM*~XQb5b{ur&>i+!2O?OzX7pzJ#HN!Xu^IpbnfJ7T0P4f8>3f_flf_IT;n&4?&p zd*6Hef;-})34U#joRZ9(KI+s7dCN?K{2aack@CnhNg%SJ(_`?(5Gz3`ZQzkdaP;MC zwI7ZBRwk$HB>cvy)CJ7HE0(QR2m#gkG;VUteteTuThV(@xui}b;d>^&mnt7(d%-v0 z`{xez3*9PW=LRrk-X?pCT1s-JXm!!Cx_*6Lhu!`lVQTkf71R}oH!&*TE^piqxqzH= znqEtKTMPj^sxE4oDU+|qn*$e$oF!NIHHCq+K>ABJ6OW>Aj|hQ$=ZwttZ+oi;hH8Ur zfi=MFKg6z7Tt_agpDQzut!|}nkvvIfwxJBU`Ke9$Zx3RT-k73(oG4vP#?j{+p)PZh z)FwEDs>=5vp8odl9nq^b_AyzGPSwTd3X7KIe$xh~&9x6C(JS3SD!Q=-3&DRvxYZDd zJQa}Z5x4}Rw_Oc2h%J5nj_bAg`Kj}mGU@ek*-3H^I~{GJu%&X@0I$lwY0 zL3?i^%=vz2PnkK|GLep{6LA|&0bVU4K~18aTaQTglcu*ZRFRSS@VL}vltV}vL|eU$ z*}!wU)C_*#rhX26AKpM%dJb)rR+JHxwBwRl(hWIOH(xD9FRP>I0!3Dm8i+?tdNnM- zl+a^H25&IOgS}c}5N7zfpui?`S!&kOzLl2A+6dH}^E4{?q)<-2@^!ZMkVVymV=g( z>v?LPf5ed+y#@D3-Q!4qbdWJ~X$z#-i|9t!Vd&a(M$@~gQ97RstcQ(XKk?uDST-`y zhlpQ%!B>4Z1Hs??hp5t1&Q0uR`Mv?!v0pR!f>)tg`JNggqp=iI6^{I1V=e+LG_SF< zrRhS3C``Ve<}S&4vIxk^D&wab)1K(26~t+H#F_Wd3xr=DK0Ib&L!FnfQ#*fgk(I+S zatmZUP&)~+!E1Ts>vXj;DX0_8oTmyIn)~Zh6Hk20ZDL_b2=Bowg`j;b^91y(z&kDc z!nyF+k=yN7p5(Qbqv`CJEmCv{Vd&Le(oAX_c7@eB&9-wc^&|5-mq@B2LTKxs`R}y0 zaME9BQ_v)WQ5{G3=RC#kaUL`H%GG{sbHz*Zt>}{(xBEyWC?qH$%SubK=P7}bP4c00 zW>eh_m>Ns=T+$Hv^b5^5W6(vf(K@!kW6VRsHz7&`u2g1#LX^0GUhcoIlA%m;7l%T3 z*hseiBxA8Z|4^rlyC{pfD#QMi>j~@-|8B&E6O@lF^d_WiHRcxdivG!5OA<3uujTJm zr5c>zhvl)}glq%UN+9@|)8zvs`U^P3!Fi&Zk!I;I1@%(3F}VBSOTJa_umQt>#tzE; zspK$Hx{~>d({&3OJC5rhUzgMXa-a$7G5Y;CMOr1OUC$dWCEv@-GoPP6NQzuhrnhhW z9wHxlD@L^l*aJ?aK=wV?G43NN-#Es{^<1yBzkyR4K~xp&nK^TK5(IbE?%RflW%^PeI=vn7wb|}p z`mkd&GP5-17eeU7Y{iDoM9P+vdRI!LakdXpv0#R?)oU^cUjzx`53#o?ljF~j0pl;< zaY5LJ)O*W+E?zww7yRrso+tZVk!SuBy>8Eix2ZJ!lID$}lqb5;oPstzP*guuTkPip z{swBd^CA1Yx3NoEt_fM#!9EamJx59rd=(2BQFKFkJ$n&II+Iz!UM>Z1;-y{DwYPJf ztu;k1g6;Y=XE}lk1Yj-Qh&&Y}9I{BNkAJ@ZM6_;|#-6|<_{CxttsWNzTY?1zZq|Km z6w3N88psUgG9{59A#4VL-x>lPWfBeW#%$RM3(wzdGTn~8b zof0u#G)$PeR>XW)q-cV(dH~I6s3hgI-cR{;dw%Dd)=4uX-_fiwC?`nyclXYt!Nr;X z5cVgxi8FF&)>mbWu~#q~1*pDTh~ZjdjQIjIviD8%B(iM%rjJTvisaUB4zQE!ifrZI zIJ;l`R{l>=kUU;TX(GS?j%aZNDNmzwH+8u8Ft8Z;7xK>_636`|On+RgRE!ki;Dv2wQL3SX1ad_tNKheCuYgkJ-K)-s8 zVi+I$MJxZBqb(P@DegE5@c25HAQy0^$Ok$K_u^bU*qBsM08htMl)L-OIFZ0VDe+B3 z``^5$gmK))13{B($bp^izwXWnE&n!-K zk^fSf_&oP5ML3PzD8lMyg{u~s>-dvZSMb_*_=j5F@OKId3je*4DBrg0supzcWV-aj6Cr&1Um-XLcmUV=6sJZ! z&!H-|psIU*0MhQ&CPM~@cATy#%GeciIJ-Goh=Q2+R2h6y7G=zJ1DJ)^@%LeA?{d5P z=u$YQ|0LP0{_&sG8Ok=8RUomZOq(MSgi$ZjjC%J$@qB$}huvQy0rz@EQ zVp$8ks1;faNIyLtaC%M7pNIBBCN%p_-s~OlPMtmA1@wkLa=P9k!)ztwt&pUsAp?#v z%L4je_%^eubXTCXKm!QkY9%7SleTk=J=@7We)cnn@ep)$%HQ=_ywmiw3db+QsH}egIOx7%oUc zS?R$oXc#33DO+RkjityitUD!Ge7P&B?+>In;DVs(X4%dGWmHe_E_>5)2_b^yzD%op zSL?3mzD7fjO}3AMw%I+>L1y~5iwKkL++G{{46Mp=Q8Gie4vp9xniSv@prH_ptic|& zWlFaH2lv%%N(Sfeehq317iTGDW-eJwt!bFvh^*v{9EaVQxZ{YaDniUDd_uRmcxE-2 zm(QA1lGcd1 zOe3}O0{aVQNGrTd#0uUXd~`4YpEr~u1=`;qA)FM-*9hE3wR?kjM(rXp;f(w&wa~7N zUV5-$Q=yuj-%dm1Fkz0V>Q!i8rB(>$3~kFDujpLU>@%DSY};GecOf0BsesxA1I!qN z@b|l)3Cssi%P_B>I@?6r-WO)<@eoDG>-$C$8g3(xd$35etwSuWn&?$nSoJM3myeIbP zC}{4anPro-MEON}1&fkX#k#qLjo$SZdYC#+)kdxlbqY}O{9&3c2c*KKU~(b0Vw@ah zwy$UT&6=s^s%I_-I3t@}z^o2@0Y--y5R-pR?_1=vu}|9P{$jR`cgN>4M(Y2Y44=k_?c8rqP{Fsnbs@dZdJEY~IP*E=9LShEtdGnX z0<@Ve->#EZ=nf0oRN?qa$uie)LD@{DP8ECMfoY%O$ZK^MNP|2|H(`VjUvff5Q#>gN zmRqCK>~*x=_pP0s^<2Lo!gE(XTlDR(%^u&*0^U<#Y|ZQlI+2pxl=d?l#&lP7zuaYJ z?!J*BCmjpuvyZonp&y7rBIB=Gd`6z7XorV-M6!R{C;rJ2=X>s&U8i)e_4FMT zY%aC!INKiF=n^EiK*|j0b7kABVb9Joe=OM-`iwU!qvH| zj)z(5xgXZO@YA~sYQzd~43I=~J4tA2#xUtS`WDZ;;hpY0TNyj@Mf;8bXbI5@cM2e& zf6ZyFd>_nEJeq@jM#o`Rmhnh`51%oIX4!-{_-RfTvUXsfUCOYZDg~9CI<;>taw=?B zC`wI6Q)FkOg-Z)_mN}ITC$zLfSBdS3(PM@;E*cVP_3K;IDmtHfr5{>9xf6du|uC3_Y z-PGaOP`SrB?d5lrQCpSwvr2`gfK8EU-E8)C?H()<^o2)IPy0zZPwy$Oiqv;hiSZu(K~ z&=j_!2mh6@nls!Fmi;rRP``p-;~^hbNERw$V9%dl;r2YHSO064EB%zTmh==}eajS< zNGuo3NZ?F1$)hkZG$9Zaeh|7KUyC7l86Z;91QMH1$XVMk05BM91q$L@=0^^yE5M$t z?^i@Wa>GNl=g_QY)gNX_?f;$s$p1TrOXl=6v%nl^z-7nH_3;MAVpEbNw1S{aBfRin zZ*U3=|AsmTj0NOMvV182{C6Bu%jLX7~CvSNdYkw#X{>Q!+Fh5o6Q^2 zrrF01Cbl_E-L5a53NH!#d&c1PCGxAY;ggdGB~MT(|7*@%fB7-FP6$Tr+njLZs}1R> zZTuR(BHaEwg3d*j(JU?IAXbEY+YyCiT$X`48DFPSA_^a-jwWU}ss&seHNx&!b|}{h z4%jnmXX({tP&f7nCOAIfmhb5gGZg)3{?(wbD9FJX;YFYGo(J5tW^5uG5FDT3LtwFrbgvPJKplvkTdIO-L6j-pYMJsbsm(>oI4iqgS*FA|R@2 zCdVkZS>ubZe6J3HiLyg_J*sWXHw*{=GG3R1WxDdJn) zA^i?Tg^Sfne2iHefzKTAFF|?%uc4S=Ne5+oEW^_VWTl zB+W7tt*8u4k2d|)AG-1j0t^+sqN&t3afuyJQ%*CKLA8DyKcXOwkiT#ywq|zEOhN>i zAd8WbK;&Z=?Wp8VSgPmD_2&L&cEgKlw*7}|qtv@`EE*8uW%w7)!bw6bh=5=Yl4#48 zr_GnJealKNJKL&H+^)L1iu2RdUvtP&7@YcuEi?!36~-K- zxBss>gcO``Mk>Z5ZLgEYt^#lP^TJ@sFuv$%D^FC~Uq!gRvU709j~-e1F=ol}XA}a% zjzY+B)n@edx#a>-&_Azx)i)g_mpxH=eem4)>di;Xqr+SRE`Y82{({*D=7&-*T**v+ zz|$z3n&!W$O!H*c?|EhOD{pgd=H}vYW3km@o?j0lQlc5)+t5+@$#5OPvM7A0337w8 z^QSe&o-S*EekqtGmQLT}g{Y*2bv52SVe?sZ{?mY-R!5#+ib-)TNE~?0+Kvlw`Tr9E zW=s)Cd`G;^6OT+vy?#YG-H(kbj(>qckISguL7evq^&tn>UaPj3=N8OCERZ!cWnU?= zTltRp`cp0z9#@6T2$wK@HBAp?1%Lp65`aD1(+|+@F$~o@9K)P?f9cgrh*i#8ylQ82BL|gODqKsz) zyzm0!YGviR^E45gG5D2|iI3QN5vZ2#r&o7$Zi>iEC3=nQdQlSM}$pJi1)#4NJ1#{I2b zB6l^c_*FwM=TdvZlG4sC{fbs!e7hueo&T%x8goM~=7ms~YPkIHWwgL5IYM#zimh&K zZ4xKK;PPq39ORI>iNvy;$gAsW=PggU>?#D3Y;v1UL1|us$*JHELZtid+L_Gd$s7Y5 z0^YK<=DP<1^XnyfRgMd9O@y>vA5tkuZHgVuy?LHGm0K{@KLTO+Y1&mq67ey64O;8J zt1Zd5`tDV^eA_fM$=OahDN-xQe7XwkJ%89<_TtGNbfa7FmCSLg)S>K)aNEDT>+p+<;TM~fcH7Uu}e)Bd* zQWI*rHZAL*t9Q_|d_`g1(RqXdZcQDBXWP?o3*Yw8 zHPq&DQ{BPB`{5zw8w<5z>ch8dU_p88WcXg&kPq+CI=m7>iV5~7j#(xjaV7CmstLK2 zJCn8qe`3WWqr8BOLE>}k1!>x2O z+x`WJx6F4gs?EDP4h04DzHP4JKFMC1sU;HV6785V(5}kPhKD%9%^JscL)PyAQJ_U1 zE!8DXZbrMvCAm?e19hs2O9%H{d->9xHpdy|84O+jygc4p5ZF9oT+r^>4mh{oVadk3}eKLAX6y^mz694t}eewUnt~Rf+ ztbu6GQUDrRB}ziu4HTN=X9H1*@pBi?@n6^9&KOHAS*E)k>!2SdL##HB)SEwx?8m_E zK9s_IO$&xiLr|`C?z>Jc$%a%(Lz#N(lg&++@)N&>ik_T5c6xuKiNPRU#$`s*)Py>c zh}-!@^{PvGg^@3LLwi-ej+?%;|Aljhx0m!H3U{JefJ(7?Ce%g~2s3NRgA~ks7^=$? z`@y8GwxT2k#`I7q9WJ@v^21C6!RV;>my2uFyhfqXvO0x&M($jYRipgEpM1P9x}&0u zh=;0@E8+$i-0nmAk> z6+P#~#h-FL{wijqwvzmtmRL{_@3CQ#-{{z9R&6mS+P!Md@mbFJ1htJ@ zQ^-(ao6*eC&=+s5*UzoIrop;R>hI8@7z3Q$L20s2J(udASHW_0t&4ta?3nAnK82R` z`cTr5wTe_~D<^(No+LXD@0^aEK$W|lh!HqZqTs}okW!P&&Nd(U?BcXPr8m;Gch3u$ zmAC72V@eML-MmmVzdMt$V#v`llBSDvE4HtVu5$`6jx$J)+I7KhtRx#C2IACkclJW3 z7SkQCJUTZw8gw=vYkGCIH17$ibX}uS@0kf#wHdD-BB~!V`Yf%^t4nahzLlj?{ocvG zMe`d`{%x~uKPAED3s&qtcV?I3KH@=LjDMjl-qo;SfVHA3vqHsjnCHl;KNp;T$+?tP zD1R@2*y9GdTu^{uDz;VZAJ7{wQL)Ug#m9X@V=B>=oeR;(RGPKosiBRQ(Cqs@>cw5o<_8|Ty*<#OdgN2) zSSH2~=m?tvdcLLNL5woo{iLDd(N*JmGd@uz*Ds35297ImBDyKy zY|FebCj{yx5WG&re$Kxj4ks@J3c(Si1+Vxw;tGJK95KM2{ucM5&_ ze~mP`)Jx>}61g<9d+G-5=dSg}-HZ@}i|0qiwou2StnQxFFYdg)Mk0TiqOcV_}E(cSIj1xu>{Smq%V@rPl%#vXLk&07A9?P z@CxwIwa`0al1T)4ciA}^gq*ZGH4Z0ppzjc>rQ#J8>zNgVtaXkOzN#~rOeb-p6 zG=U%Ojqmo@?x0A$gY`eH-$@H^=tb*;JsBJ@Nul zIRbhCRk2G4?|Lv+VGC2yH|522zPIt$OV2?ETCCF>*AB|(O4phke)6~N+QBO2hXwC* z92a(sMyeR&W{2Gd7*Vuik_MRM15Q`pWs_AT!wnA84#YENrz{X{yxh&ybcv=c@)w=WDS303?WCK3 zL2gz-7^RKIjL13R94C@zY+FS+Qh=1}G9q|zy}o`MKXI(FVD}d*nMr~D;w_}eHEZG$ zhr_RP5QLv+@+<&=KO+_~` zMF-egduWc#(C5vx_Gmzr4snVaI>)fAQ5YP-Im&S*wxySoa!KX;B}Vt@EY_7;UOXrB zPzWi%-Fq!V@$fF$llipa8Z!zCFagh_^+@lO8VWB~_i`rhgWk1nPJSboiJVbhEJnHD~@>4Fd+{I>d(zy^TXO~WU zD5m8kU&7VmhI^xazmom-NHa(lXM#q~3Q506Rf1F!7MogbWEHk*QSv&fi=Q+N87r^K z#D_EbTl|QD*i$INHSo^+hvf^XWT>e11%o|1Nyiy$61j$+Onu7sC13F}~l^mFe#@7ruL}>|%4GrcpuXO2GmOaJ4Qj>r1F!BR;gqM=;wyZ<)3$R9RBQQQ}MIBPE>h@2#5MiK*Y0cC zXYCoI7>MnRW_3K@^aX>kWL}KoMTxO+@rbF;@p%ughM&MIL}&J zv;W=C-%8rTy=;EBP!~@*ZZYg9s3TpuoHeF)X$@(#A0-#=c1eE{$uBZx#SoHpbc`WA z52}M=p};P?F2V0h8V)O-^YGo zRzkuWuY@OCq(}1nGCg@Wv&~vM+Os$3zQwm(7YSB6Hdo1#PuX5f_dRi+7%xv9y3gz2A8M>y8V&u6 zKFm_~a=2G#0dp`p9ASYny1k978{Z|_%LDRCsTW+Q*D6FwFK(thd3ngYL>|Y~kb~;?Dxa^YV9epQvYCLQ3we=zUpKajbE{3&den=n>nD`_Q#;RX`pFrVnvle)o&+dYzdJ_=NdGH{u_ zbNWZaF|(y>X1;^N4A$v>ij=IlWz3nm+&nz`_b{VG9T;XLKM08jsyn7EJE?eK>MYlx z{qlvr5!J2W9morM>E1MOZ{N#l_VLQ`vTd$oiB8uBG+@GqivpskSxUG%$%7E4$tW5 zi(+LDei}R*Jc^&NEGTJP?L9r*S9|fI0vM(thcJs~+Bx~ALHf$@ZpZ-3G#`&9`flic zqsLPARfP|&`sjpuCF0s(6+LV7h zC4*HjZ$177Up2+71E`B7dx9p(4bYEhMR#jjlEGe!7lW+*rPOegAz1{(T1ieFpx02L69=2EO~N G?f(Kus+KSS literal 0 HcmV?d00001 diff --git a/openvidu-recording-java/src/main/resources/static/index.html b/openvidu-recording-java/src/main/resources/static/index.html new file mode 100644 index 00000000..9fafc009 --- /dev/null +++ b/openvidu-recording-java/src/main/resources/static/index.html @@ -0,0 +1,99 @@ + + + + openvidu-recording-java + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+

Join a video session

+
+

+ + +

+

+ +

+
+
+
+
+ + +
+ +
+
+
OpenVidu © 2017
+ + + +
+
+ + + + \ No newline at end of file diff --git a/openvidu-recording-java/src/main/resources/static/openvidu-browser-1.8.0.js b/openvidu-recording-java/src/main/resources/static/openvidu-browser-1.8.0.js new file mode 100644 index 00000000..16abfc5a --- /dev/null +++ b/openvidu-recording-java/src/main/resources/static/openvidu-browser-1.8.0.js @@ -0,0 +1,15134 @@ +(function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + if (typeof console.trace === 'function') { + // not supported in IE 10 + console.trace(); + } + } + } + + return this; +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.once = function(type, listener) { + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + var fired = false; + + function g() { + this.removeListener(type, g); + + if (!fired) { + fired = true; + listener.apply(this, arguments); + } + } + + g.listener = listener; + this.on(type, g); + + return this; +}; + +// emits a 'removeListener' event iff the listener was removed +EventEmitter.prototype.removeListener = function(type, listener) { + var list, position, length, i; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events || !this._events[type]) + return this; + + list = this._events[type]; + length = list.length; + position = -1; + + if (list === listener || + (isFunction(list.listener) && list.listener === listener)) { + delete this._events[type]; + if (this._events.removeListener) + this.emit('removeListener', type, listener); + + } else if (isObject(list)) { + for (i = length; i-- > 0;) { + if (list[i] === listener || + (list[i].listener && list[i].listener === listener)) { + position = i; + break; + } + } + + if (position < 0) + return this; + + if (list.length === 1) { + list.length = 0; + delete this._events[type]; + } else { + list.splice(position, 1); + } + + if (this._events.removeListener) + this.emit('removeListener', type, listener); + } + + return this; +}; + +EventEmitter.prototype.removeAllListeners = function(type) { + var key, listeners; + + if (!this._events) + return this; + + // not listening for removeListener, no need to emit + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {}; + else if (this._events[type]) + delete this._events[type]; + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + for (key in this._events) { + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = {}; + return this; + } + + listeners = this._events[type]; + + if (isFunction(listeners)) { + this.removeListener(type, listeners); + } else if (listeners) { + // LIFO order + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]); + } + delete this._events[type]; + + return this; +}; + +EventEmitter.prototype.listeners = function(type) { + var ret; + if (!this._events || !this._events[type]) + ret = []; + else if (isFunction(this._events[type])) + ret = [this._events[type]]; + else + ret = this._events[type].slice(); + return ret; +}; + +EventEmitter.prototype.listenerCount = function(type) { + if (this._events) { + var evlistener = this._events[type]; + + if (isFunction(evlistener)) + return 1; + else if (evlistener) + return evlistener.length; + } + return 0; +}; + +EventEmitter.listenerCount = function(emitter, type) { + return emitter.listenerCount(type); +}; + +function isFunction(arg) { + return typeof arg === 'function'; +} + +function isNumber(arg) { + return typeof arg === 'number'; +} + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} + +function isUndefined(arg) { + return arg === void 0; +} + +},{}],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 = module.exports = 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; +}; + +},{"./stun.json":3,"./turn.json":4,"normalice":8}],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", + "stun.services.mozilla.com" +] + +},{}],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; + + //Setup Audio Context + if (!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.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) { + 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) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],7:[function(require,module,exports){ +/*! + * @name JavaScript/NodeJS Merge v1.2.0 + * @author yeikos + * @repository https://github.com/yeikos/js.merge + + * Copyright 2014 yeikos - MIT license + * https://raw.github.com/yeikos/js.merge/master/LICENSE + */ + +;(function(isNode) { + + /** + * Merge one or more objects + * @param bool? clone + * @param mixed,... arguments + * @return object + */ + + var Public = function(clone) { + + return merge(clone === true, false, arguments); + + }, publicName = 'merge'; + + /** + * Merge two or more objects recursively + * @param bool? clone + * @param mixed,... arguments + * @return object + */ + + Public.recursive = function(clone) { + + return merge(clone === true, true, arguments); + + }; + + /** + * Clone the input removing any reference + * @param mixed input + * @return mixed + */ + + Public.clone = function(input) { + + var output = input, + type = typeOf(input), + index, size; + + if (type === 'array') { + + output = []; + size = input.length; + + for (index=0;index 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; +}; + +},{}],9:[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; }; + +},{}],10:[function(require,module,exports){ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ +'use strict'; + +var SDPUtils = require('sdp'); + +function writeMediaSection(transceiver, caps, type, stream, dtlsRole) { + var sdp = SDPUtils.writeRtpDescription(transceiver.kind, caps); + + // Map ICE parameters (ufrag, pwd) to SDP. + sdp += SDPUtils.writeIceParameters( + transceiver.iceGatherer.getLocalParameters()); + + // Map DTLS parameters to SDP. + sdp += SDPUtils.writeDtlsParameters( + transceiver.dtlsTransport.getLocalParameters(), + type === 'offer' ? 'actpass' : dtlsRole || 'active'); + + sdp += 'a=mid:' + transceiver.mid + '\r\n'; + + if (transceiver.rtpSender && transceiver.rtpReceiver) { + sdp += 'a=sendrecv\r\n'; + } else if (transceiver.rtpSender) { + sdp += 'a=sendonly\r\n'; + } else if (transceiver.rtpReceiver) { + sdp += 'a=recvonly\r\n'; + } else { + sdp += 'a=inactive\r\n'; + } + + if (transceiver.rtpSender) { + var trackId = transceiver.rtpSender._initialTrackId || + transceiver.rtpSender.track.id; + transceiver.rtpSender._initialTrackId = trackId; + // spec. + var msid = 'msid:' + (stream ? stream.id : '-') + ' ' + + trackId + '\r\n'; + sdp += 'a=' + msid; + // for Chrome. Legacy should no longer be required. + sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc + + ' ' + msid; + + // RTX + if (transceiver.sendEncodingParameters[0].rtx) { + sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc + + ' ' + msid; + sdp += 'a=ssrc-group:FID ' + + transceiver.sendEncodingParameters[0].ssrc + ' ' + + transceiver.sendEncodingParameters[0].rtx.ssrc + + '\r\n'; + } + } + // FIXME: this should be written by writeRtpDescription. + sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc + + ' cname:' + SDPUtils.localCName + '\r\n'; + if (transceiver.rtpSender && transceiver.sendEncodingParameters[0].rtx) { + sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc + + ' cname:' + SDPUtils.localCName + '\r\n'; + } + return sdp; +} + +// Edge does not like +// 1) stun: filtered after 14393 unless ?transport=udp is present +// 2) turn: that does not have all of turn:host:port?transport=udp +// 3) turn: with ipv6 addresses +// 4) turn: occurring muliple times +function filterIceServers(iceServers, edgeVersion) { + var hasTurn = false; + iceServers = JSON.parse(JSON.stringify(iceServers)); + return iceServers.filter(function(server) { + if (server && (server.urls || server.url)) { + var urls = server.urls || server.url; + if (server.url && !server.urls) { + console.warn('RTCIceServer.url is deprecated! Use urls instead.'); + } + var isString = typeof urls === 'string'; + if (isString) { + urls = [urls]; + } + urls = urls.filter(function(url) { + var validTurn = url.indexOf('turn:') === 0 && + url.indexOf('transport=udp') !== -1 && + url.indexOf('turn:[') === -1 && + !hasTurn; + + if (validTurn) { + hasTurn = true; + return true; + } + return url.indexOf('stun:') === 0 && edgeVersion >= 14393 && + url.indexOf('?transport=udp') === -1; + }); + + delete server.url; + server.urls = isString ? urls[0] : urls; + return !!urls.length; + } + }); +} + +// Determines the intersection of local and remote capabilities. +function getCommonCapabilities(localCapabilities, remoteCapabilities) { + var commonCapabilities = { + codecs: [], + headerExtensions: [], + fecMechanisms: [] + }; + + var findCodecByPayloadType = function(pt, codecs) { + pt = parseInt(pt, 10); + for (var i = 0; i < codecs.length; i++) { + if (codecs[i].payloadType === pt || + codecs[i].preferredPayloadType === pt) { + return codecs[i]; + } + } + }; + + var rtxCapabilityMatches = function(lRtx, rRtx, lCodecs, rCodecs) { + var lCodec = findCodecByPayloadType(lRtx.parameters.apt, lCodecs); + var rCodec = findCodecByPayloadType(rRtx.parameters.apt, rCodecs); + return lCodec && rCodec && + lCodec.name.toLowerCase() === rCodec.name.toLowerCase(); + }; + + localCapabilities.codecs.forEach(function(lCodec) { + for (var i = 0; i < remoteCapabilities.codecs.length; i++) { + var rCodec = remoteCapabilities.codecs[i]; + if (lCodec.name.toLowerCase() === rCodec.name.toLowerCase() && + lCodec.clockRate === rCodec.clockRate) { + if (lCodec.name.toLowerCase() === 'rtx' && + lCodec.parameters && rCodec.parameters.apt) { + // for RTX we need to find the local rtx that has a apt + // which points to the same local codec as the remote one. + if (!rtxCapabilityMatches(lCodec, rCodec, + localCapabilities.codecs, remoteCapabilities.codecs)) { + continue; + } + } + rCodec = JSON.parse(JSON.stringify(rCodec)); // deepcopy + // number of channels is the highest common number of channels + rCodec.numChannels = Math.min(lCodec.numChannels, + rCodec.numChannels); + // push rCodec so we reply with offerer payload type + commonCapabilities.codecs.push(rCodec); + + // determine common feedback mechanisms + rCodec.rtcpFeedback = rCodec.rtcpFeedback.filter(function(fb) { + for (var j = 0; j < lCodec.rtcpFeedback.length; j++) { + if (lCodec.rtcpFeedback[j].type === fb.type && + lCodec.rtcpFeedback[j].parameter === fb.parameter) { + return true; + } + } + return false; + }); + // FIXME: also need to determine .parameters + // see https://github.com/openpeer/ortc/issues/569 + break; + } + } + }); + + localCapabilities.headerExtensions.forEach(function(lHeaderExtension) { + for (var i = 0; i < remoteCapabilities.headerExtensions.length; + i++) { + var rHeaderExtension = remoteCapabilities.headerExtensions[i]; + if (lHeaderExtension.uri === rHeaderExtension.uri) { + commonCapabilities.headerExtensions.push(rHeaderExtension); + break; + } + } + }); + + // FIXME: fecMechanisms + return commonCapabilities; +} + +// is action=setLocalDescription with type allowed in signalingState +function isActionAllowedInSignalingState(action, type, signalingState) { + return { + offer: { + setLocalDescription: ['stable', 'have-local-offer'], + setRemoteDescription: ['stable', 'have-remote-offer'] + }, + answer: { + setLocalDescription: ['have-remote-offer', 'have-local-pranswer'], + setRemoteDescription: ['have-local-offer', 'have-remote-pranswer'] + } + }[type][action].indexOf(signalingState) !== -1; +} + +function maybeAddCandidate(iceTransport, candidate) { + // Edge's internal representation adds some fields therefore + // not all fieldѕ are taken into account. + var alreadyAdded = iceTransport.getRemoteCandidates() + .find(function(remoteCandidate) { + return candidate.foundation === remoteCandidate.foundation && + candidate.ip === remoteCandidate.ip && + candidate.port === remoteCandidate.port && + candidate.priority === remoteCandidate.priority && + candidate.protocol === remoteCandidate.protocol && + candidate.type === remoteCandidate.type; + }); + if (!alreadyAdded) { + iceTransport.addRemoteCandidate(candidate); + } + return !alreadyAdded; +} + + +function makeError(name, description) { + var e = new Error(description); + e.name = name; + // legacy error codes from https://heycam.github.io/webidl/#idl-DOMException-error-names + e.code = { + NotSupportedError: 9, + InvalidStateError: 11, + InvalidAccessError: 15, + TypeError: undefined, + OperationError: undefined + }[name]; + return e; +} + +module.exports = function(window, edgeVersion) { + // https://w3c.github.io/mediacapture-main/#mediastream + // Helper function to add the track to the stream and + // dispatch the event ourselves. + function addTrackToStreamAndFireEvent(track, stream) { + stream.addTrack(track); + stream.dispatchEvent(new window.MediaStreamTrackEvent('addtrack', + {track: track})); + } + + function removeTrackFromStreamAndFireEvent(track, stream) { + stream.removeTrack(track); + stream.dispatchEvent(new window.MediaStreamTrackEvent('removetrack', + {track: track})); + } + + function fireAddTrack(pc, track, receiver, streams) { + var trackEvent = new Event('track'); + trackEvent.track = track; + trackEvent.receiver = receiver; + trackEvent.transceiver = {receiver: receiver}; + trackEvent.streams = streams; + window.setTimeout(function() { + pc._dispatchEvent('track', trackEvent); + }); + } + + var RTCPeerConnection = function(config) { + var pc = this; + + var _eventTarget = document.createDocumentFragment(); + ['addEventListener', 'removeEventListener', 'dispatchEvent'] + .forEach(function(method) { + pc[method] = _eventTarget[method].bind(_eventTarget); + }); + + this.canTrickleIceCandidates = null; + + this.needNegotiation = false; + + this.localStreams = []; + this.remoteStreams = []; + + this.localDescription = null; + this.remoteDescription = null; + + this.signalingState = 'stable'; + this.iceConnectionState = 'new'; + this.connectionState = 'new'; + this.iceGatheringState = 'new'; + + config = JSON.parse(JSON.stringify(config || {})); + + this.usingBundle = config.bundlePolicy === 'max-bundle'; + if (config.rtcpMuxPolicy === 'negotiate') { + throw(makeError('NotSupportedError', + 'rtcpMuxPolicy \'negotiate\' is not supported')); + } else if (!config.rtcpMuxPolicy) { + config.rtcpMuxPolicy = 'require'; + } + + switch (config.iceTransportPolicy) { + case 'all': + case 'relay': + break; + default: + config.iceTransportPolicy = 'all'; + break; + } + + switch (config.bundlePolicy) { + case 'balanced': + case 'max-compat': + case 'max-bundle': + break; + default: + config.bundlePolicy = 'balanced'; + break; + } + + config.iceServers = filterIceServers(config.iceServers || [], edgeVersion); + + this._iceGatherers = []; + if (config.iceCandidatePoolSize) { + for (var i = config.iceCandidatePoolSize; i > 0; i--) { + this._iceGatherers.push(new window.RTCIceGatherer({ + iceServers: config.iceServers, + gatherPolicy: config.iceTransportPolicy + })); + } + } else { + config.iceCandidatePoolSize = 0; + } + + this._config = config; + + // per-track iceGathers, iceTransports, dtlsTransports, rtpSenders, ... + // everything that is needed to describe a SDP m-line. + this.transceivers = []; + + this._sdpSessionId = SDPUtils.generateSessionId(); + this._sdpSessionVersion = 0; + + this._dtlsRole = undefined; // role for a=setup to use in answers. + + this._isClosed = false; + }; + + // set up event handlers on prototype + RTCPeerConnection.prototype.onicecandidate = null; + RTCPeerConnection.prototype.onaddstream = null; + RTCPeerConnection.prototype.ontrack = null; + RTCPeerConnection.prototype.onremovestream = null; + RTCPeerConnection.prototype.onsignalingstatechange = null; + RTCPeerConnection.prototype.oniceconnectionstatechange = null; + RTCPeerConnection.prototype.onconnectionstatechange = null; + RTCPeerConnection.prototype.onicegatheringstatechange = null; + RTCPeerConnection.prototype.onnegotiationneeded = null; + RTCPeerConnection.prototype.ondatachannel = null; + + RTCPeerConnection.prototype._dispatchEvent = function(name, event) { + if (this._isClosed) { + return; + } + this.dispatchEvent(event); + if (typeof this['on' + name] === 'function') { + this['on' + name](event); + } + }; + + RTCPeerConnection.prototype._emitGatheringStateChange = function() { + var event = new Event('icegatheringstatechange'); + this._dispatchEvent('icegatheringstatechange', event); + }; + + RTCPeerConnection.prototype.getConfiguration = function() { + return this._config; + }; + + RTCPeerConnection.prototype.getLocalStreams = function() { + return this.localStreams; + }; + + RTCPeerConnection.prototype.getRemoteStreams = function() { + return this.remoteStreams; + }; + + // internal helper to create a transceiver object. + // (which is not yet the same as the WebRTC 1.0 transceiver) + RTCPeerConnection.prototype._createTransceiver = function(kind, doNotAdd) { + var hasBundleTransport = this.transceivers.length > 0; + var transceiver = { + track: null, + iceGatherer: null, + iceTransport: null, + dtlsTransport: null, + localCapabilities: null, + remoteCapabilities: null, + rtpSender: null, + rtpReceiver: null, + kind: kind, + mid: null, + sendEncodingParameters: null, + recvEncodingParameters: null, + stream: null, + associatedRemoteMediaStreams: [], + wantReceive: true + }; + if (this.usingBundle && hasBundleTransport) { + transceiver.iceTransport = this.transceivers[0].iceTransport; + transceiver.dtlsTransport = this.transceivers[0].dtlsTransport; + } else { + var transports = this._createIceAndDtlsTransports(); + transceiver.iceTransport = transports.iceTransport; + transceiver.dtlsTransport = transports.dtlsTransport; + } + if (!doNotAdd) { + this.transceivers.push(transceiver); + } + return transceiver; + }; + + RTCPeerConnection.prototype.addTrack = function(track, stream) { + if (this._isClosed) { + throw makeError('InvalidStateError', + 'Attempted to call addTrack on a closed peerconnection.'); + } + + var alreadyExists = this.transceivers.find(function(s) { + return s.track === track; + }); + + if (alreadyExists) { + throw makeError('InvalidAccessError', 'Track already exists.'); + } + + var transceiver; + for (var i = 0; i < this.transceivers.length; i++) { + if (!this.transceivers[i].track && + this.transceivers[i].kind === track.kind) { + transceiver = this.transceivers[i]; + } + } + if (!transceiver) { + transceiver = this._createTransceiver(track.kind); + } + + this._maybeFireNegotiationNeeded(); + + if (this.localStreams.indexOf(stream) === -1) { + this.localStreams.push(stream); + } + + transceiver.track = track; + transceiver.stream = stream; + transceiver.rtpSender = new window.RTCRtpSender(track, + transceiver.dtlsTransport); + return transceiver.rtpSender; + }; + + RTCPeerConnection.prototype.addStream = function(stream) { + var pc = this; + if (edgeVersion >= 15025) { + stream.getTracks().forEach(function(track) { + pc.addTrack(track, stream); + }); + } else { + // Clone is necessary for local demos mostly, attaching directly + // to two different senders does not work (build 10547). + // Fixed in 15025 (or earlier) + var clonedStream = stream.clone(); + stream.getTracks().forEach(function(track, idx) { + var clonedTrack = clonedStream.getTracks()[idx]; + track.addEventListener('enabled', function(event) { + clonedTrack.enabled = event.enabled; + }); + }); + clonedStream.getTracks().forEach(function(track) { + pc.addTrack(track, clonedStream); + }); + } + }; + + RTCPeerConnection.prototype.removeTrack = function(sender) { + if (this._isClosed) { + throw makeError('InvalidStateError', + 'Attempted to call removeTrack on a closed peerconnection.'); + } + + if (!(sender instanceof window.RTCRtpSender)) { + throw new TypeError('Argument 1 of RTCPeerConnection.removeTrack ' + + 'does not implement interface RTCRtpSender.'); + } + + var transceiver = this.transceivers.find(function(t) { + return t.rtpSender === sender; + }); + + if (!transceiver) { + throw makeError('InvalidAccessError', + 'Sender was not created by this connection.'); + } + var stream = transceiver.stream; + + transceiver.rtpSender.stop(); + transceiver.rtpSender = null; + transceiver.track = null; + transceiver.stream = null; + + // remove the stream from the set of local streams + var localStreams = this.transceivers.map(function(t) { + return t.stream; + }); + if (localStreams.indexOf(stream) === -1 && + this.localStreams.indexOf(stream) > -1) { + this.localStreams.splice(this.localStreams.indexOf(stream), 1); + } + + this._maybeFireNegotiationNeeded(); + }; + + RTCPeerConnection.prototype.removeStream = function(stream) { + var pc = this; + stream.getTracks().forEach(function(track) { + var sender = pc.getSenders().find(function(s) { + return s.track === track; + }); + if (sender) { + pc.removeTrack(sender); + } + }); + }; + + RTCPeerConnection.prototype.getSenders = function() { + return this.transceivers.filter(function(transceiver) { + return !!transceiver.rtpSender; + }) + .map(function(transceiver) { + return transceiver.rtpSender; + }); + }; + + RTCPeerConnection.prototype.getReceivers = function() { + return this.transceivers.filter(function(transceiver) { + return !!transceiver.rtpReceiver; + }) + .map(function(transceiver) { + return transceiver.rtpReceiver; + }); + }; + + + RTCPeerConnection.prototype._createIceGatherer = function(sdpMLineIndex, + usingBundle) { + var pc = this; + if (usingBundle && sdpMLineIndex > 0) { + return this.transceivers[0].iceGatherer; + } else if (this._iceGatherers.length) { + return this._iceGatherers.shift(); + } + var iceGatherer = new window.RTCIceGatherer({ + iceServers: this._config.iceServers, + gatherPolicy: this._config.iceTransportPolicy + }); + Object.defineProperty(iceGatherer, 'state', + {value: 'new', writable: true} + ); + + this.transceivers[sdpMLineIndex].bufferedCandidateEvents = []; + this.transceivers[sdpMLineIndex].bufferCandidates = function(event) { + var end = !event.candidate || Object.keys(event.candidate).length === 0; + // polyfill since RTCIceGatherer.state is not implemented in + // Edge 10547 yet. + iceGatherer.state = end ? 'completed' : 'gathering'; + if (pc.transceivers[sdpMLineIndex].bufferedCandidateEvents !== null) { + pc.transceivers[sdpMLineIndex].bufferedCandidateEvents.push(event); + } + }; + iceGatherer.addEventListener('localcandidate', + this.transceivers[sdpMLineIndex].bufferCandidates); + return iceGatherer; + }; + + // start gathering from an RTCIceGatherer. + RTCPeerConnection.prototype._gather = function(mid, sdpMLineIndex) { + var pc = this; + var iceGatherer = this.transceivers[sdpMLineIndex].iceGatherer; + if (iceGatherer.onlocalcandidate) { + return; + } + var bufferedCandidateEvents = + this.transceivers[sdpMLineIndex].bufferedCandidateEvents; + this.transceivers[sdpMLineIndex].bufferedCandidateEvents = null; + iceGatherer.removeEventListener('localcandidate', + this.transceivers[sdpMLineIndex].bufferCandidates); + iceGatherer.onlocalcandidate = function(evt) { + if (pc.usingBundle && sdpMLineIndex > 0) { + // if we know that we use bundle we can drop candidates with + // ѕdpMLineIndex > 0. If we don't do this then our state gets + // confused since we dispose the extra ice gatherer. + return; + } + var event = new Event('icecandidate'); + event.candidate = {sdpMid: mid, sdpMLineIndex: sdpMLineIndex}; + + var cand = evt.candidate; + // Edge emits an empty object for RTCIceCandidateComplete‥ + var end = !cand || Object.keys(cand).length === 0; + if (end) { + // polyfill since RTCIceGatherer.state is not implemented in + // Edge 10547 yet. + if (iceGatherer.state === 'new' || iceGatherer.state === 'gathering') { + iceGatherer.state = 'completed'; + } + } else { + if (iceGatherer.state === 'new') { + iceGatherer.state = 'gathering'; + } + // RTCIceCandidate doesn't have a component, needs to be added + cand.component = 1; + var serializedCandidate = SDPUtils.writeCandidate(cand); + event.candidate = Object.assign(event.candidate, + SDPUtils.parseCandidate(serializedCandidate)); + event.candidate.candidate = serializedCandidate; + } + + // update local description. + var sections = SDPUtils.getMediaSections(pc.localDescription.sdp); + if (!end) { + sections[event.candidate.sdpMLineIndex] += + 'a=' + event.candidate.candidate + '\r\n'; + } else { + sections[event.candidate.sdpMLineIndex] += + 'a=end-of-candidates\r\n'; + } + pc.localDescription.sdp = + SDPUtils.getDescription(pc.localDescription.sdp) + + sections.join(''); + var complete = pc.transceivers.every(function(transceiver) { + return transceiver.iceGatherer && + transceiver.iceGatherer.state === 'completed'; + }); + + if (pc.iceGatheringState !== 'gathering') { + pc.iceGatheringState = 'gathering'; + pc._emitGatheringStateChange(); + } + + // Emit candidate. Also emit null candidate when all gatherers are + // complete. + if (!end) { + pc._dispatchEvent('icecandidate', event); + } + if (complete) { + pc._dispatchEvent('icecandidate', new Event('icecandidate')); + pc.iceGatheringState = 'complete'; + pc._emitGatheringStateChange(); + } + }; + + // emit already gathered candidates. + window.setTimeout(function() { + bufferedCandidateEvents.forEach(function(e) { + iceGatherer.onlocalcandidate(e); + }); + }, 0); + }; + + // Create ICE transport and DTLS transport. + RTCPeerConnection.prototype._createIceAndDtlsTransports = function() { + var pc = this; + var iceTransport = new window.RTCIceTransport(null); + iceTransport.onicestatechange = function() { + pc._updateIceConnectionState(); + pc._updateConnectionState(); + }; + + var dtlsTransport = new window.RTCDtlsTransport(iceTransport); + dtlsTransport.ondtlsstatechange = function() { + pc._updateConnectionState(); + }; + dtlsTransport.onerror = function() { + // onerror does not set state to failed by itself. + Object.defineProperty(dtlsTransport, 'state', + {value: 'failed', writable: true}); + pc._updateConnectionState(); + }; + + return { + iceTransport: iceTransport, + dtlsTransport: dtlsTransport + }; + }; + + // Destroy ICE gatherer, ICE transport and DTLS transport. + // Without triggering the callbacks. + RTCPeerConnection.prototype._disposeIceAndDtlsTransports = function( + sdpMLineIndex) { + var iceGatherer = this.transceivers[sdpMLineIndex].iceGatherer; + if (iceGatherer) { + delete iceGatherer.onlocalcandidate; + delete this.transceivers[sdpMLineIndex].iceGatherer; + } + var iceTransport = this.transceivers[sdpMLineIndex].iceTransport; + if (iceTransport) { + delete iceTransport.onicestatechange; + delete this.transceivers[sdpMLineIndex].iceTransport; + } + var dtlsTransport = this.transceivers[sdpMLineIndex].dtlsTransport; + if (dtlsTransport) { + delete dtlsTransport.ondtlsstatechange; + delete dtlsTransport.onerror; + delete this.transceivers[sdpMLineIndex].dtlsTransport; + } + }; + + // Start the RTP Sender and Receiver for a transceiver. + RTCPeerConnection.prototype._transceive = function(transceiver, + send, recv) { + var params = getCommonCapabilities(transceiver.localCapabilities, + transceiver.remoteCapabilities); + if (send && transceiver.rtpSender) { + params.encodings = transceiver.sendEncodingParameters; + params.rtcp = { + cname: SDPUtils.localCName, + compound: transceiver.rtcpParameters.compound + }; + if (transceiver.recvEncodingParameters.length) { + params.rtcp.ssrc = transceiver.recvEncodingParameters[0].ssrc; + } + transceiver.rtpSender.send(params); + } + if (recv && transceiver.rtpReceiver && params.codecs.length > 0) { + // remove RTX field in Edge 14942 + if (transceiver.kind === 'video' + && transceiver.recvEncodingParameters + && edgeVersion < 15019) { + transceiver.recvEncodingParameters.forEach(function(p) { + delete p.rtx; + }); + } + if (transceiver.recvEncodingParameters.length) { + params.encodings = transceiver.recvEncodingParameters; + } else { + params.encodings = [{}]; + } + params.rtcp = { + compound: transceiver.rtcpParameters.compound + }; + if (transceiver.rtcpParameters.cname) { + params.rtcp.cname = transceiver.rtcpParameters.cname; + } + if (transceiver.sendEncodingParameters.length) { + params.rtcp.ssrc = transceiver.sendEncodingParameters[0].ssrc; + } + transceiver.rtpReceiver.receive(params); + } + }; + + RTCPeerConnection.prototype.setLocalDescription = function(description) { + var pc = this; + + // Note: pranswer is not supported. + if (['offer', 'answer'].indexOf(description.type) === -1) { + return Promise.reject(makeError('TypeError', + 'Unsupported type "' + description.type + '"')); + } + + if (!isActionAllowedInSignalingState('setLocalDescription', + description.type, pc.signalingState) || pc._isClosed) { + return Promise.reject(makeError('InvalidStateError', + 'Can not set local ' + description.type + + ' in state ' + pc.signalingState)); + } + + var sections; + var sessionpart; + if (description.type === 'offer') { + // VERY limited support for SDP munging. Limited to: + // * changing the order of codecs + sections = SDPUtils.splitSections(description.sdp); + sessionpart = sections.shift(); + sections.forEach(function(mediaSection, sdpMLineIndex) { + var caps = SDPUtils.parseRtpParameters(mediaSection); + pc.transceivers[sdpMLineIndex].localCapabilities = caps; + }); + + pc.transceivers.forEach(function(transceiver, sdpMLineIndex) { + pc._gather(transceiver.mid, sdpMLineIndex); + }); + } else if (description.type === 'answer') { + sections = SDPUtils.splitSections(pc.remoteDescription.sdp); + sessionpart = sections.shift(); + var isIceLite = SDPUtils.matchPrefix(sessionpart, + 'a=ice-lite').length > 0; + sections.forEach(function(mediaSection, sdpMLineIndex) { + var transceiver = pc.transceivers[sdpMLineIndex]; + var iceGatherer = transceiver.iceGatherer; + var iceTransport = transceiver.iceTransport; + var dtlsTransport = transceiver.dtlsTransport; + var localCapabilities = transceiver.localCapabilities; + var remoteCapabilities = transceiver.remoteCapabilities; + + // treat bundle-only as not-rejected. + var rejected = SDPUtils.isRejected(mediaSection) && + SDPUtils.matchPrefix(mediaSection, 'a=bundle-only').length === 0; + + if (!rejected && !transceiver.rejected) { + var remoteIceParameters = SDPUtils.getIceParameters( + mediaSection, sessionpart); + var remoteDtlsParameters = SDPUtils.getDtlsParameters( + mediaSection, sessionpart); + if (isIceLite) { + remoteDtlsParameters.role = 'server'; + } + + if (!pc.usingBundle || sdpMLineIndex === 0) { + pc._gather(transceiver.mid, sdpMLineIndex); + if (iceTransport.state === 'new') { + iceTransport.start(iceGatherer, remoteIceParameters, + isIceLite ? 'controlling' : 'controlled'); + } + if (dtlsTransport.state === 'new') { + dtlsTransport.start(remoteDtlsParameters); + } + } + + // Calculate intersection of capabilities. + var params = getCommonCapabilities(localCapabilities, + remoteCapabilities); + + // Start the RTCRtpSender. The RTCRtpReceiver for this + // transceiver has already been started in setRemoteDescription. + pc._transceive(transceiver, + params.codecs.length > 0, + false); + } + }); + } + + pc.localDescription = { + type: description.type, + sdp: description.sdp + }; + if (description.type === 'offer') { + pc._updateSignalingState('have-local-offer'); + } else { + pc._updateSignalingState('stable'); + } + + return Promise.resolve(); + }; + + RTCPeerConnection.prototype.setRemoteDescription = function(description) { + var pc = this; + + // Note: pranswer is not supported. + if (['offer', 'answer'].indexOf(description.type) === -1) { + return Promise.reject(makeError('TypeError', + 'Unsupported type "' + description.type + '"')); + } + + if (!isActionAllowedInSignalingState('setRemoteDescription', + description.type, pc.signalingState) || pc._isClosed) { + return Promise.reject(makeError('InvalidStateError', + 'Can not set remote ' + description.type + + ' in state ' + pc.signalingState)); + } + + var streams = {}; + pc.remoteStreams.forEach(function(stream) { + streams[stream.id] = stream; + }); + var receiverList = []; + var sections = SDPUtils.splitSections(description.sdp); + var sessionpart = sections.shift(); + var isIceLite = SDPUtils.matchPrefix(sessionpart, + 'a=ice-lite').length > 0; + var usingBundle = SDPUtils.matchPrefix(sessionpart, + 'a=group:BUNDLE ').length > 0; + pc.usingBundle = usingBundle; + var iceOptions = SDPUtils.matchPrefix(sessionpart, + 'a=ice-options:')[0]; + if (iceOptions) { + pc.canTrickleIceCandidates = iceOptions.substr(14).split(' ') + .indexOf('trickle') >= 0; + } else { + pc.canTrickleIceCandidates = false; + } + + sections.forEach(function(mediaSection, sdpMLineIndex) { + var lines = SDPUtils.splitLines(mediaSection); + var kind = SDPUtils.getKind(mediaSection); + // treat bundle-only as not-rejected. + var rejected = SDPUtils.isRejected(mediaSection) && + SDPUtils.matchPrefix(mediaSection, 'a=bundle-only').length === 0; + var protocol = lines[0].substr(2).split(' ')[2]; + + var direction = SDPUtils.getDirection(mediaSection, sessionpart); + var remoteMsid = SDPUtils.parseMsid(mediaSection); + + var mid = SDPUtils.getMid(mediaSection) || SDPUtils.generateIdentifier(); + + // Reject datachannels which are not implemented yet. + if ((kind === 'application' && protocol === 'DTLS/SCTP') || rejected) { + // TODO: this is dangerous in the case where a non-rejected m-line + // becomes rejected. + pc.transceivers[sdpMLineIndex] = { + mid: mid, + kind: kind, + rejected: true + }; + return; + } + + if (!rejected && pc.transceivers[sdpMLineIndex] && + pc.transceivers[sdpMLineIndex].rejected) { + // recycle a rejected transceiver. + pc.transceivers[sdpMLineIndex] = pc._createTransceiver(kind, true); + } + + var transceiver; + var iceGatherer; + var iceTransport; + var dtlsTransport; + var rtpReceiver; + var sendEncodingParameters; + var recvEncodingParameters; + var localCapabilities; + + var track; + // FIXME: ensure the mediaSection has rtcp-mux set. + var remoteCapabilities = SDPUtils.parseRtpParameters(mediaSection); + var remoteIceParameters; + var remoteDtlsParameters; + if (!rejected) { + remoteIceParameters = SDPUtils.getIceParameters(mediaSection, + sessionpart); + remoteDtlsParameters = SDPUtils.getDtlsParameters(mediaSection, + sessionpart); + remoteDtlsParameters.role = 'client'; + } + recvEncodingParameters = + SDPUtils.parseRtpEncodingParameters(mediaSection); + + var rtcpParameters = SDPUtils.parseRtcpParameters(mediaSection); + + var isComplete = SDPUtils.matchPrefix(mediaSection, + 'a=end-of-candidates', sessionpart).length > 0; + var cands = SDPUtils.matchPrefix(mediaSection, 'a=candidate:') + .map(function(cand) { + return SDPUtils.parseCandidate(cand); + }) + .filter(function(cand) { + return cand.component === 1; + }); + + // Check if we can use BUNDLE and dispose transports. + if ((description.type === 'offer' || description.type === 'answer') && + !rejected && usingBundle && sdpMLineIndex > 0 && + pc.transceivers[sdpMLineIndex]) { + pc._disposeIceAndDtlsTransports(sdpMLineIndex); + pc.transceivers[sdpMLineIndex].iceGatherer = + pc.transceivers[0].iceGatherer; + pc.transceivers[sdpMLineIndex].iceTransport = + pc.transceivers[0].iceTransport; + pc.transceivers[sdpMLineIndex].dtlsTransport = + pc.transceivers[0].dtlsTransport; + if (pc.transceivers[sdpMLineIndex].rtpSender) { + pc.transceivers[sdpMLineIndex].rtpSender.setTransport( + pc.transceivers[0].dtlsTransport); + } + if (pc.transceivers[sdpMLineIndex].rtpReceiver) { + pc.transceivers[sdpMLineIndex].rtpReceiver.setTransport( + pc.transceivers[0].dtlsTransport); + } + } + if (description.type === 'offer' && !rejected) { + transceiver = pc.transceivers[sdpMLineIndex] || + pc._createTransceiver(kind); + transceiver.mid = mid; + + if (!transceiver.iceGatherer) { + transceiver.iceGatherer = pc._createIceGatherer(sdpMLineIndex, + usingBundle); + } + + if (cands.length && transceiver.iceTransport.state === 'new') { + if (isComplete && (!usingBundle || sdpMLineIndex === 0)) { + transceiver.iceTransport.setRemoteCandidates(cands); + } else { + cands.forEach(function(candidate) { + maybeAddCandidate(transceiver.iceTransport, candidate); + }); + } + } + + localCapabilities = window.RTCRtpReceiver.getCapabilities(kind); + + // filter RTX until additional stuff needed for RTX is implemented + // in adapter.js + if (edgeVersion < 15019) { + localCapabilities.codecs = localCapabilities.codecs.filter( + function(codec) { + return codec.name !== 'rtx'; + }); + } + + sendEncodingParameters = transceiver.sendEncodingParameters || [{ + ssrc: (2 * sdpMLineIndex + 2) * 1001 + }]; + + // TODO: rewrite to use http://w3c.github.io/webrtc-pc/#set-associated-remote-streams + var isNewTrack = false; + if (direction === 'sendrecv' || direction === 'sendonly') { + isNewTrack = !transceiver.rtpReceiver; + rtpReceiver = transceiver.rtpReceiver || + new window.RTCRtpReceiver(transceiver.dtlsTransport, kind); + + if (isNewTrack) { + var stream; + track = rtpReceiver.track; + // FIXME: does not work with Plan B. + if (remoteMsid && remoteMsid.stream === '-') { + // no-op. a stream id of '-' means: no associated stream. + } else if (remoteMsid) { + if (!streams[remoteMsid.stream]) { + streams[remoteMsid.stream] = new window.MediaStream(); + Object.defineProperty(streams[remoteMsid.stream], 'id', { + get: function() { + return remoteMsid.stream; + } + }); + } + Object.defineProperty(track, 'id', { + get: function() { + return remoteMsid.track; + } + }); + stream = streams[remoteMsid.stream]; + } else { + if (!streams.default) { + streams.default = new window.MediaStream(); + } + stream = streams.default; + } + if (stream) { + addTrackToStreamAndFireEvent(track, stream); + transceiver.associatedRemoteMediaStreams.push(stream); + } + receiverList.push([track, rtpReceiver, stream]); + } + } else if (transceiver.rtpReceiver && transceiver.rtpReceiver.track) { + transceiver.associatedRemoteMediaStreams.forEach(function(s) { + var nativeTrack = s.getTracks().find(function(t) { + return t.id === transceiver.rtpReceiver.track.id; + }); + if (nativeTrack) { + removeTrackFromStreamAndFireEvent(nativeTrack, s); + } + }); + transceiver.associatedRemoteMediaStreams = []; + } + + transceiver.localCapabilities = localCapabilities; + transceiver.remoteCapabilities = remoteCapabilities; + transceiver.rtpReceiver = rtpReceiver; + transceiver.rtcpParameters = rtcpParameters; + transceiver.sendEncodingParameters = sendEncodingParameters; + transceiver.recvEncodingParameters = recvEncodingParameters; + + // Start the RTCRtpReceiver now. The RTPSender is started in + // setLocalDescription. + pc._transceive(pc.transceivers[sdpMLineIndex], + false, + isNewTrack); + } else if (description.type === 'answer' && !rejected) { + transceiver = pc.transceivers[sdpMLineIndex]; + iceGatherer = transceiver.iceGatherer; + iceTransport = transceiver.iceTransport; + dtlsTransport = transceiver.dtlsTransport; + rtpReceiver = transceiver.rtpReceiver; + sendEncodingParameters = transceiver.sendEncodingParameters; + localCapabilities = transceiver.localCapabilities; + + pc.transceivers[sdpMLineIndex].recvEncodingParameters = + recvEncodingParameters; + pc.transceivers[sdpMLineIndex].remoteCapabilities = + remoteCapabilities; + pc.transceivers[sdpMLineIndex].rtcpParameters = rtcpParameters; + + if (cands.length && iceTransport.state === 'new') { + if ((isIceLite || isComplete) && + (!usingBundle || sdpMLineIndex === 0)) { + iceTransport.setRemoteCandidates(cands); + } else { + cands.forEach(function(candidate) { + maybeAddCandidate(transceiver.iceTransport, candidate); + }); + } + } + + if (!usingBundle || sdpMLineIndex === 0) { + if (iceTransport.state === 'new') { + iceTransport.start(iceGatherer, remoteIceParameters, + 'controlling'); + } + if (dtlsTransport.state === 'new') { + dtlsTransport.start(remoteDtlsParameters); + } + } + + pc._transceive(transceiver, + direction === 'sendrecv' || direction === 'recvonly', + direction === 'sendrecv' || direction === 'sendonly'); + + // TODO: rewrite to use http://w3c.github.io/webrtc-pc/#set-associated-remote-streams + if (rtpReceiver && + (direction === 'sendrecv' || direction === 'sendonly')) { + track = rtpReceiver.track; + if (remoteMsid) { + if (!streams[remoteMsid.stream]) { + streams[remoteMsid.stream] = new window.MediaStream(); + } + addTrackToStreamAndFireEvent(track, streams[remoteMsid.stream]); + receiverList.push([track, rtpReceiver, streams[remoteMsid.stream]]); + } else { + if (!streams.default) { + streams.default = new window.MediaStream(); + } + addTrackToStreamAndFireEvent(track, streams.default); + receiverList.push([track, rtpReceiver, streams.default]); + } + } else { + // FIXME: actually the receiver should be created later. + delete transceiver.rtpReceiver; + } + } + }); + + if (pc._dtlsRole === undefined) { + pc._dtlsRole = description.type === 'offer' ? 'active' : 'passive'; + } + + pc.remoteDescription = { + type: description.type, + sdp: description.sdp + }; + if (description.type === 'offer') { + pc._updateSignalingState('have-remote-offer'); + } else { + pc._updateSignalingState('stable'); + } + Object.keys(streams).forEach(function(sid) { + var stream = streams[sid]; + if (stream.getTracks().length) { + if (pc.remoteStreams.indexOf(stream) === -1) { + pc.remoteStreams.push(stream); + var event = new Event('addstream'); + event.stream = stream; + window.setTimeout(function() { + pc._dispatchEvent('addstream', event); + }); + } + + receiverList.forEach(function(item) { + var track = item[0]; + var receiver = item[1]; + if (stream.id !== item[2].id) { + return; + } + fireAddTrack(pc, track, receiver, [stream]); + }); + } + }); + receiverList.forEach(function(item) { + if (item[2]) { + return; + } + fireAddTrack(pc, item[0], item[1], []); + }); + + // check whether addIceCandidate({}) was called within four seconds after + // setRemoteDescription. + window.setTimeout(function() { + if (!(pc && pc.transceivers)) { + return; + } + pc.transceivers.forEach(function(transceiver) { + if (transceiver.iceTransport && + transceiver.iceTransport.state === 'new' && + transceiver.iceTransport.getRemoteCandidates().length > 0) { + console.warn('Timeout for addRemoteCandidate. Consider sending ' + + 'an end-of-candidates notification'); + transceiver.iceTransport.addRemoteCandidate({}); + } + }); + }, 4000); + + return Promise.resolve(); + }; + + RTCPeerConnection.prototype.close = function() { + this.transceivers.forEach(function(transceiver) { + /* not yet + if (transceiver.iceGatherer) { + transceiver.iceGatherer.close(); + } + */ + if (transceiver.iceTransport) { + transceiver.iceTransport.stop(); + } + if (transceiver.dtlsTransport) { + transceiver.dtlsTransport.stop(); + } + if (transceiver.rtpSender) { + transceiver.rtpSender.stop(); + } + if (transceiver.rtpReceiver) { + transceiver.rtpReceiver.stop(); + } + }); + // FIXME: clean up tracks, local streams, remote streams, etc + this._isClosed = true; + this._updateSignalingState('closed'); + }; + + // Update the signaling state. + RTCPeerConnection.prototype._updateSignalingState = function(newState) { + this.signalingState = newState; + var event = new Event('signalingstatechange'); + this._dispatchEvent('signalingstatechange', event); + }; + + // Determine whether to fire the negotiationneeded event. + RTCPeerConnection.prototype._maybeFireNegotiationNeeded = function() { + var pc = this; + if (this.signalingState !== 'stable' || this.needNegotiation === true) { + return; + } + this.needNegotiation = true; + window.setTimeout(function() { + if (pc.needNegotiation) { + pc.needNegotiation = false; + var event = new Event('negotiationneeded'); + pc._dispatchEvent('negotiationneeded', event); + } + }, 0); + }; + + // Update the ice connection state. + RTCPeerConnection.prototype._updateIceConnectionState = function() { + var newState; + var states = { + 'new': 0, + closed: 0, + checking: 0, + connected: 0, + completed: 0, + disconnected: 0, + failed: 0 + }; + this.transceivers.forEach(function(transceiver) { + states[transceiver.iceTransport.state]++; + }); + + newState = 'new'; + if (states.failed > 0) { + newState = 'failed'; + } else if (states.checking > 0) { + newState = 'checking'; + } else if (states.disconnected > 0) { + newState = 'disconnected'; + } else if (states.new > 0) { + newState = 'new'; + } else if (states.connected > 0) { + newState = 'connected'; + } else if (states.completed > 0) { + newState = 'completed'; + } + + if (newState !== this.iceConnectionState) { + this.iceConnectionState = newState; + var event = new Event('iceconnectionstatechange'); + this._dispatchEvent('iceconnectionstatechange', event); + } + }; + + // Update the connection state. + RTCPeerConnection.prototype._updateConnectionState = function() { + var newState; + var states = { + 'new': 0, + closed: 0, + connecting: 0, + connected: 0, + completed: 0, + disconnected: 0, + failed: 0 + }; + this.transceivers.forEach(function(transceiver) { + states[transceiver.iceTransport.state]++; + states[transceiver.dtlsTransport.state]++; + }); + // ICETransport.completed and connected are the same for this purpose. + states.connected += states.completed; + + newState = 'new'; + if (states.failed > 0) { + newState = 'failed'; + } else if (states.connecting > 0) { + newState = 'connecting'; + } else if (states.disconnected > 0) { + newState = 'disconnected'; + } else if (states.new > 0) { + newState = 'new'; + } else if (states.connected > 0) { + newState = 'connected'; + } + + if (newState !== this.connectionState) { + this.connectionState = newState; + var event = new Event('connectionstatechange'); + this._dispatchEvent('connectionstatechange', event); + } + }; + + RTCPeerConnection.prototype.createOffer = function() { + var pc = this; + + if (pc._isClosed) { + return Promise.reject(makeError('InvalidStateError', + 'Can not call createOffer after close')); + } + + var numAudioTracks = pc.transceivers.filter(function(t) { + return t.kind === 'audio'; + }).length; + var numVideoTracks = pc.transceivers.filter(function(t) { + return t.kind === 'video'; + }).length; + + // Determine number of audio and video tracks we need to send/recv. + var offerOptions = arguments[0]; + if (offerOptions) { + // Reject Chrome legacy constraints. + if (offerOptions.mandatory || offerOptions.optional) { + throw new TypeError( + 'Legacy mandatory/optional constraints not supported.'); + } + if (offerOptions.offerToReceiveAudio !== undefined) { + if (offerOptions.offerToReceiveAudio === true) { + numAudioTracks = 1; + } else if (offerOptions.offerToReceiveAudio === false) { + numAudioTracks = 0; + } else { + numAudioTracks = offerOptions.offerToReceiveAudio; + } + } + if (offerOptions.offerToReceiveVideo !== undefined) { + if (offerOptions.offerToReceiveVideo === true) { + numVideoTracks = 1; + } else if (offerOptions.offerToReceiveVideo === false) { + numVideoTracks = 0; + } else { + numVideoTracks = offerOptions.offerToReceiveVideo; + } + } + } + + pc.transceivers.forEach(function(transceiver) { + if (transceiver.kind === 'audio') { + numAudioTracks--; + if (numAudioTracks < 0) { + transceiver.wantReceive = false; + } + } else if (transceiver.kind === 'video') { + numVideoTracks--; + if (numVideoTracks < 0) { + transceiver.wantReceive = false; + } + } + }); + + // Create M-lines for recvonly streams. + while (numAudioTracks > 0 || numVideoTracks > 0) { + if (numAudioTracks > 0) { + pc._createTransceiver('audio'); + numAudioTracks--; + } + if (numVideoTracks > 0) { + pc._createTransceiver('video'); + numVideoTracks--; + } + } + + var sdp = SDPUtils.writeSessionBoilerplate(pc._sdpSessionId, + pc._sdpSessionVersion++); + pc.transceivers.forEach(function(transceiver, sdpMLineIndex) { + // For each track, create an ice gatherer, ice transport, + // dtls transport, potentially rtpsender and rtpreceiver. + var track = transceiver.track; + var kind = transceiver.kind; + var mid = transceiver.mid || SDPUtils.generateIdentifier(); + transceiver.mid = mid; + + if (!transceiver.iceGatherer) { + transceiver.iceGatherer = pc._createIceGatherer(sdpMLineIndex, + pc.usingBundle); + } + + var localCapabilities = window.RTCRtpSender.getCapabilities(kind); + // filter RTX until additional stuff needed for RTX is implemented + // in adapter.js + if (edgeVersion < 15019) { + localCapabilities.codecs = localCapabilities.codecs.filter( + function(codec) { + return codec.name !== 'rtx'; + }); + } + localCapabilities.codecs.forEach(function(codec) { + // work around https://bugs.chromium.org/p/webrtc/issues/detail?id=6552 + // by adding level-asymmetry-allowed=1 + if (codec.name === 'H264' && + codec.parameters['level-asymmetry-allowed'] === undefined) { + codec.parameters['level-asymmetry-allowed'] = '1'; + } + + // for subsequent offers, we might have to re-use the payload + // type of the last offer. + if (transceiver.remoteCapabilities && + transceiver.remoteCapabilities.codecs) { + transceiver.remoteCapabilities.codecs.forEach(function(remoteCodec) { + if (codec.name.toLowerCase() === remoteCodec.name.toLowerCase() && + codec.clockRate === remoteCodec.clockRate) { + codec.preferredPayloadType = remoteCodec.payloadType; + } + }); + } + }); + localCapabilities.headerExtensions.forEach(function(hdrExt) { + var remoteExtensions = transceiver.remoteCapabilities && + transceiver.remoteCapabilities.headerExtensions || []; + remoteExtensions.forEach(function(rHdrExt) { + if (hdrExt.uri === rHdrExt.uri) { + hdrExt.id = rHdrExt.id; + } + }); + }); + + // generate an ssrc now, to be used later in rtpSender.send + var sendEncodingParameters = transceiver.sendEncodingParameters || [{ + ssrc: (2 * sdpMLineIndex + 1) * 1001 + }]; + if (track) { + // add RTX + if (edgeVersion >= 15019 && kind === 'video' && + !sendEncodingParameters[0].rtx) { + sendEncodingParameters[0].rtx = { + ssrc: sendEncodingParameters[0].ssrc + 1 + }; + } + } + + if (transceiver.wantReceive) { + transceiver.rtpReceiver = new window.RTCRtpReceiver( + transceiver.dtlsTransport, kind); + } + + transceiver.localCapabilities = localCapabilities; + transceiver.sendEncodingParameters = sendEncodingParameters; + }); + + // always offer BUNDLE and dispose on return if not supported. + if (pc._config.bundlePolicy !== 'max-compat') { + sdp += 'a=group:BUNDLE ' + pc.transceivers.map(function(t) { + return t.mid; + }).join(' ') + '\r\n'; + } + sdp += 'a=ice-options:trickle\r\n'; + + pc.transceivers.forEach(function(transceiver, sdpMLineIndex) { + sdp += writeMediaSection(transceiver, transceiver.localCapabilities, + 'offer', transceiver.stream, pc._dtlsRole); + sdp += 'a=rtcp-rsize\r\n'; + + if (transceiver.iceGatherer && pc.iceGatheringState !== 'new' && + (sdpMLineIndex === 0 || !pc.usingBundle)) { + transceiver.iceGatherer.getLocalCandidates().forEach(function(cand) { + cand.component = 1; + sdp += 'a=' + SDPUtils.writeCandidate(cand) + '\r\n'; + }); + + if (transceiver.iceGatherer.state === 'completed') { + sdp += 'a=end-of-candidates\r\n'; + } + } + }); + + var desc = new window.RTCSessionDescription({ + type: 'offer', + sdp: sdp + }); + return Promise.resolve(desc); + }; + + RTCPeerConnection.prototype.createAnswer = function() { + var pc = this; + + if (pc._isClosed) { + return Promise.reject(makeError('InvalidStateError', + 'Can not call createAnswer after close')); + } + + if (!(pc.signalingState === 'have-remote-offer' || + pc.signalingState === 'have-local-pranswer')) { + return Promise.reject(makeError('InvalidStateError', + 'Can not call createAnswer in signalingState ' + pc.signalingState)); + } + + var sdp = SDPUtils.writeSessionBoilerplate(pc._sdpSessionId, + pc._sdpSessionVersion++); + if (pc.usingBundle) { + sdp += 'a=group:BUNDLE ' + pc.transceivers.map(function(t) { + return t.mid; + }).join(' ') + '\r\n'; + } + var mediaSectionsInOffer = SDPUtils.getMediaSections( + pc.remoteDescription.sdp).length; + pc.transceivers.forEach(function(transceiver, sdpMLineIndex) { + if (sdpMLineIndex + 1 > mediaSectionsInOffer) { + return; + } + if (transceiver.rejected) { + if (transceiver.kind === 'application') { + sdp += 'm=application 0 DTLS/SCTP 5000\r\n'; + } else if (transceiver.kind === 'audio') { + sdp += 'm=audio 0 UDP/TLS/RTP/SAVPF 0\r\n' + + 'a=rtpmap:0 PCMU/8000\r\n'; + } else if (transceiver.kind === 'video') { + sdp += 'm=video 0 UDP/TLS/RTP/SAVPF 120\r\n' + + 'a=rtpmap:120 VP8/90000\r\n'; + } + sdp += 'c=IN IP4 0.0.0.0\r\n' + + 'a=inactive\r\n' + + 'a=mid:' + transceiver.mid + '\r\n'; + return; + } + + // FIXME: look at direction. + if (transceiver.stream) { + var localTrack; + if (transceiver.kind === 'audio') { + localTrack = transceiver.stream.getAudioTracks()[0]; + } else if (transceiver.kind === 'video') { + localTrack = transceiver.stream.getVideoTracks()[0]; + } + if (localTrack) { + // add RTX + if (edgeVersion >= 15019 && transceiver.kind === 'video' && + !transceiver.sendEncodingParameters[0].rtx) { + transceiver.sendEncodingParameters[0].rtx = { + ssrc: transceiver.sendEncodingParameters[0].ssrc + 1 + }; + } + } + } + + // Calculate intersection of capabilities. + var commonCapabilities = getCommonCapabilities( + transceiver.localCapabilities, + transceiver.remoteCapabilities); + + var hasRtx = commonCapabilities.codecs.filter(function(c) { + return c.name.toLowerCase() === 'rtx'; + }).length; + if (!hasRtx && transceiver.sendEncodingParameters[0].rtx) { + delete transceiver.sendEncodingParameters[0].rtx; + } + + sdp += writeMediaSection(transceiver, commonCapabilities, + 'answer', transceiver.stream, pc._dtlsRole); + if (transceiver.rtcpParameters && + transceiver.rtcpParameters.reducedSize) { + sdp += 'a=rtcp-rsize\r\n'; + } + }); + + var desc = new window.RTCSessionDescription({ + type: 'answer', + sdp: sdp + }); + return Promise.resolve(desc); + }; + + RTCPeerConnection.prototype.addIceCandidate = function(candidate) { + var pc = this; + var sections; + if (candidate && !(candidate.sdpMLineIndex !== undefined || + candidate.sdpMid)) { + return Promise.reject(new TypeError('sdpMLineIndex or sdpMid required')); + } + + // TODO: needs to go into ops queue. + return new Promise(function(resolve, reject) { + if (!pc.remoteDescription) { + return reject(makeError('InvalidStateError', + 'Can not add ICE candidate without a remote description')); + } else if (!candidate || candidate.candidate === '') { + for (var j = 0; j < pc.transceivers.length; j++) { + if (pc.transceivers[j].rejected) { + continue; + } + pc.transceivers[j].iceTransport.addRemoteCandidate({}); + sections = SDPUtils.getMediaSections(pc.remoteDescription.sdp); + sections[j] += 'a=end-of-candidates\r\n'; + pc.remoteDescription.sdp = + SDPUtils.getDescription(pc.remoteDescription.sdp) + + sections.join(''); + if (pc.usingBundle) { + break; + } + } + } else { + var sdpMLineIndex = candidate.sdpMLineIndex; + if (candidate.sdpMid) { + for (var i = 0; i < pc.transceivers.length; i++) { + if (pc.transceivers[i].mid === candidate.sdpMid) { + sdpMLineIndex = i; + break; + } + } + } + var transceiver = pc.transceivers[sdpMLineIndex]; + if (transceiver) { + if (transceiver.rejected) { + return resolve(); + } + var cand = Object.keys(candidate.candidate).length > 0 ? + SDPUtils.parseCandidate(candidate.candidate) : {}; + // Ignore Chrome's invalid candidates since Edge does not like them. + if (cand.protocol === 'tcp' && (cand.port === 0 || cand.port === 9)) { + return resolve(); + } + // Ignore RTCP candidates, we assume RTCP-MUX. + if (cand.component && cand.component !== 1) { + return resolve(); + } + // when using bundle, avoid adding candidates to the wrong + // ice transport. And avoid adding candidates added in the SDP. + if (sdpMLineIndex === 0 || (sdpMLineIndex > 0 && + transceiver.iceTransport !== pc.transceivers[0].iceTransport)) { + if (!maybeAddCandidate(transceiver.iceTransport, cand)) { + return reject(makeError('OperationError', + 'Can not add ICE candidate')); + } + } + + // update the remoteDescription. + var candidateString = candidate.candidate.trim(); + if (candidateString.indexOf('a=') === 0) { + candidateString = candidateString.substr(2); + } + sections = SDPUtils.getMediaSections(pc.remoteDescription.sdp); + sections[sdpMLineIndex] += 'a=' + + (cand.type ? candidateString : 'end-of-candidates') + + '\r\n'; + pc.remoteDescription.sdp = sections.join(''); + } else { + return reject(makeError('OperationError', + 'Can not add ICE candidate')); + } + } + resolve(); + }); + }; + + RTCPeerConnection.prototype.getStats = function() { + var promises = []; + this.transceivers.forEach(function(transceiver) { + ['rtpSender', 'rtpReceiver', 'iceGatherer', 'iceTransport', + 'dtlsTransport'].forEach(function(method) { + if (transceiver[method]) { + promises.push(transceiver[method].getStats()); + } + }); + }); + var fixStatsType = function(stat) { + return { + inboundrtp: 'inbound-rtp', + outboundrtp: 'outbound-rtp', + candidatepair: 'candidate-pair', + localcandidate: 'local-candidate', + remotecandidate: 'remote-candidate' + }[stat.type] || stat.type; + }; + return new Promise(function(resolve) { + // shim getStats with maplike support + var results = new Map(); + Promise.all(promises).then(function(res) { + res.forEach(function(result) { + Object.keys(result).forEach(function(id) { + result[id].type = fixStatsType(result[id]); + results.set(id, result[id]); + }); + }); + resolve(results); + }); + }); + }; + + // legacy callback shims. Should be moved to adapter.js some days. + var methods = ['createOffer', 'createAnswer']; + methods.forEach(function(method) { + var nativeMethod = RTCPeerConnection.prototype[method]; + RTCPeerConnection.prototype[method] = function() { + var args = arguments; + if (typeof args[0] === 'function' || + typeof args[1] === 'function') { // legacy + return nativeMethod.apply(this, [arguments[2]]) + .then(function(description) { + if (typeof args[0] === 'function') { + args[0].apply(null, [description]); + } + }, function(error) { + if (typeof args[1] === 'function') { + args[1].apply(null, [error]); + } + }); + } + return nativeMethod.apply(this, arguments); + }; + }); + + methods = ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']; + methods.forEach(function(method) { + var nativeMethod = RTCPeerConnection.prototype[method]; + RTCPeerConnection.prototype[method] = function() { + var args = arguments; + if (typeof args[1] === 'function' || + typeof args[2] === 'function') { // legacy + return nativeMethod.apply(this, arguments) + .then(function() { + if (typeof args[1] === 'function') { + args[1].apply(null); + } + }, function(error) { + if (typeof args[2] === 'function') { + args[2].apply(null, [error]); + } + }); + } + return nativeMethod.apply(this, arguments); + }; + }); + + // getStats is special. It doesn't have a spec legacy method yet we support + // getStats(something, cb) without error callbacks. + ['getStats'].forEach(function(method) { + var nativeMethod = RTCPeerConnection.prototype[method]; + RTCPeerConnection.prototype[method] = function() { + var args = arguments; + if (typeof args[1] === 'function') { + return nativeMethod.apply(this, arguments) + .then(function() { + if (typeof args[1] === 'function') { + args[1].apply(null); + } + }); + } + return nativeMethod.apply(this, arguments); + }; + }); + + return RTCPeerConnection; +}; + +},{"sdp":19}],11:[function(require,module,exports){ +var grammar = module.exports = { + v: [{ + name: 'version', + reg: /^(\d*)$/ + }], + o: [{ //o=- 20518 0 IN IP4 203.0.113.1 + // NB: sessionId will be a String in most cases because it is huge + name: 'origin', + reg: /^(\S*) (\d*) (\d*) (\S*) IP(\d) (\S*)/, + names: ['username', 'sessionId', 'sessionVersion', 'netType', 'ipVer', 'address'], + format: "%s %s %d %s IP%d %s" + }], + // default parsing of these only (though some of these feel outdated) + s: [{ name: 'name' }], + i: [{ name: 'description' }], + u: [{ name: 'uri' }], + e: [{ name: 'email' }], + p: [{ name: 'phone' }], + z: [{ name: 'timezones' }], // TODO: this one can actually be parsed properly.. + r: [{ name: 'repeats' }], // TODO: this one can also be parsed properly + //k: [{}], // outdated thing ignored + t: [{ //t=0 0 + name: 'timing', + reg: /^(\d*) (\d*)/, + names: ['start', 'stop'], + format: "%d %d" + }], + c: [{ //c=IN IP4 10.47.197.26 + name: 'connection', + reg: /^IN IP(\d) (\S*)/, + names: ['version', 'ip'], + format: "IN IP%d %s" + }], + b: [{ //b=AS:4000 + push: 'bandwidth', + reg: /^(TIAS|AS|CT|RR|RS):(\d*)/, + names: ['type', 'limit'], + format: "%s:%s" + }], + m: [{ //m=video 51744 RTP/AVP 126 97 98 34 31 + // NB: special - pushes to session + // TODO: rtp/fmtp should be filtered by the payloads found here? + reg: /^(\w*) (\d*) ([\w\/]*)(?: (.*))?/, + names: ['type', 'port', 'protocol', 'payloads'], + format: "%s %d %s %s" + }], + a: [ + { //a=rtpmap:110 opus/48000/2 + push: 'rtp', + reg: /^rtpmap:(\d*) ([\w\-]*)(?:\s*\/(\d*)(?:\s*\/(\S*))?)?/, + names: ['payload', 'codec', 'rate', 'encoding'], + format: function (o) { + return (o.encoding) ? + "rtpmap:%d %s/%s/%s": + o.rate ? + "rtpmap:%d %s/%s": + "rtpmap:%d %s"; + } + }, + { + //a=fmtp:108 profile-level-id=24;object=23;bitrate=64000 + //a=fmtp:111 minptime=10; useinbandfec=1 + push: 'fmtp', + reg: /^fmtp:(\d*) ([\S| ]*)/, + names: ['payload', 'config'], + format: "fmtp:%d %s" + }, + { //a=control:streamid=0 + name: 'control', + reg: /^control:(.*)/, + format: "control:%s" + }, + { //a=rtcp:65179 IN IP4 193.84.77.194 + name: 'rtcp', + reg: /^rtcp:(\d*)(?: (\S*) IP(\d) (\S*))?/, + names: ['port', 'netType', 'ipVer', 'address'], + format: function (o) { + return (o.address != null) ? + "rtcp:%d %s IP%d %s": + "rtcp:%d"; + } + }, + { //a=rtcp-fb:98 trr-int 100 + push: 'rtcpFbTrrInt', + reg: /^rtcp-fb:(\*|\d*) trr-int (\d*)/, + names: ['payload', 'value'], + format: "rtcp-fb:%d trr-int %d" + }, + { //a=rtcp-fb:98 nack rpsi + push: 'rtcpFb', + reg: /^rtcp-fb:(\*|\d*) ([\w-_]*)(?: ([\w-_]*))?/, + names: ['payload', 'type', 'subtype'], + format: function (o) { + return (o.subtype != null) ? + "rtcp-fb:%s %s %s": + "rtcp-fb:%s %s"; + } + }, + { //a=extmap:2 urn:ietf:params:rtp-hdrext:toffset + //a=extmap:1/recvonly URI-gps-string + push: 'ext', + reg: /^extmap:([\w_\/]*) (\S*)(?: (\S*))?/, + names: ['value', 'uri', 'config'], // value may include "/direction" suffix + format: function (o) { + return (o.config != null) ? + "extmap:%s %s %s": + "extmap:%s %s"; + } + }, + { + //a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR|2^20|1:32 + push: 'crypto', + reg: /^crypto:(\d*) ([\w_]*) (\S*)(?: (\S*))?/, + names: ['id', 'suite', 'config', 'sessionConfig'], + format: function (o) { + return (o.sessionConfig != null) ? + "crypto:%d %s %s %s": + "crypto:%d %s %s"; + } + }, + { //a=setup:actpass + name: 'setup', + reg: /^setup:(\w*)/, + format: "setup:%s" + }, + { //a=mid:1 + name: 'mid', + reg: /^mid:([^\s]*)/, + format: "mid:%s" + }, + { //a=msid:0c8b064d-d807-43b4-b434-f92a889d8587 98178685-d409-46e0-8e16-7ef0db0db64a + name: 'msid', + reg: /^msid:(.*)/, + format: "msid:%s" + }, + { //a=ptime:20 + name: 'ptime', + reg: /^ptime:(\d*)/, + format: "ptime:%d" + }, + { //a=maxptime:60 + name: 'maxptime', + reg: /^maxptime:(\d*)/, + format: "maxptime:%d" + }, + { //a=sendrecv + name: 'direction', + reg: /^(sendrecv|recvonly|sendonly|inactive)/ + }, + { //a=ice-lite + name: 'icelite', + reg: /^(ice-lite)/ + }, + { //a=ice-ufrag:F7gI + name: 'iceUfrag', + reg: /^ice-ufrag:(\S*)/, + format: "ice-ufrag:%s" + }, + { //a=ice-pwd:x9cml/YzichV2+XlhiMu8g + name: 'icePwd', + reg: /^ice-pwd:(\S*)/, + format: "ice-pwd:%s" + }, + { //a=fingerprint:SHA-1 00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33 + name: 'fingerprint', + reg: /^fingerprint:(\S*) (\S*)/, + names: ['type', 'hash'], + format: "fingerprint:%s %s" + }, + { + //a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host + //a=candidate:1162875081 1 udp 2113937151 192.168.34.75 60017 typ host generation 0 + //a=candidate:3289912957 2 udp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 generation 0 + //a=candidate:229815620 1 tcp 1518280447 192.168.150.19 60017 typ host tcptype active generation 0 + //a=candidate:3289912957 2 tcp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 tcptype passive generation 0 + push:'candidates', + reg: /^candidate:(\S*) (\d*) (\S*) (\d*) (\S*) (\d*) typ (\S*)(?: raddr (\S*) rport (\d*))?(?: tcptype (\S*))?(?: generation (\d*))?/, + names: ['foundation', 'component', 'transport', 'priority', 'ip', 'port', 'type', 'raddr', 'rport', 'tcptype', 'generation'], + format: function (o) { + var str = "candidate:%s %d %s %d %s %d typ %s"; + + str += (o.raddr != null) ? " raddr %s rport %d" : "%v%v"; + + // NB: candidate has three optional chunks, so %void middles one if it's missing + str += (o.tcptype != null) ? " tcptype %s" : "%v"; + + if (o.generation != null) { + str += " generation %d"; + } + return str; + } + }, + { //a=end-of-candidates (keep after the candidates line for readability) + name: 'endOfCandidates', + reg: /^(end-of-candidates)/ + }, + { //a=remote-candidates:1 203.0.113.1 54400 2 203.0.113.1 54401 ... + name: 'remoteCandidates', + reg: /^remote-candidates:(.*)/, + format: "remote-candidates:%s" + }, + { //a=ice-options:google-ice + name: 'iceOptions', + reg: /^ice-options:(\S*)/, + format: "ice-options:%s" + }, + { //a=ssrc:2566107569 cname:t9YU8M1UxTF8Y1A1 + push: "ssrcs", + reg: /^ssrc:(\d*) ([\w_]*):(.*)/, + names: ['id', 'attribute', 'value'], + format: "ssrc:%d %s:%s" + }, + { //a=ssrc-group:FEC 1 2 + push: "ssrcGroups", + reg: /^ssrc-group:(\w*) (.*)/, + names: ['semantics', 'ssrcs'], + format: "ssrc-group:%s %s" + }, + { //a=msid-semantic: WMS Jvlam5X3SX1OP6pn20zWogvaKJz5Hjf9OnlV + name: "msidSemantic", + reg: /^msid-semantic:\s?(\w*) (\S*)/, + names: ['semantic', 'token'], + format: "msid-semantic: %s %s" // space after ":" is not accidental + }, + { //a=group:BUNDLE audio video + push: 'groups', + reg: /^group:(\w*) (.*)/, + names: ['type', 'mids'], + format: "group:%s %s" + }, + { //a=rtcp-mux + name: 'rtcpMux', + reg: /^(rtcp-mux)/ + }, + { //a=rtcp-rsize + name: 'rtcpRsize', + reg: /^(rtcp-rsize)/ + }, + { // any a= that we don't understand is kepts verbatim on media.invalid + push: 'invalid', + names: ["value"] + } + ] +}; + +// set sensible defaults to avoid polluting the grammar with boring details +Object.keys(grammar).forEach(function (key) { + var objs = grammar[key]; + objs.forEach(function (obj) { + if (!obj.reg) { + obj.reg = /(.*)/; + } + if (!obj.format) { + obj.format = "%s"; + } + }); +}); + +},{}],12:[function(require,module,exports){ +var parser = require('./parser'); +var writer = require('./writer'); + +exports.write = writer; +exports.parse = parser.parse; +exports.parseFmtpConfig = parser.parseFmtpConfig; +exports.parsePayloads = parser.parsePayloads; +exports.parseRemoteCandidates = parser.parseRemoteCandidates; + +},{"./parser":13,"./writer":14}],13:[function(require,module,exports){ +var toIntIfInt = function (v) { + return String(Number(v)) === v ? Number(v) : v; +}; + +var attachProperties = function (match, location, names, rawName) { + if (rawName && !names) { + location[rawName] = toIntIfInt(match[1]); + } + else { + for (var i = 0; i < names.length; i += 1) { + if (match[i+1] != null) { + location[names[i]] = toIntIfInt(match[i+1]); + } + } + } +}; + +var parseReg = function (obj, location, content) { + var needsBlank = obj.name && obj.names; + if (obj.push && !location[obj.push]) { + location[obj.push] = []; + } + else if (needsBlank && !location[obj.name]) { + location[obj.name] = {}; + } + var keyLocation = obj.push ? + {} : // blank object that will be pushed + needsBlank ? location[obj.name] : location; // otherwise, named location or root + + attachProperties(content.match(obj.reg), keyLocation, obj.names, obj.name); + + if (obj.push) { + location[obj.push].push(keyLocation); + } +}; + +var grammar = require('./grammar'); +var validLine = RegExp.prototype.test.bind(/^([a-z])=(.*)/); + +exports.parse = function (sdp) { + var session = {} + , media = [] + , location = session; // points at where properties go under (one of the above) + + // parse lines we understand + sdp.split(/(\r\n|\r|\n)/).filter(validLine).forEach(function (l) { + var type = l[0]; + var content = l.slice(2); + if (type === 'm') { + media.push({rtp: [], fmtp: []}); + location = media[media.length-1]; // point at latest media line + } + + for (var j = 0; j < (grammar[type] || []).length; j += 1) { + var obj = grammar[type][j]; + if (obj.reg.test(content)) { + return parseReg(obj, location, content); + } + } + }); + + session.media = media; // link it up + return session; +}; + +var fmtpReducer = function (acc, expr) { + var s = expr.split('='); + if (s.length === 2) { + acc[s[0]] = toIntIfInt(s[1]); + } + return acc; +}; + +exports.parseFmtpConfig = function (str) { + return str.split(/\;\s?/).reduce(fmtpReducer, {}); +}; + +exports.parsePayloads = function (str) { + return str.split(' ').map(Number); +}; + +exports.parseRemoteCandidates = function (str) { + var candidates = []; + var parts = str.split(' ').map(toIntIfInt); + for (var i = 0; i < parts.length; i += 3) { + candidates.push({ + component: parts[i], + ip: parts[i + 1], + port: parts[i + 2] + }); + } + return candidates; +}; + +},{"./grammar":11}],14:[function(require,module,exports){ +var grammar = require('./grammar'); + +// customized util.format - discards excess arguments and can void middle ones +var formatRegExp = /%[sdv%]/g; +var format = function (formatStr) { + var i = 1; + var args = arguments; + var len = args.length; + return formatStr.replace(formatRegExp, function (x) { + if (i >= len) { + return x; // missing argument + } + var arg = args[i]; + i += 1; + switch (x) { + case '%%': + return '%'; + case '%s': + return String(arg); + case '%d': + return Number(arg); + case '%v': + return ''; + } + }); + // NB: we discard excess arguments - they are typically undefined from makeLine +}; + +var makeLine = function (type, obj, location) { + var str = obj.format instanceof Function ? + (obj.format(obj.push ? location : location[obj.name])) : + obj.format; + + var args = [type + '=' + str]; + if (obj.names) { + for (var i = 0; i < obj.names.length; i += 1) { + var n = obj.names[i]; + if (obj.name) { + args.push(location[obj.name][n]); + } + else { // for mLine and push attributes + args.push(location[obj.names[i]]); + } + } + } + else { + args.push(location[obj.name]); + } + return format.apply(null, args); +}; + +// RFC specified order +// TODO: extend this with all the rest +var defaultOuterOrder = [ + 'v', 'o', 's', 'i', + 'u', 'e', 'p', 'c', + 'b', 't', 'r', 'z', 'a' +]; +var defaultInnerOrder = ['i', 'c', 'b', 'a']; + + +module.exports = function (session, opts) { + opts = opts || {}; + // ensure certain properties exist + if (session.version == null) { + session.version = 0; // "v=0" must be there (only defined version atm) + } + if (session.name == null) { + session.name = " "; // "s= " must be there if no meaningful name set + } + session.media.forEach(function (mLine) { + if (mLine.payloads == null) { + mLine.payloads = ""; + } + }); + + var outerOrder = opts.outerOrder || defaultOuterOrder; + var innerOrder = opts.innerOrder || defaultInnerOrder; + var sdp = []; + + // loop through outerOrder for matching properties on session + outerOrder.forEach(function (type) { + grammar[type].forEach(function (obj) { + if (obj.name in session && session[obj.name] != null) { + sdp.push(makeLine(type, obj, session)); + } + else if (obj.push in session && session[obj.push] != null) { + session[obj.push].forEach(function (el) { + sdp.push(makeLine(type, obj, el)); + }); + } + }); + }); + + // then for each media line, follow the innerOrder + session.media.forEach(function (mLine) { + sdp.push(makeLine('m', grammar.m[0], mLine)); + + innerOrder.forEach(function (type) { + grammar[type].forEach(function (obj) { + if (obj.name in mLine && mLine[obj.name] != null) { + sdp.push(makeLine(type, obj, mLine)); + } + else if (obj.push in mLine && mLine[obj.push] != null) { + mLine[obj.push].forEach(function (el) { + sdp.push(makeLine(type, obj, el)); + }); + } + }); + }); + }); + + return sdp.join('\r\n') + '\r\n'; +}; + +},{"./grammar":11}],15:[function(require,module,exports){ +/* Copyright @ 2015 Atlassian Pty Ltd + * + * 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. + */ + +module.exports = function arrayEquals(array) { + // if the other array is a falsy value, return + if (!array) + return false; + + // compare lengths - can save a lot of time + if (this.length != array.length) + return false; + + for (var i = 0, l = this.length; i < l; i++) { + // Check if we have nested arrays + if (this[i] instanceof Array && array[i] instanceof Array) { + // recurse into the nested arrays + if (!arrayEquals.apply(this[i], [array[i]])) + return false; + } else if (this[i] != array[i]) { + // Warning - two different object instances will never be equal: + // {x:20} != {x:20} + return false; + } + } + return true; +}; + + +},{}],16:[function(require,module,exports){ +/* Copyright @ 2015 Atlassian Pty Ltd + * + * 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. + */ + +exports.Interop = require('./interop'); + +},{"./interop":17}],17:[function(require,module,exports){ +/* Copyright @ 2015 Atlassian Pty Ltd + * + * 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. + */ + +/* global RTCSessionDescription */ +/* global RTCIceCandidate */ +/* jshint -W097 */ +"use strict"; + +var transform = require('./transform'); +var arrayEquals = require('./array-equals'); + +function Interop() { + + /** + * This map holds the most recent Unified Plan offer/answer SDP that was + * converted to Plan B, with the SDP type ('offer' or 'answer') as keys and + * the SDP string as values. + * + * @type {{}} + */ + this.cache = { + mlB2UMap : {}, + mlU2BMap : {} + }; +} + +module.exports = Interop; + +/** + * Changes the candidate args to match with the related Unified Plan + */ +Interop.prototype.candidateToUnifiedPlan = function(candidate) { + var cand = new RTCIceCandidate(candidate); + + cand.sdpMLineIndex = this.cache.mlB2UMap[cand.sdpMLineIndex]; + /* TODO: change sdpMid to (audio|video)-SSRC */ + + return cand; +}; + +/** + * Changes the candidate args to match with the related Plan B + */ +Interop.prototype.candidateToPlanB = function(candidate) { + var cand = new RTCIceCandidate(candidate); + + if (cand.sdpMid.indexOf('audio') === 0) { + cand.sdpMid = 'audio'; + } else if (cand.sdpMid.indexOf('video') === 0) { + cand.sdpMid = 'video'; + } else { + throw new Error('candidate with ' + cand.sdpMid + ' not allowed'); + } + + cand.sdpMLineIndex = this.cache.mlU2BMap[cand.sdpMLineIndex]; + + return cand; +}; + +/** + * Returns the index of the first m-line with the given media type and with a + * direction which allows sending, in the last Unified Plan description with + * type "answer" converted to Plan B. Returns {null} if there is no saved + * answer, or if none of its m-lines with the given type allow sending. + * @param type the media type ("audio" or "video"). + * @returns {*} + */ +Interop.prototype.getFirstSendingIndexFromAnswer = function(type) { + if (!this.cache.answer) { + return null; + } + + var session = transform.parse(this.cache.answer); + if (session && session.media && Array.isArray(session.media)){ + for (var i = 0; i < session.media.length; i++) { + if (session.media[i].type == type && + (!session.media[i].direction /* default to sendrecv */ || + session.media[i].direction === 'sendrecv' || + session.media[i].direction === 'sendonly')){ + return i; + } + } + } + + return null; +}; + +/** + * This method transforms a Unified Plan SDP to an equivalent Plan B SDP. A + * PeerConnection wrapper transforms the SDP to Plan B before passing it to the + * application. + * + * @param desc + * @returns {*} + */ +Interop.prototype.toPlanB = function(desc) { + var self = this; + //#region Preliminary input validation. + + if (typeof desc !== 'object' || desc === null || + typeof desc.sdp !== 'string') { + console.warn('An empty description was passed as an argument.'); + return desc; + } + + // Objectify the SDP for easier manipulation. + var session = transform.parse(desc.sdp); + + // If the SDP contains no media, there's nothing to transform. + if (typeof session.media === 'undefined' || + !Array.isArray(session.media) || session.media.length === 0) { + console.warn('The description has no media.'); + return desc; + } + + // Try some heuristics to "make sure" this is a Unified Plan SDP. Plan B + // SDP has a video, an audio and a data "channel" at most. + if (session.media.length <= 3 && session.media.every(function(m) { + return ['video', 'audio', 'data'].indexOf(m.mid) !== -1; + })) { + console.warn('This description does not look like Unified Plan.'); + return desc; + } + + //#endregion + + // HACK https://bugzilla.mozilla.org/show_bug.cgi?id=1113443 + var sdp = desc.sdp; + var rewrite = false; + for (var i = 0; i < session.media.length; i++) { + var uLine = session.media[i]; + uLine.rtp.forEach(function(rtp) { + if (rtp.codec === 'NULL') + { + rewrite = true; + var offer = transform.parse(self.cache.offer); + rtp.codec = offer.media[i].rtp[0].codec; + } + }); + } + if (rewrite) { + sdp = transform.write(session); + } + + // Unified Plan SDP is our "precious". Cache it for later use in the Plan B + // -> Unified Plan transformation. + this.cache[desc.type] = sdp; + + //#region Convert from Unified Plan to Plan B. + + // We rebuild the session.media array. + var media = session.media; + session.media = []; + + // Associative array that maps channel types to channel objects for fast + // access to channel objects by their type, e.g. type2bl['audio']->channel + // obj. + var type2bl = {}; + + // Used to build the group:BUNDLE value after the channels construction + // loop. + var types = []; + + media.forEach(function(uLine) { + // rtcp-mux is required in the Plan B SDP. + if ((typeof uLine.rtcpMux !== 'string' || + uLine.rtcpMux !== 'rtcp-mux') && + uLine.direction !== 'inactive') { + throw new Error('Cannot convert to Plan B because m-lines ' + + 'without the rtcp-mux attribute were found.'); + } + + // If we don't have a channel for this uLine.type OR the selected is + // inactive, then select this uLine as the channel basis. + if (typeof type2bl[uLine.type] === 'undefined' || + type2bl[uLine.type].direction === 'inactive') { + type2bl[uLine.type] = uLine; + } + + if (uLine.protocol != type2bl[uLine.type].protocol) { + throw new Error('Cannot convert to Plan B because m-lines ' + + 'have different protocols and this library does not have ' + + 'support for that'); + } + + if (uLine.payloads != type2bl[uLine.type].payloads) { + throw new Error('Cannot convert to Plan B because m-lines ' + + 'have different payloads and this library does not have ' + + 'support for that'); + } + + }); + + // Implode the Unified Plan m-lines/tracks into Plan B channels. + media.forEach(function(uLine) { + if (uLine.type === 'application') { + session.media.push(uLine); + types.push(uLine.mid); + return; + } + + // Add sources to the channel and handle a=msid. + if (typeof uLine.sources === 'object') { + Object.keys(uLine.sources).forEach(function(ssrc) { + if (typeof type2bl[uLine.type].sources !== 'object') + type2bl[uLine.type].sources = {}; + + // Assign the sources to the channel. + type2bl[uLine.type].sources[ssrc] = + uLine.sources[ssrc]; + + if (typeof uLine.msid !== 'undefined') { + // In Plan B the msid is an SSRC attribute. Also, we don't + // care about the obsolete label and mslabel attributes. + // + // Note that it is not guaranteed that the uLine will + // have an msid. recvonly channels in particular don't have + // one. + type2bl[uLine.type].sources[ssrc].msid = + uLine.msid; + } + // NOTE ssrcs in ssrc groups will share msids, as + // draft-uberti-rtcweb-plan-00 mandates. + }); + } + + // Add ssrc groups to the channel. + if (typeof uLine.ssrcGroups !== 'undefined' && + Array.isArray(uLine.ssrcGroups)) { + + // Create the ssrcGroups array, if it's not defined. + if (typeof type2bl[uLine.type].ssrcGroups === 'undefined' || + !Array.isArray(type2bl[uLine.type].ssrcGroups)) { + type2bl[uLine.type].ssrcGroups = []; + } + + type2bl[uLine.type].ssrcGroups = + type2bl[uLine.type].ssrcGroups.concat( + uLine.ssrcGroups); + } + + if (type2bl[uLine.type] === uLine) { + // Plan B mids are in ['audio', 'video', 'data'] + uLine.mid = uLine.type; + + // Plan B doesn't support/need the bundle-only attribute. + delete uLine.bundleOnly; + + // In Plan B the msid is an SSRC attribute. + delete uLine.msid; + + if (uLine.type == media[0].type) { + types.unshift(uLine.type); + // Add the channel to the new media array. + session.media.unshift(uLine); + } else { + types.push(uLine.type); + // Add the channel to the new media array. + session.media.push(uLine); + } + } + }); + + if (typeof session.groups !== 'undefined') { + // We regenerate the BUNDLE group with the new mids. + session.groups.some(function(group) { + if (group.type === 'BUNDLE') { + group.mids = types.join(' '); + return true; + } + }); + } + + // msid semantic + session.msidSemantic = { + semantic: 'WMS', + token: '*' + }; + + var resStr = transform.write(session); + + return new RTCSessionDescription({ + type: desc.type, + sdp: resStr + }); + + //#endregion +}; + +/* follow rules defined in RFC4145 */ +function addSetupAttr(uLine) { + if (typeof uLine.setup === 'undefined') { + return; + } + + if (uLine.setup === "active") { + uLine.setup = "passive"; + } else if (uLine.setup === "passive") { + uLine.setup = "active"; + } +} + +/** + * This method transforms a Plan B SDP to an equivalent Unified Plan SDP. A + * PeerConnection wrapper transforms the SDP to Unified Plan before passing it + * to FF. + * + * @param desc + * @returns {*} + */ +Interop.prototype.toUnifiedPlan = function(desc) { + var self = this; + //#region Preliminary input validation. + + if (typeof desc !== 'object' || desc === null || + typeof desc.sdp !== 'string') { + console.warn('An empty description was passed as an argument.'); + return desc; + } + + var session = transform.parse(desc.sdp); + + // If the SDP contains no media, there's nothing to transform. + if (typeof session.media === 'undefined' || + !Array.isArray(session.media) || session.media.length === 0) { + console.warn('The description has no media.'); + return desc; + } + + // Try some heuristics to "make sure" this is a Plan B SDP. Plan B SDP has + // a video, an audio and a data "channel" at most. + if (session.media.length > 3 || !session.media.every(function(m) { + return ['video', 'audio', 'data'].indexOf(m.mid) !== -1; + })) { + console.warn('This description does not look like Plan B.'); + return desc; + } + + // Make sure this Plan B SDP can be converted to a Unified Plan SDP. + var mids = []; + session.media.forEach(function(m) { + mids.push(m.mid); + }); + + var hasBundle = false; + if (typeof session.groups !== 'undefined' && + Array.isArray(session.groups)) { + hasBundle = session.groups.every(function(g) { + return g.type !== 'BUNDLE' || + arrayEquals.apply(g.mids.sort(), [mids.sort()]); + }); + } + + if (!hasBundle) { + var mustBeBundle = false; + + session.media.forEach(function(m) { + if (m.direction !== 'inactive') { + mustBeBundle = true; + } + }); + + if (mustBeBundle) { + throw new Error("Cannot convert to Unified Plan because m-lines that" + + " are not bundled were found."); + } + } + + //#endregion + + + //#region Convert from Plan B to Unified Plan. + + // Unfortunately, a Plan B offer/answer doesn't have enough information to + // rebuild an equivalent Unified Plan offer/answer. + // + // For example, if this is a local answer (in Unified Plan style) that we + // convert to Plan B prior to handing it over to the application (the + // PeerConnection wrapper called us, for instance, after a successful + // createAnswer), we want to remember the m-line at which we've seen the + // (local) SSRC. That's because when the application wants to do call the + // SLD method, forcing us to do the inverse transformation (from Plan B to + // Unified Plan), we need to know to which m-line to assign the (local) + // SSRC. We also need to know all the other m-lines that the original + // answer had and include them in the transformed answer as well. + // + // Another example is if this is a remote offer that we convert to Plan B + // prior to giving it to the application, we want to remember the mid at + // which we've seen the (remote) SSRC. + // + // In the iteration that follows, we use the cached Unified Plan (if it + // exists) to assign mids to ssrcs. + + var type; + if (desc.type === 'answer') { + type = 'offer'; + } else if (desc.type === 'offer') { + type = 'answer'; + } else { + throw new Error("Type '" + desc.type + "' not supported."); + } + + var cached; + if (typeof this.cache[type] !== 'undefined') { + cached = transform.parse(this.cache[type]); + } + + var recvonlySsrcs = { + audio: {}, + video: {} + }; + + // A helper map that sends mids to m-line objects. We use it later to + // rebuild the Unified Plan style session.media array. + var mid2ul = {}; + var bIdx = 0; + var uIdx = 0; + + var sources2ul = {}; + + var candidates; + var iceUfrag; + var icePwd; + var fingerprint; + var payloads = {}; + var rtcpFb = {}; + var rtp = {}; + + session.media.forEach(function(bLine) { + if ((typeof bLine.rtcpMux !== 'string' || + bLine.rtcpMux !== 'rtcp-mux') && + bLine.direction !== 'inactive') { + throw new Error("Cannot convert to Unified Plan because m-lines " + + "without the rtcp-mux attribute were found."); + } + + if (bLine.type === 'application') { + mid2ul[bLine.mid] = bLine; + return; + } + + // With rtcp-mux and bundle all the channels should have the same ICE + // stuff. + var sources = bLine.sources; + var ssrcGroups = bLine.ssrcGroups; + var port = bLine.port; + + /* Chrome adds different candidates even using bundle, so we concat the candidates list */ + if (typeof bLine.candidates != 'undefined') { + if (typeof candidates != 'undefined') { + candidates = candidates.concat(bLine.candidates); + } else { + candidates = bLine.candidates; + } + } + + if ((typeof iceUfrag != 'undefined') && (typeof bLine.iceUfrag != 'undefined') && (iceUfrag != bLine.iceUfrag)) { + throw new Error("Only BUNDLE supported, iceUfrag must be the same for all m-lines.\n" + + "\tLast iceUfrag: " + iceUfrag + "\n" + + "\tNew iceUfrag: " + bLine.iceUfrag + ); + } + + if (typeof bLine.iceUfrag != 'undefined') { + iceUfrag = bLine.iceUfrag; + } + + if ((typeof icePwd != 'undefined') && (typeof bLine.icePwd != 'undefined') && (icePwd != bLine.icePwd)) { + throw new Error("Only BUNDLE supported, icePwd must be the same for all m-lines.\n" + + "\tLast icePwd: " + icePwd + "\n" + + "\tNew icePwd: " + bLine.icePwd + ); + } + + if (typeof bLine.icePwd != 'undefined') { + icePwd = bLine.icePwd; + } + + if ((typeof fingerprint != 'undefined') && (typeof bLine.fingerprint != 'undefined') && + (fingerprint.type != bLine.fingerprint.type || fingerprint.hash != bLine.fingerprint.hash)) { + throw new Error("Only BUNDLE supported, fingerprint must be the same for all m-lines.\n" + + "\tLast fingerprint: " + JSON.stringify(fingerprint) + "\n" + + "\tNew fingerprint: " + JSON.stringify(bLine.fingerprint) + ); + } + + if (typeof bLine.fingerprint != 'undefined') { + fingerprint = bLine.fingerprint; + } + + payloads[bLine.type] = bLine.payloads; + rtcpFb[bLine.type] = bLine.rtcpFb; + rtp[bLine.type] = bLine.rtp; + + // inverted ssrc group map + var ssrc2group = {}; + if (typeof ssrcGroups !== 'undefined' && Array.isArray(ssrcGroups)) { + ssrcGroups.forEach(function (ssrcGroup) { + // XXX This might brake if an SSRC is in more than one group + // for some reason. + if (typeof ssrcGroup.ssrcs !== 'undefined' && + Array.isArray(ssrcGroup.ssrcs)) { + ssrcGroup.ssrcs.forEach(function (ssrc) { + if (typeof ssrc2group[ssrc] === 'undefined') { + ssrc2group[ssrc] = []; + } + + ssrc2group[ssrc].push(ssrcGroup); + }); + } + }); + } + + // ssrc to m-line index. + var ssrc2ml = {}; + + if (typeof sources === 'object') { + + // We'll use the "bLine" object as a prototype for each new "mLine" + // that we create, but first we need to clean it up a bit. + delete bLine.sources; + delete bLine.ssrcGroups; + delete bLine.candidates; + delete bLine.iceUfrag; + delete bLine.icePwd; + delete bLine.fingerprint; + delete bLine.port; + delete bLine.mid; + + // Explode the Plan B channel sources with one m-line per source. + Object.keys(sources).forEach(function(ssrc) { + + // The (unified) m-line for this SSRC. We either create it from + // scratch or, if it's a grouped SSRC, we re-use a related + // mline. In other words, if the source is grouped with another + // source, put the two together in the same m-line. + var uLine; + + // We assume here that we are the answerer in the O/A, so any + // offers which we translate come from the remote side, while + // answers are local. So the check below is to make that we + // handle receive-only SSRCs in a special way only if they come + // from the remote side. + if (desc.type==='offer') { + // We want to detect SSRCs which are used by a remote peer + // in an m-line with direction=recvonly (i.e. they are + // being used for RTCP only). + // This information would have gotten lost if the remote + // peer used Unified Plan and their local description was + // translated to Plan B. So we use the lack of an MSID + // attribute to deduce a "receive only" SSRC. + if (!sources[ssrc].msid) { + recvonlySsrcs[bLine.type][ssrc] = sources[ssrc]; + // Receive-only SSRCs must not create new m-lines. We + // will assign them to an existing m-line later. + return; + } + } + + if (typeof ssrc2group[ssrc] !== 'undefined' && + Array.isArray(ssrc2group[ssrc])) { + ssrc2group[ssrc].some(function (ssrcGroup) { + // ssrcGroup.ssrcs *is* an Array, no need to check + // again here. + return ssrcGroup.ssrcs.some(function (related) { + if (typeof ssrc2ml[related] === 'object') { + uLine = ssrc2ml[related]; + return true; + } + }); + }); + } + + if (typeof uLine === 'object') { + // the m-line already exists. Just add the source. + uLine.sources[ssrc] = sources[ssrc]; + delete sources[ssrc].msid; + } else { + // Use the "bLine" as a prototype for the "uLine". + uLine = Object.create(bLine); + ssrc2ml[ssrc] = uLine; + + if (typeof sources[ssrc].msid !== 'undefined') { + // Assign the msid of the source to the m-line. Note + // that it is not guaranteed that the source will have + // msid. In particular "recvonly" sources don't have an + // msid. Note that "recvonly" is a term only defined + // for m-lines. + uLine.msid = sources[ssrc].msid; + delete sources[ssrc].msid; + } + + // We assign one SSRC per media line. + uLine.sources = {}; + uLine.sources[ssrc] = sources[ssrc]; + uLine.ssrcGroups = ssrc2group[ssrc]; + + // Use the cached Unified Plan SDP (if it exists) to assign + // SSRCs to mids. + if (typeof cached !== 'undefined' && + typeof cached.media !== 'undefined' && + Array.isArray(cached.media)) { + + cached.media.forEach(function (m) { + if (typeof m.sources === 'object') { + Object.keys(m.sources).forEach(function (s) { + if (s === ssrc) { + uLine.mid = m.mid; + } + }); + } + }); + } + + if (typeof uLine.mid === 'undefined') { + + // If this is an SSRC that we see for the first time + // assign it a new mid. This is typically the case when + // this method is called to transform a remote + // description for the first time or when there is a + // new SSRC in the remote description because a new + // peer has joined the conference. Local SSRCs should + // have already been added to the map in the toPlanB + // method. + // + // Because FF generates answers in Unified Plan style, + // we MUST already have a cached answer with all the + // local SSRCs mapped to some m-line/mid. + + uLine.mid = [bLine.type, '-', ssrc].join(''); + } + + // Include the candidates in the 1st media line. + uLine.candidates = candidates; + uLine.iceUfrag = iceUfrag; + uLine.icePwd = icePwd; + uLine.fingerprint = fingerprint; + uLine.port = port; + + mid2ul[uLine.mid] = uLine; + sources2ul[uIdx] = uLine.sources; + + self.cache.mlU2BMap[uIdx] = bIdx; + if (typeof self.cache.mlB2UMap[bIdx] === 'undefined') { + self.cache.mlB2UMap[bIdx] = uIdx; + } + uIdx++; + } + }); + } else { + var uLine = bLine; + + uLine.candidates = candidates; + uLine.iceUfrag = iceUfrag; + uLine.icePwd = icePwd; + uLine.fingerprint = fingerprint; + uLine.port = port; + + mid2ul[uLine.mid] = uLine; + + self.cache.mlU2BMap[uIdx] = bIdx; + if (typeof self.cache.mlB2UMap[bIdx] === 'undefined') { + self.cache.mlB2UMap[bIdx] = uIdx; + } + } + + bIdx++; + }); + + // Rebuild the media array in the right order and add the missing mLines + // (missing from the Plan B SDP). + session.media = []; + mids = []; // reuse + + if (desc.type === 'answer') { + + // The media lines in the answer must match the media lines in the + // offer. The order is important too. Here we assume that Firefox is + // the answerer, so we merely have to use the reconstructed (unified) + // answer to update the cached (unified) answer accordingly. + // + // In the general case, one would have to use the cached (unified) + // offer to find the m-lines that are missing from the reconstructed + // answer, potentially grabbing them from the cached (unified) answer. + // One has to be careful with this approach because inactive m-lines do + // not always have an mid, making it tricky (impossible?) to find where + // exactly and which m-lines are missing from the reconstructed answer. + + for (var i = 0; i < cached.media.length; i++) { + var uLine = cached.media[i]; + + delete uLine.msid; + delete uLine.sources; + delete uLine.ssrcGroups; + + if (typeof sources2ul[i] === 'undefined') { + if (!uLine.direction + || uLine.direction === 'sendrecv') + uLine.direction = 'recvonly'; + else if (uLine.direction === 'sendonly') + uLine.direction = 'inactive'; + } else { + if (!uLine.direction + || uLine.direction === 'sendrecv') + uLine.direction = 'sendrecv'; + else if (uLine.direction === 'recvonly') + uLine.direction = 'sendonly'; + } + + uLine.sources = sources2ul[i]; + uLine.candidates = candidates; + uLine.iceUfrag = iceUfrag; + uLine.icePwd = icePwd; + uLine.fingerprint = fingerprint; + + uLine.rtp = rtp[uLine.type]; + uLine.payloads = payloads[uLine.type]; + uLine.rtcpFb = rtcpFb[uLine.type]; + + session.media.push(uLine); + + if (typeof uLine.mid === 'string') { + // inactive lines don't/may not have an mid. + mids.push(uLine.mid); + } + } + } else { + + // SDP offer/answer (and the JSEP spec) forbids removing an m-section + // under any circumstances. If we are no longer interested in sending a + // track, we just remove the msid and ssrc attributes and set it to + // either a=recvonly (as the reofferer, we must use recvonly if the + // other side was previously sending on the m-section, but we can also + // leave the possibility open if it wasn't previously in use), or + // a=inactive. + + if (typeof cached !== 'undefined' && + typeof cached.media !== 'undefined' && + Array.isArray(cached.media)) { + cached.media.forEach(function(uLine) { + mids.push(uLine.mid); + if (typeof mid2ul[uLine.mid] !== 'undefined') { + session.media.push(mid2ul[uLine.mid]); + } else { + delete uLine.msid; + delete uLine.sources; + delete uLine.ssrcGroups; + + if (!uLine.direction + || uLine.direction === 'sendrecv') { + uLine.direction = 'sendonly'; + } + if (!uLine.direction + || uLine.direction === 'recvonly') { + uLine.direction = 'inactive'; + } + + addSetupAttr (uLine); + session.media.push(uLine); + } + }); + } + + // Add all the remaining (new) m-lines of the transformed SDP. + Object.keys(mid2ul).forEach(function(mid) { + if (mids.indexOf(mid) === -1) { + mids.push(mid); + if (mid2ul[mid].direction === 'recvonly') { + // This is a remote recvonly channel. Add its SSRC to the + // appropriate sendrecv or sendonly channel. + // TODO(gp) what if we don't have sendrecv/sendonly + // channel? + + var done = false; + + session.media.some(function (uLine) { + if ((uLine.direction === 'sendrecv' || + uLine.direction === 'sendonly') && + uLine.type === mid2ul[mid].type) { + // mid2ul[mid] shouldn't have any ssrc-groups + Object.keys(mid2ul[mid].sources).forEach( + function (ssrc) { + uLine.sources[ssrc] = + mid2ul[mid].sources[ssrc]; + }); + + done = true; + return true; + } + }); + + if (!done) { + session.media.push(mid2ul[mid]); + } + } else { + session.media.push(mid2ul[mid]); + } + } + }); + } + + // After we have constructed the Plan Unified m-lines we can figure out + // where (in which m-line) to place the 'recvonly SSRCs'. + // Note: we assume here that we are the answerer in the O/A, so any offers + // which we translate come from the remote side, while answers are local + // (and so our last local description is cached as an 'answer'). + ["audio", "video"].forEach(function (type) { + if (!session || !session.media || !Array.isArray(session.media)) + return; + + var idx = null; + if (Object.keys(recvonlySsrcs[type]).length > 0) { + idx = self.getFirstSendingIndexFromAnswer(type); + if (idx === null){ + // If this is the first offer we receive, we don't have a + // cached answer. Assume that we will be sending media using + // the first m-line for each media type. + + for (var i = 0; i < session.media.length; i++) { + if (session.media[i].type === type) { + idx = i; + break; + } + } + } + } + + if (idx && session.media.length > idx) { + var mLine = session.media[idx]; + Object.keys(recvonlySsrcs[type]).forEach(function(ssrc) { + if (mLine.sources && mLine.sources[ssrc]) { + console.warn("Replacing an existing SSRC."); + } + if (!mLine.sources) { + mLine.sources = {}; + } + + mLine.sources[ssrc] = recvonlySsrcs[type][ssrc]; + }); + } + }); + + if (typeof session.groups !== 'undefined') { + // We regenerate the BUNDLE group (since we regenerated the mids) + session.groups.some(function(group) { + if (group.type === 'BUNDLE') { + group.mids = mids.join(' '); + return true; + } + }); + } + + // msid semantic + session.msidSemantic = { + semantic: 'WMS', + token: '*' + }; + + var resStr = transform.write(session); + + // Cache the transformed SDP (Unified Plan) for later re-use in this + // function. + this.cache[desc.type] = resStr; + + return new RTCSessionDescription({ + type: desc.type, + sdp: resStr + }); + + //#endregion +}; + +},{"./array-equals":15,"./transform":18}],18:[function(require,module,exports){ +/* Copyright @ 2015 Atlassian Pty Ltd + * + * 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. + */ + +var transform = require('sdp-transform'); + +exports.write = function(session, opts) { + + if (typeof session !== 'undefined' && + typeof session.media !== 'undefined' && + Array.isArray(session.media)) { + + session.media.forEach(function (mLine) { + // expand sources to ssrcs + if (typeof mLine.sources !== 'undefined' && + Object.keys(mLine.sources).length !== 0) { + mLine.ssrcs = []; + Object.keys(mLine.sources).forEach(function (ssrc) { + var source = mLine.sources[ssrc]; + Object.keys(source).forEach(function (attribute) { + mLine.ssrcs.push({ + id: ssrc, + attribute: attribute, + value: source[attribute] + }); + }); + }); + delete mLine.sources; + } + + // join ssrcs in ssrc groups + if (typeof mLine.ssrcGroups !== 'undefined' && + Array.isArray(mLine.ssrcGroups)) { + mLine.ssrcGroups.forEach(function (ssrcGroup) { + if (typeof ssrcGroup.ssrcs !== 'undefined' && + Array.isArray(ssrcGroup.ssrcs)) { + ssrcGroup.ssrcs = ssrcGroup.ssrcs.join(' '); + } + }); + } + }); + } + + // join group mids + if (typeof session !== 'undefined' && + typeof session.groups !== 'undefined' && Array.isArray(session.groups)) { + + session.groups.forEach(function (g) { + if (typeof g.mids !== 'undefined' && Array.isArray(g.mids)) { + g.mids = g.mids.join(' '); + } + }); + } + + return transform.write(session, opts); +}; + +exports.parse = function(sdp) { + var session = transform.parse(sdp); + + if (typeof session !== 'undefined' && typeof session.media !== 'undefined' && + Array.isArray(session.media)) { + + session.media.forEach(function (mLine) { + // group sources attributes by ssrc + if (typeof mLine.ssrcs !== 'undefined' && Array.isArray(mLine.ssrcs)) { + mLine.sources = {}; + mLine.ssrcs.forEach(function (ssrc) { + if (!mLine.sources[ssrc.id]) + mLine.sources[ssrc.id] = {}; + mLine.sources[ssrc.id][ssrc.attribute] = ssrc.value; + }); + + delete mLine.ssrcs; + } + + // split ssrcs in ssrc groups + if (typeof mLine.ssrcGroups !== 'undefined' && + Array.isArray(mLine.ssrcGroups)) { + mLine.ssrcGroups.forEach(function (ssrcGroup) { + if (typeof ssrcGroup.ssrcs === 'string') { + ssrcGroup.ssrcs = ssrcGroup.ssrcs.split(' '); + } + }); + } + }); + } + // split group mids + if (typeof session !== 'undefined' && + typeof session.groups !== 'undefined' && Array.isArray(session.groups)) { + + session.groups.forEach(function (g) { + if (typeof g.mids === 'string') { + g.mids = g.mids.split(' '); + } + }); + } + + return session; +}; + + +},{"sdp-transform":12}],19:[function(require,module,exports){ + /* eslint-env node */ +'use strict'; + +// SDP helpers. +var SDPUtils = {}; + +// Generate an alphanumeric identifier for cname or mids. +// TODO: use UUIDs instead? https://gist.github.com/jed/982883 +SDPUtils.generateIdentifier = function() { + return Math.random().toString(36).substr(2, 10); +}; + +// The RTCP CNAME used by all peerconnections from the same JS. +SDPUtils.localCName = SDPUtils.generateIdentifier(); + +// Splits SDP into lines, dealing with both CRLF and LF. +SDPUtils.splitLines = function(blob) { + return blob.trim().split('\n').map(function(line) { + return line.trim(); + }); +}; +// Splits SDP into sessionpart and mediasections. Ensures CRLF. +SDPUtils.splitSections = function(blob) { + var parts = blob.split('\nm='); + return parts.map(function(part, index) { + return (index > 0 ? 'm=' + part : part).trim() + '\r\n'; + }); +}; + +// returns the session description. +SDPUtils.getDescription = function(blob) { + var sections = SDPUtils.splitSections(blob); + return sections && sections[0]; +}; + +// returns the individual media sections. +SDPUtils.getMediaSections = function(blob) { + var sections = SDPUtils.splitSections(blob); + sections.shift(); + return sections; +}; + +// Returns lines that start with a certain prefix. +SDPUtils.matchPrefix = function(blob, prefix) { + return SDPUtils.splitLines(blob).filter(function(line) { + return line.indexOf(prefix) === 0; + }); +}; + +// Parses an ICE candidate line. Sample input: +// candidate:702786350 2 udp 41819902 8.8.8.8 60769 typ relay raddr 8.8.8.8 +// rport 55996" +SDPUtils.parseCandidate = function(line) { + var parts; + // Parse both variants. + if (line.indexOf('a=candidate:') === 0) { + parts = line.substring(12).split(' '); + } else { + parts = line.substring(10).split(' '); + } + + var candidate = { + foundation: parts[0], + component: parseInt(parts[1], 10), + protocol: parts[2].toLowerCase(), + priority: parseInt(parts[3], 10), + ip: parts[4], + port: parseInt(parts[5], 10), + // skip parts[6] == 'typ' + type: parts[7] + }; + + for (var i = 8; i < parts.length; i += 2) { + switch (parts[i]) { + case 'raddr': + candidate.relatedAddress = parts[i + 1]; + break; + case 'rport': + candidate.relatedPort = parseInt(parts[i + 1], 10); + break; + case 'tcptype': + candidate.tcpType = parts[i + 1]; + break; + case 'ufrag': + candidate.ufrag = parts[i + 1]; // for backward compability. + candidate.usernameFragment = parts[i + 1]; + break; + default: // extension handling, in particular ufrag + candidate[parts[i]] = parts[i + 1]; + break; + } + } + return candidate; +}; + +// Translates a candidate object into SDP candidate attribute. +SDPUtils.writeCandidate = function(candidate) { + var sdp = []; + sdp.push(candidate.foundation); + sdp.push(candidate.component); + sdp.push(candidate.protocol.toUpperCase()); + sdp.push(candidate.priority); + sdp.push(candidate.ip); + sdp.push(candidate.port); + + var type = candidate.type; + sdp.push('typ'); + sdp.push(type); + if (type !== 'host' && candidate.relatedAddress && + candidate.relatedPort) { + sdp.push('raddr'); + sdp.push(candidate.relatedAddress); // was: relAddr + sdp.push('rport'); + sdp.push(candidate.relatedPort); // was: relPort + } + if (candidate.tcpType && candidate.protocol.toLowerCase() === 'tcp') { + sdp.push('tcptype'); + sdp.push(candidate.tcpType); + } + if (candidate.usernameFragment || candidate.ufrag) { + sdp.push('ufrag'); + sdp.push(candidate.usernameFragment || candidate.ufrag); + } + return 'candidate:' + sdp.join(' '); +}; + +// Parses an ice-options line, returns an array of option tags. +// a=ice-options:foo bar +SDPUtils.parseIceOptions = function(line) { + return line.substr(14).split(' '); +} + +// Parses an rtpmap line, returns RTCRtpCoddecParameters. Sample input: +// a=rtpmap:111 opus/48000/2 +SDPUtils.parseRtpMap = function(line) { + var parts = line.substr(9).split(' '); + var parsed = { + payloadType: parseInt(parts.shift(), 10) // was: id + }; + + parts = parts[0].split('/'); + + parsed.name = parts[0]; + parsed.clockRate = parseInt(parts[1], 10); // was: clockrate + // was: channels + parsed.numChannels = parts.length === 3 ? parseInt(parts[2], 10) : 1; + return parsed; +}; + +// Generate an a=rtpmap line from RTCRtpCodecCapability or +// RTCRtpCodecParameters. +SDPUtils.writeRtpMap = function(codec) { + var pt = codec.payloadType; + if (codec.preferredPayloadType !== undefined) { + pt = codec.preferredPayloadType; + } + return 'a=rtpmap:' + pt + ' ' + codec.name + '/' + codec.clockRate + + (codec.numChannels !== 1 ? '/' + codec.numChannels : '') + '\r\n'; +}; + +// Parses an a=extmap line (headerextension from RFC 5285). Sample input: +// a=extmap:2 urn:ietf:params:rtp-hdrext:toffset +// a=extmap:2/sendonly urn:ietf:params:rtp-hdrext:toffset +SDPUtils.parseExtmap = function(line) { + var parts = line.substr(9).split(' '); + return { + id: parseInt(parts[0], 10), + direction: parts[0].indexOf('/') > 0 ? parts[0].split('/')[1] : 'sendrecv', + uri: parts[1] + }; +}; + +// Generates a=extmap line from RTCRtpHeaderExtensionParameters or +// RTCRtpHeaderExtension. +SDPUtils.writeExtmap = function(headerExtension) { + return 'a=extmap:' + (headerExtension.id || headerExtension.preferredId) + + (headerExtension.direction && headerExtension.direction !== 'sendrecv' + ? '/' + headerExtension.direction + : '') + + ' ' + headerExtension.uri + '\r\n'; +}; + +// Parses an ftmp line, returns dictionary. Sample input: +// a=fmtp:96 vbr=on;cng=on +// Also deals with vbr=on; cng=on +SDPUtils.parseFmtp = function(line) { + var parsed = {}; + var kv; + var parts = line.substr(line.indexOf(' ') + 1).split(';'); + for (var j = 0; j < parts.length; j++) { + kv = parts[j].trim().split('='); + parsed[kv[0].trim()] = kv[1]; + } + return parsed; +}; + +// Generates an a=ftmp line from RTCRtpCodecCapability or RTCRtpCodecParameters. +SDPUtils.writeFmtp = function(codec) { + var line = ''; + var pt = codec.payloadType; + if (codec.preferredPayloadType !== undefined) { + pt = codec.preferredPayloadType; + } + if (codec.parameters && Object.keys(codec.parameters).length) { + var params = []; + Object.keys(codec.parameters).forEach(function(param) { + params.push(param + '=' + codec.parameters[param]); + }); + line += 'a=fmtp:' + pt + ' ' + params.join(';') + '\r\n'; + } + return line; +}; + +// Parses an rtcp-fb line, returns RTCPRtcpFeedback object. Sample input: +// a=rtcp-fb:98 nack rpsi +SDPUtils.parseRtcpFb = function(line) { + var parts = line.substr(line.indexOf(' ') + 1).split(' '); + return { + type: parts.shift(), + parameter: parts.join(' ') + }; +}; +// Generate a=rtcp-fb lines from RTCRtpCodecCapability or RTCRtpCodecParameters. +SDPUtils.writeRtcpFb = function(codec) { + var lines = ''; + var pt = codec.payloadType; + if (codec.preferredPayloadType !== undefined) { + pt = codec.preferredPayloadType; + } + if (codec.rtcpFeedback && codec.rtcpFeedback.length) { + // FIXME: special handling for trr-int? + codec.rtcpFeedback.forEach(function(fb) { + lines += 'a=rtcp-fb:' + pt + ' ' + fb.type + + (fb.parameter && fb.parameter.length ? ' ' + fb.parameter : '') + + '\r\n'; + }); + } + return lines; +}; + +// Parses an RFC 5576 ssrc media attribute. Sample input: +// a=ssrc:3735928559 cname:something +SDPUtils.parseSsrcMedia = function(line) { + var sp = line.indexOf(' '); + var parts = { + ssrc: parseInt(line.substr(7, sp - 7), 10) + }; + var colon = line.indexOf(':', sp); + if (colon > -1) { + parts.attribute = line.substr(sp + 1, colon - sp - 1); + parts.value = line.substr(colon + 1); + } else { + parts.attribute = line.substr(sp + 1); + } + return parts; +}; + +// Extracts the MID (RFC 5888) from a media section. +// returns the MID or undefined if no mid line was found. +SDPUtils.getMid = function(mediaSection) { + var mid = SDPUtils.matchPrefix(mediaSection, 'a=mid:')[0]; + if (mid) { + return mid.substr(6); + } +} + +SDPUtils.parseFingerprint = function(line) { + var parts = line.substr(14).split(' '); + return { + algorithm: parts[0].toLowerCase(), // algorithm is case-sensitive in Edge. + value: parts[1] + }; +}; + +// Extracts DTLS parameters from SDP media section or sessionpart. +// FIXME: for consistency with other functions this should only +// get the fingerprint line as input. See also getIceParameters. +SDPUtils.getDtlsParameters = function(mediaSection, sessionpart) { + var lines = SDPUtils.matchPrefix(mediaSection + sessionpart, + 'a=fingerprint:'); + // Note: a=setup line is ignored since we use the 'auto' role. + // Note2: 'algorithm' is not case sensitive except in Edge. + return { + role: 'auto', + fingerprints: lines.map(SDPUtils.parseFingerprint) + }; +}; + +// Serializes DTLS parameters to SDP. +SDPUtils.writeDtlsParameters = function(params, setupType) { + var sdp = 'a=setup:' + setupType + '\r\n'; + params.fingerprints.forEach(function(fp) { + sdp += 'a=fingerprint:' + fp.algorithm + ' ' + fp.value + '\r\n'; + }); + return sdp; +}; +// Parses ICE information from SDP media section or sessionpart. +// FIXME: for consistency with other functions this should only +// get the ice-ufrag and ice-pwd lines as input. +SDPUtils.getIceParameters = function(mediaSection, sessionpart) { + var lines = SDPUtils.splitLines(mediaSection); + // Search in session part, too. + lines = lines.concat(SDPUtils.splitLines(sessionpart)); + var iceParameters = { + usernameFragment: lines.filter(function(line) { + return line.indexOf('a=ice-ufrag:') === 0; + })[0].substr(12), + password: lines.filter(function(line) { + return line.indexOf('a=ice-pwd:') === 0; + })[0].substr(10) + }; + return iceParameters; +}; + +// Serializes ICE parameters to SDP. +SDPUtils.writeIceParameters = function(params) { + return 'a=ice-ufrag:' + params.usernameFragment + '\r\n' + + 'a=ice-pwd:' + params.password + '\r\n'; +}; + +// Parses the SDP media section and returns RTCRtpParameters. +SDPUtils.parseRtpParameters = function(mediaSection) { + var description = { + codecs: [], + headerExtensions: [], + fecMechanisms: [], + rtcp: [] + }; + var lines = SDPUtils.splitLines(mediaSection); + var mline = lines[0].split(' '); + for (var i = 3; i < mline.length; i++) { // find all codecs from mline[3..] + var pt = mline[i]; + var rtpmapline = SDPUtils.matchPrefix( + mediaSection, 'a=rtpmap:' + pt + ' ')[0]; + if (rtpmapline) { + var codec = SDPUtils.parseRtpMap(rtpmapline); + var fmtps = SDPUtils.matchPrefix( + mediaSection, 'a=fmtp:' + pt + ' '); + // Only the first a=fmtp: is considered. + codec.parameters = fmtps.length ? SDPUtils.parseFmtp(fmtps[0]) : {}; + codec.rtcpFeedback = SDPUtils.matchPrefix( + mediaSection, 'a=rtcp-fb:' + pt + ' ') + .map(SDPUtils.parseRtcpFb); + description.codecs.push(codec); + // parse FEC mechanisms from rtpmap lines. + switch (codec.name.toUpperCase()) { + case 'RED': + case 'ULPFEC': + description.fecMechanisms.push(codec.name.toUpperCase()); + break; + default: // only RED and ULPFEC are recognized as FEC mechanisms. + break; + } + } + } + SDPUtils.matchPrefix(mediaSection, 'a=extmap:').forEach(function(line) { + description.headerExtensions.push(SDPUtils.parseExtmap(line)); + }); + // FIXME: parse rtcp. + return description; +}; + +// Generates parts of the SDP media section describing the capabilities / +// parameters. +SDPUtils.writeRtpDescription = function(kind, caps) { + var sdp = ''; + + // Build the mline. + sdp += 'm=' + kind + ' '; + sdp += caps.codecs.length > 0 ? '9' : '0'; // reject if no codecs. + sdp += ' UDP/TLS/RTP/SAVPF '; + sdp += caps.codecs.map(function(codec) { + if (codec.preferredPayloadType !== undefined) { + return codec.preferredPayloadType; + } + return codec.payloadType; + }).join(' ') + '\r\n'; + + sdp += 'c=IN IP4 0.0.0.0\r\n'; + sdp += 'a=rtcp:9 IN IP4 0.0.0.0\r\n'; + + // Add a=rtpmap lines for each codec. Also fmtp and rtcp-fb. + caps.codecs.forEach(function(codec) { + sdp += SDPUtils.writeRtpMap(codec); + sdp += SDPUtils.writeFmtp(codec); + sdp += SDPUtils.writeRtcpFb(codec); + }); + var maxptime = 0; + caps.codecs.forEach(function(codec) { + if (codec.maxptime > maxptime) { + maxptime = codec.maxptime; + } + }); + if (maxptime > 0) { + sdp += 'a=maxptime:' + maxptime + '\r\n'; + } + sdp += 'a=rtcp-mux\r\n'; + + caps.headerExtensions.forEach(function(extension) { + sdp += SDPUtils.writeExtmap(extension); + }); + // FIXME: write fecMechanisms. + return sdp; +}; + +// Parses the SDP media section and returns an array of +// RTCRtpEncodingParameters. +SDPUtils.parseRtpEncodingParameters = function(mediaSection) { + var encodingParameters = []; + var description = SDPUtils.parseRtpParameters(mediaSection); + var hasRed = description.fecMechanisms.indexOf('RED') !== -1; + var hasUlpfec = description.fecMechanisms.indexOf('ULPFEC') !== -1; + + // filter a=ssrc:... cname:, ignore PlanB-msid + var ssrcs = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:') + .map(function(line) { + return SDPUtils.parseSsrcMedia(line); + }) + .filter(function(parts) { + return parts.attribute === 'cname'; + }); + var primarySsrc = ssrcs.length > 0 && ssrcs[0].ssrc; + var secondarySsrc; + + var flows = SDPUtils.matchPrefix(mediaSection, 'a=ssrc-group:FID') + .map(function(line) { + var parts = line.split(' '); + parts.shift(); + return parts.map(function(part) { + return parseInt(part, 10); + }); + }); + if (flows.length > 0 && flows[0].length > 1 && flows[0][0] === primarySsrc) { + secondarySsrc = flows[0][1]; + } + + description.codecs.forEach(function(codec) { + if (codec.name.toUpperCase() === 'RTX' && codec.parameters.apt) { + var encParam = { + ssrc: primarySsrc, + codecPayloadType: parseInt(codec.parameters.apt, 10), + rtx: { + ssrc: secondarySsrc + } + }; + encodingParameters.push(encParam); + if (hasRed) { + encParam = JSON.parse(JSON.stringify(encParam)); + encParam.fec = { + ssrc: secondarySsrc, + mechanism: hasUlpfec ? 'red+ulpfec' : 'red' + }; + encodingParameters.push(encParam); + } + } + }); + if (encodingParameters.length === 0 && primarySsrc) { + encodingParameters.push({ + ssrc: primarySsrc + }); + } + + // we support both b=AS and b=TIAS but interpret AS as TIAS. + var bandwidth = SDPUtils.matchPrefix(mediaSection, 'b='); + if (bandwidth.length) { + if (bandwidth[0].indexOf('b=TIAS:') === 0) { + bandwidth = parseInt(bandwidth[0].substr(7), 10); + } else if (bandwidth[0].indexOf('b=AS:') === 0) { + // use formula from JSEP to convert b=AS to TIAS value. + bandwidth = parseInt(bandwidth[0].substr(5), 10) * 1000 * 0.95 + - (50 * 40 * 8); + } else { + bandwidth = undefined; + } + encodingParameters.forEach(function(params) { + params.maxBitrate = bandwidth; + }); + } + return encodingParameters; +}; + +// parses http://draft.ortc.org/#rtcrtcpparameters* +SDPUtils.parseRtcpParameters = function(mediaSection) { + var rtcpParameters = {}; + + var cname; + // Gets the first SSRC. Note that with RTX there might be multiple + // SSRCs. + var remoteSsrc = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:') + .map(function(line) { + return SDPUtils.parseSsrcMedia(line); + }) + .filter(function(obj) { + return obj.attribute === 'cname'; + })[0]; + if (remoteSsrc) { + rtcpParameters.cname = remoteSsrc.value; + rtcpParameters.ssrc = remoteSsrc.ssrc; + } + + // Edge uses the compound attribute instead of reducedSize + // compound is !reducedSize + var rsize = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-rsize'); + rtcpParameters.reducedSize = rsize.length > 0; + rtcpParameters.compound = rsize.length === 0; + + // parses the rtcp-mux attrіbute. + // Note that Edge does not support unmuxed RTCP. + var mux = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-mux'); + rtcpParameters.mux = mux.length > 0; + + return rtcpParameters; +}; + +// parses either a=msid: or a=ssrc:... msid lines and returns +// the id of the MediaStream and MediaStreamTrack. +SDPUtils.parseMsid = function(mediaSection) { + var parts; + var spec = SDPUtils.matchPrefix(mediaSection, 'a=msid:'); + if (spec.length === 1) { + parts = spec[0].substr(7).split(' '); + return {stream: parts[0], track: parts[1]}; + } + var planB = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:') + .map(function(line) { + return SDPUtils.parseSsrcMedia(line); + }) + .filter(function(parts) { + return parts.attribute === 'msid'; + }); + if (planB.length > 0) { + parts = planB[0].value.split(' '); + return {stream: parts[0], track: parts[1]}; + } +}; + +// Generate a session ID for SDP. +// https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-20#section-5.2.1 +// recommends using a cryptographically random +ve 64-bit value +// but right now this should be acceptable and within the right range +SDPUtils.generateSessionId = function() { + return Math.random().toString().substr(2, 21); +}; + +// Write boilder plate for start of SDP +// sessId argument is optional - if not supplied it will +// be generated randomly +// sessVersion is optional and defaults to 2 +SDPUtils.writeSessionBoilerplate = function(sessId, sessVer) { + var sessionId; + var version = sessVer !== undefined ? sessVer : 2; + if (sessId) { + sessionId = sessId; + } else { + sessionId = SDPUtils.generateSessionId(); + } + // FIXME: sess-id should be an NTP timestamp. + return 'v=0\r\n' + + 'o=thisisadapterortc ' + sessionId + ' ' + version + ' IN IP4 127.0.0.1\r\n' + + 's=-\r\n' + + 't=0 0\r\n'; +}; + +SDPUtils.writeMediaSection = function(transceiver, caps, type, stream) { + var sdp = SDPUtils.writeRtpDescription(transceiver.kind, caps); + + // Map ICE parameters (ufrag, pwd) to SDP. + sdp += SDPUtils.writeIceParameters( + transceiver.iceGatherer.getLocalParameters()); + + // Map DTLS parameters to SDP. + sdp += SDPUtils.writeDtlsParameters( + transceiver.dtlsTransport.getLocalParameters(), + type === 'offer' ? 'actpass' : 'active'); + + sdp += 'a=mid:' + transceiver.mid + '\r\n'; + + if (transceiver.direction) { + sdp += 'a=' + transceiver.direction + '\r\n'; + } else if (transceiver.rtpSender && transceiver.rtpReceiver) { + sdp += 'a=sendrecv\r\n'; + } else if (transceiver.rtpSender) { + sdp += 'a=sendonly\r\n'; + } else if (transceiver.rtpReceiver) { + sdp += 'a=recvonly\r\n'; + } else { + sdp += 'a=inactive\r\n'; + } + + if (transceiver.rtpSender) { + // spec. + var msid = 'msid:' + stream.id + ' ' + + transceiver.rtpSender.track.id + '\r\n'; + sdp += 'a=' + msid; + + // for Chrome. + sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc + + ' ' + msid; + if (transceiver.sendEncodingParameters[0].rtx) { + sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc + + ' ' + msid; + sdp += 'a=ssrc-group:FID ' + + transceiver.sendEncodingParameters[0].ssrc + ' ' + + transceiver.sendEncodingParameters[0].rtx.ssrc + + '\r\n'; + } + } + // FIXME: this should be written by writeRtpDescription. + sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc + + ' cname:' + SDPUtils.localCName + '\r\n'; + if (transceiver.rtpSender && transceiver.sendEncodingParameters[0].rtx) { + sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc + + ' cname:' + SDPUtils.localCName + '\r\n'; + } + return sdp; +}; + +// Gets the direction from the mediaSection or the sessionpart. +SDPUtils.getDirection = function(mediaSection, sessionpart) { + // Look for sendrecv, sendonly, recvonly, inactive, default to sendrecv. + var lines = SDPUtils.splitLines(mediaSection); + for (var i = 0; i < lines.length; i++) { + switch (lines[i]) { + case 'a=sendrecv': + case 'a=sendonly': + case 'a=recvonly': + case 'a=inactive': + return lines[i].substr(2); + default: + // FIXME: What should happen here? + } + } + if (sessionpart) { + return SDPUtils.getDirection(sessionpart); + } + return 'sendrecv'; +}; + +SDPUtils.getKind = function(mediaSection) { + var lines = SDPUtils.splitLines(mediaSection); + var mline = lines[0].split(' '); + return mline[0].substr(2); +}; + +SDPUtils.isRejected = function(mediaSection) { + return mediaSection.split(' ', 2)[1] === '0'; +}; + +SDPUtils.parseMLine = function(mediaSection) { + var lines = SDPUtils.splitLines(mediaSection); + var parts = lines[0].substr(2).split(' '); + return { + kind: parts[0], + port: parseInt(parts[1], 10), + protocol: parts[2], + fmt: parts.slice(3).join(' ') + }; +}; + +SDPUtils.parseOLine = function(mediaSection) { + var line = SDPUtils.matchPrefix(mediaSection, 'o=')[0]; + var parts = line.substr(2).split(' '); + return { + username: parts[0], + sessionId: parts[1], + sessionVersion: parseInt(parts[2], 10), + netType: parts[3], + addressType: parts[4], + address: parts[5], + }; +} + +// Expose public methods. +if (typeof module === 'object') { + module.exports = SDPUtils; +} + +},{}],20:[function(require,module,exports){ +/** + * UAParser.js v0.7.17 + * Lightweight JavaScript-based User-Agent string parser + * https://github.com/faisalman/ua-parser-js + * + * Copyright © 2012-2016 Faisal Salman + * Dual licensed under GPLv2 & MIT + */ + +(function (window, undefined) { + + 'use strict'; + + ////////////// + // Constants + ///////////// + + + var LIBVERSION = '0.7.17', + EMPTY = '', + UNKNOWN = '?', + FUNC_TYPE = 'function', + UNDEF_TYPE = 'undefined', + OBJ_TYPE = 'object', + STR_TYPE = 'string', + MAJOR = 'major', // deprecated + MODEL = 'model', + NAME = 'name', + TYPE = 'type', + VENDOR = 'vendor', + VERSION = 'version', + ARCHITECTURE= 'architecture', + CONSOLE = 'console', + MOBILE = 'mobile', + TABLET = 'tablet', + SMARTTV = 'smarttv', + WEARABLE = 'wearable', + EMBEDDED = 'embedded'; + + + /////////// + // Helper + ////////// + + + var util = { + extend : function (regexes, extensions) { + var margedRegexes = {}; + for (var i in regexes) { + if (extensions[i] && extensions[i].length % 2 === 0) { + margedRegexes[i] = extensions[i].concat(regexes[i]); + } else { + margedRegexes[i] = regexes[i]; + } + } + return margedRegexes; + }, + has : function (str1, str2) { + if (typeof str1 === "string") { + return str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1; + } else { + return false; + } + }, + lowerize : function (str) { + return str.toLowerCase(); + }, + major : function (version) { + return typeof(version) === STR_TYPE ? version.replace(/[^\d\.]/g,'').split(".")[0] : undefined; + }, + trim : function (str) { + return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); + } + }; + + + /////////////// + // Map helper + ////////////// + + + var mapper = { + + rgx : function (ua, arrays) { + + //var result = {}, + var i = 0, j, k, p, q, matches, match;//, args = arguments; + + /*// construct object barebones + for (p = 0; p < args[1].length; p++) { + q = args[1][p]; + result[typeof q === OBJ_TYPE ? q[0] : q] = undefined; + }*/ + + // loop through all regexes maps + while (i < arrays.length && !matches) { + + var regex = arrays[i], // even sequence (0,2,4,..) + props = arrays[i + 1]; // odd sequence (1,3,5,..) + j = k = 0; + + // try matching uastring with regexes + while (j < regex.length && !matches) { + + matches = regex[j++].exec(ua); + + if (!!matches) { + for (p = 0; p < props.length; p++) { + match = matches[++k]; + q = props[p]; + // check if given property is actually array + if (typeof q === OBJ_TYPE && q.length > 0) { + if (q.length == 2) { + if (typeof q[1] == FUNC_TYPE) { + // assign modified match + this[q[0]] = q[1].call(this, match); + } else { + // assign given value, ignore regex match + this[q[0]] = q[1]; + } + } else if (q.length == 3) { + // check whether function or regex + if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) { + // call function (usually string mapper) + this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined; + } else { + // sanitize match using given regex + this[q[0]] = match ? match.replace(q[1], q[2]) : undefined; + } + } else if (q.length == 4) { + this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined; + } + } else { + this[q] = match ? match : undefined; + } + } + } + } + i += 2; + } + // console.log(this); + //return this; + }, + + str : function (str, map) { + + for (var i in map) { + // check if array + if (typeof map[i] === OBJ_TYPE && map[i].length > 0) { + for (var j = 0; j < map[i].length; j++) { + if (util.has(map[i][j], str)) { + return (i === UNKNOWN) ? undefined : i; + } + } + } else if (util.has(map[i], str)) { + return (i === UNKNOWN) ? undefined : i; + } + } + return str; + } + }; + + + /////////////// + // String map + ////////////// + + + var maps = { + + browser : { + oldsafari : { + version : { + '1.0' : '/8', + '1.2' : '/1', + '1.3' : '/3', + '2.0' : '/412', + '2.0.2' : '/416', + '2.0.3' : '/417', + '2.0.4' : '/419', + '?' : '/' + } + } + }, + + device : { + amazon : { + model : { + 'Fire Phone' : ['SD', 'KF'] + } + }, + sprint : { + model : { + 'Evo Shift 4G' : '7373KT' + }, + vendor : { + 'HTC' : 'APA', + 'Sprint' : 'Sprint' + } + } + }, + + os : { + windows : { + version : { + 'ME' : '4.90', + 'NT 3.11' : 'NT3.51', + 'NT 4.0' : 'NT4.0', + '2000' : 'NT 5.0', + 'XP' : ['NT 5.1', 'NT 5.2'], + 'Vista' : 'NT 6.0', + '7' : 'NT 6.1', + '8' : 'NT 6.2', + '8.1' : 'NT 6.3', + '10' : ['NT 6.4', 'NT 10.0'], + 'RT' : 'ARM' + } + } + } + }; + + + ////////////// + // Regex map + ///////////// + + + var regexes = { + + browser : [[ + + // Presto based + /(opera\smini)\/([\w\.-]+)/i, // Opera Mini + /(opera\s[mobiletab]+).+version\/([\w\.-]+)/i, // Opera Mobi/Tablet + /(opera).+version\/([\w\.]+)/i, // Opera > 9.80 + /(opera)[\/\s]+([\w\.]+)/i // Opera < 9.80 + ], [NAME, VERSION], [ + + /(opios)[\/\s]+([\w\.]+)/i // Opera mini on iphone >= 8.0 + ], [[NAME, 'Opera Mini'], VERSION], [ + + /\s(opr)\/([\w\.]+)/i // Opera Webkit + ], [[NAME, 'Opera'], VERSION], [ + + // Mixed + /(kindle)\/([\w\.]+)/i, // Kindle + /(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?([\w\.]+)*/i, + // Lunascape/Maxthon/Netfront/Jasmine/Blazer + + // Trident based + /(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?([\w\.]*)/i, + // Avant/IEMobile/SlimBrowser/Baidu + /(?:ms|\()(ie)\s([\w\.]+)/i, // Internet Explorer + + // Webkit/KHTML based + /(rekonq)\/([\w\.]+)*/i, // Rekonq + /(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser)\/([\w\.-]+)/i + // Chromium/Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser + ], [NAME, VERSION], [ + + /(trident).+rv[:\s]([\w\.]+).+like\sgecko/i // IE11 + ], [[NAME, 'IE'], VERSION], [ + + /(edge)\/((\d+)?[\w\.]+)/i // Microsoft Edge + ], [NAME, VERSION], [ + + /(yabrowser)\/([\w\.]+)/i // Yandex + ], [[NAME, 'Yandex'], VERSION], [ + + /(puffin)\/([\w\.]+)/i // Puffin + ], [[NAME, 'Puffin'], VERSION], [ + + /((?:[\s\/])uc?\s?browser|(?:juc.+)ucweb)[\/\s]?([\w\.]+)/i + // UCBrowser + ], [[NAME, 'UCBrowser'], VERSION], [ + + /(comodo_dragon)\/([\w\.]+)/i // Comodo Dragon + ], [[NAME, /_/g, ' '], VERSION], [ + + /(micromessenger)\/([\w\.]+)/i // WeChat + ], [[NAME, 'WeChat'], VERSION], [ + + /(QQ)\/([\d\.]+)/i // QQ, aka ShouQ + ], [NAME, VERSION], [ + + /m?(qqbrowser)[\/\s]?([\w\.]+)/i // QQBrowser + ], [NAME, VERSION], [ + + /xiaomi\/miuibrowser\/([\w\.]+)/i // MIUI Browser + ], [VERSION, [NAME, 'MIUI Browser']], [ + + /;fbav\/([\w\.]+);/i // Facebook App for iOS & Android + ], [VERSION, [NAME, 'Facebook']], [ + + /headlesschrome(?:\/([\w\.]+)|\s)/i // Chrome Headless + ], [VERSION, [NAME, 'Chrome Headless']], [ + + /\swv\).+(chrome)\/([\w\.]+)/i // Chrome WebView + ], [[NAME, /(.+)/, '$1 WebView'], VERSION], [ + + /((?:oculus|samsung)browser)\/([\w\.]+)/i + ], [[NAME, /(.+(?:g|us))(.+)/, '$1 $2'], VERSION], [ // Oculus / Samsung Browser + + /android.+version\/([\w\.]+)\s+(?:mobile\s?safari|safari)*/i // Android Browser + ], [VERSION, [NAME, 'Android Browser']], [ + + /(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?([\w\.]+)/i + // Chrome/OmniWeb/Arora/Tizen/Nokia + ], [NAME, VERSION], [ + + /(dolfin)\/([\w\.]+)/i // Dolphin + ], [[NAME, 'Dolphin'], VERSION], [ + + /((?:android.+)crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS + ], [[NAME, 'Chrome'], VERSION], [ + + /(coast)\/([\w\.]+)/i // Opera Coast + ], [[NAME, 'Opera Coast'], VERSION], [ + + /fxios\/([\w\.-]+)/i // Firefox for iOS + ], [VERSION, [NAME, 'Firefox']], [ + + /version\/([\w\.]+).+?mobile\/\w+\s(safari)/i // Mobile Safari + ], [VERSION, [NAME, 'Mobile Safari']], [ + + /version\/([\w\.]+).+?(mobile\s?safari|safari)/i // Safari & Safari Mobile + ], [VERSION, NAME], [ + + /webkit.+?(gsa)\/([\w\.]+).+?(mobile\s?safari|safari)(\/[\w\.]+)/i // Google Search Appliance on iOS + ], [[NAME, 'GSA'], VERSION], [ + + /webkit.+?(mobile\s?safari|safari)(\/[\w\.]+)/i // Safari < 3.0 + ], [NAME, [VERSION, mapper.str, maps.browser.oldsafari.version]], [ + + /(konqueror)\/([\w\.]+)/i, // Konqueror + /(webkit|khtml)\/([\w\.]+)/i + ], [NAME, VERSION], [ + + // Gecko based + /(navigator|netscape)\/([\w\.-]+)/i // Netscape + ], [[NAME, 'Netscape'], VERSION], [ + /(swiftfox)/i, // Swiftfox + /(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?([\w\.\+]+)/i, + // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror + /(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/([\w\.-]+)/i, + // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix + /(mozilla)\/([\w\.]+).+rv\:.+gecko\/\d+/i, // Mozilla + + // Other + /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir)[\/\s]?([\w\.]+)/i, + // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Sleipnir + /(links)\s\(([\w\.]+)/i, // Links + /(gobrowser)\/?([\w\.]+)*/i, // GoBrowser + /(ice\s?browser)\/v?([\w\._]+)/i, // ICE Browser + /(mosaic)[\/\s]([\w\.]+)/i // Mosaic + ], [NAME, VERSION] + + /* ///////////////////// + // Media players BEGIN + //////////////////////// + + , [ + + /(apple(?:coremedia|))\/((\d+)[\w\._]+)/i, // Generic Apple CoreMedia + /(coremedia) v((\d+)[\w\._]+)/i + ], [NAME, VERSION], [ + + /(aqualung|lyssna|bsplayer)\/((\d+)?[\w\.-]+)/i // Aqualung/Lyssna/BSPlayer + ], [NAME, VERSION], [ + + /(ares|ossproxy)\s((\d+)[\w\.-]+)/i // Ares/OSSProxy + ], [NAME, VERSION], [ + + /(audacious|audimusicstream|amarok|bass|core|dalvik|gnomemplayer|music on console|nsplayer|psp-internetradioplayer|videos)\/((\d+)[\w\.-]+)/i, + // Audacious/AudiMusicStream/Amarok/BASS/OpenCORE/Dalvik/GnomeMplayer/MoC + // NSPlayer/PSP-InternetRadioPlayer/Videos + /(clementine|music player daemon)\s((\d+)[\w\.-]+)/i, // Clementine/MPD + /(lg player|nexplayer)\s((\d+)[\d\.]+)/i, + /player\/(nexplayer|lg player)\s((\d+)[\w\.-]+)/i // NexPlayer/LG Player + ], [NAME, VERSION], [ + /(nexplayer)\s((\d+)[\w\.-]+)/i // Nexplayer + ], [NAME, VERSION], [ + + /(flrp)\/((\d+)[\w\.-]+)/i // Flip Player + ], [[NAME, 'Flip Player'], VERSION], [ + + /(fstream|nativehost|queryseekspider|ia-archiver|facebookexternalhit)/i + // FStream/NativeHost/QuerySeekSpider/IA Archiver/facebookexternalhit + ], [NAME], [ + + /(gstreamer) souphttpsrc (?:\([^\)]+\)){0,1} libsoup\/((\d+)[\w\.-]+)/i + // Gstreamer + ], [NAME, VERSION], [ + + /(htc streaming player)\s[\w_]+\s\/\s((\d+)[\d\.]+)/i, // HTC Streaming Player + /(java|python-urllib|python-requests|wget|libcurl)\/((\d+)[\w\.-_]+)/i, + // Java/urllib/requests/wget/cURL + /(lavf)((\d+)[\d\.]+)/i // Lavf (FFMPEG) + ], [NAME, VERSION], [ + + /(htc_one_s)\/((\d+)[\d\.]+)/i // HTC One S + ], [[NAME, /_/g, ' '], VERSION], [ + + /(mplayer)(?:\s|\/)(?:(?:sherpya-){0,1}svn)(?:-|\s)(r\d+(?:-\d+[\w\.-]+){0,1})/i + // MPlayer SVN + ], [NAME, VERSION], [ + + /(mplayer)(?:\s|\/|[unkow-]+)((\d+)[\w\.-]+)/i // MPlayer + ], [NAME, VERSION], [ + + /(mplayer)/i, // MPlayer (no other info) + /(yourmuze)/i, // YourMuze + /(media player classic|nero showtime)/i // Media Player Classic/Nero ShowTime + ], [NAME], [ + + /(nero (?:home|scout))\/((\d+)[\w\.-]+)/i // Nero Home/Nero Scout + ], [NAME, VERSION], [ + + /(nokia\d+)\/((\d+)[\w\.-]+)/i // Nokia + ], [NAME, VERSION], [ + + /\s(songbird)\/((\d+)[\w\.-]+)/i // Songbird/Philips-Songbird + ], [NAME, VERSION], [ + + /(winamp)3 version ((\d+)[\w\.-]+)/i, // Winamp + /(winamp)\s((\d+)[\w\.-]+)/i, + /(winamp)mpeg\/((\d+)[\w\.-]+)/i + ], [NAME, VERSION], [ + + /(ocms-bot|tapinradio|tunein radio|unknown|winamp|inlight radio)/i // OCMS-bot/tap in radio/tunein/unknown/winamp (no other info) + // inlight radio + ], [NAME], [ + + /(quicktime|rma|radioapp|radioclientapplication|soundtap|totem|stagefright|streamium)\/((\d+)[\w\.-]+)/i + // QuickTime/RealMedia/RadioApp/RadioClientApplication/ + // SoundTap/Totem/Stagefright/Streamium + ], [NAME, VERSION], [ + + /(smp)((\d+)[\d\.]+)/i // SMP + ], [NAME, VERSION], [ + + /(vlc) media player - version ((\d+)[\w\.]+)/i, // VLC Videolan + /(vlc)\/((\d+)[\w\.-]+)/i, + /(xbmc|gvfs|xine|xmms|irapp)\/((\d+)[\w\.-]+)/i, // XBMC/gvfs/Xine/XMMS/irapp + /(foobar2000)\/((\d+)[\d\.]+)/i, // Foobar2000 + /(itunes)\/((\d+)[\d\.]+)/i // iTunes + ], [NAME, VERSION], [ + + /(wmplayer)\/((\d+)[\w\.-]+)/i, // Windows Media Player + /(windows-media-player)\/((\d+)[\w\.-]+)/i + ], [[NAME, /-/g, ' '], VERSION], [ + + /windows\/((\d+)[\w\.-]+) upnp\/[\d\.]+ dlnadoc\/[\d\.]+ (home media server)/i + // Windows Media Server + ], [VERSION, [NAME, 'Windows']], [ + + /(com\.riseupradioalarm)\/((\d+)[\d\.]*)/i // RiseUP Radio Alarm + ], [NAME, VERSION], [ + + /(rad.io)\s((\d+)[\d\.]+)/i, // Rad.io + /(radio.(?:de|at|fr))\s((\d+)[\d\.]+)/i + ], [[NAME, 'rad.io'], VERSION] + + ////////////////////// + // Media players END + ////////////////////*/ + + ], + + cpu : [[ + + /(?:(amd|x(?:(?:86|64)[_-])?|wow|win)64)[;\)]/i // AMD64 + ], [[ARCHITECTURE, 'amd64']], [ + + /(ia32(?=;))/i // IA32 (quicktime) + ], [[ARCHITECTURE, util.lowerize]], [ + + /((?:i[346]|x)86)[;\)]/i // IA32 + ], [[ARCHITECTURE, 'ia32']], [ + + // PocketPC mistakenly identified as PowerPC + /windows\s(ce|mobile);\sppc;/i + ], [[ARCHITECTURE, 'arm']], [ + + /((?:ppc|powerpc)(?:64)?)(?:\smac|;|\))/i // PowerPC + ], [[ARCHITECTURE, /ower/, '', util.lowerize]], [ + + /(sun4\w)[;\)]/i // SPARC + ], [[ARCHITECTURE, 'sparc']], [ + + /((?:avr32|ia64(?=;))|68k(?=\))|arm(?:64|(?=v\d+;))|(?=atmel\s)avr|(?:irix|mips|sparc)(?:64)?(?=;)|pa-risc)/i + // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC + ], [[ARCHITECTURE, util.lowerize]] + ], + + device : [[ + + /\((ipad|playbook);[\w\s\);-]+(rim|apple)/i // iPad/PlayBook + ], [MODEL, VENDOR, [TYPE, TABLET]], [ + + /applecoremedia\/[\w\.]+ \((ipad)/ // iPad + ], [MODEL, [VENDOR, 'Apple'], [TYPE, TABLET]], [ + + /(apple\s{0,1}tv)/i // Apple TV + ], [[MODEL, 'Apple TV'], [VENDOR, 'Apple']], [ + + /(archos)\s(gamepad2?)/i, // Archos + /(hp).+(touchpad)/i, // HP TouchPad + /(hp).+(tablet)/i, // HP Tablet + /(kindle)\/([\w\.]+)/i, // Kindle + /\s(nook)[\w\s]+build\/(\w+)/i, // Nook + /(dell)\s(strea[kpr\s\d]*[\dko])/i // Dell Streak + ], [VENDOR, MODEL, [TYPE, TABLET]], [ + + /(kf[A-z]+)\sbuild\/[\w\.]+.*silk\//i // Kindle Fire HD + ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [ + /(sd|kf)[0349hijorstuw]+\sbuild\/[\w\.]+.*silk\//i // Fire Phone + ], [[MODEL, mapper.str, maps.device.amazon.model], [VENDOR, 'Amazon'], [TYPE, MOBILE]], [ + + /\((ip[honed|\s\w*]+);.+(apple)/i // iPod/iPhone + ], [MODEL, VENDOR, [TYPE, MOBILE]], [ + /\((ip[honed|\s\w*]+);/i // iPod/iPhone + ], [MODEL, [VENDOR, 'Apple'], [TYPE, MOBILE]], [ + + /(blackberry)[\s-]?(\w+)/i, // BlackBerry + /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[\s_-]?([\w-]+)*/i, + // BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron + /(hp)\s([\w\s]+\w)/i, // HP iPAQ + /(asus)-?(\w+)/i // Asus + ], [VENDOR, MODEL, [TYPE, MOBILE]], [ + /\(bb10;\s(\w+)/i // BlackBerry 10 + ], [MODEL, [VENDOR, 'BlackBerry'], [TYPE, MOBILE]], [ + // Asus Tablets + /android.+(transfo[prime\s]{4,10}\s\w+|eeepc|slider\s\w+|nexus 7|padfone)/i + ], [MODEL, [VENDOR, 'Asus'], [TYPE, TABLET]], [ + + /(sony)\s(tablet\s[ps])\sbuild\//i, // Sony + /(sony)?(?:sgp.+)\sbuild\//i + ], [[VENDOR, 'Sony'], [MODEL, 'Xperia Tablet'], [TYPE, TABLET]], [ + /android.+\s([c-g]\d{4}|so[-l]\w+)\sbuild\//i + ], [MODEL, [VENDOR, 'Sony'], [TYPE, MOBILE]], [ + + /\s(ouya)\s/i, // Ouya + /(nintendo)\s([wids3u]+)/i // Nintendo + ], [VENDOR, MODEL, [TYPE, CONSOLE]], [ + + /android.+;\s(shield)\sbuild/i // Nvidia + ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, CONSOLE]], [ + + /(playstation\s[34portablevi]+)/i // Playstation + ], [MODEL, [VENDOR, 'Sony'], [TYPE, CONSOLE]], [ + + /(sprint\s(\w+))/i // Sprint Phones + ], [[VENDOR, mapper.str, maps.device.sprint.vendor], [MODEL, mapper.str, maps.device.sprint.model], [TYPE, MOBILE]], [ + + /(lenovo)\s?(S(?:5000|6000)+(?:[-][\w+]))/i // Lenovo tablets + ], [VENDOR, MODEL, [TYPE, TABLET]], [ + + /(htc)[;_\s-]+([\w\s]+(?=\))|\w+)*/i, // HTC + /(zte)-(\w+)*/i, // ZTE + /(alcatel|geeksphone|lenovo|nexian|panasonic|(?=;\s)sony)[_\s-]?([\w-]+)*/i + // Alcatel/GeeksPhone/Lenovo/Nexian/Panasonic/Sony + ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [ + + /(nexus\s9)/i // HTC Nexus 9 + ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [ + + /d\/huawei([\w\s-]+)[;\)]/i, + /(nexus\s6p)/i // Huawei + ], [MODEL, [VENDOR, 'Huawei'], [TYPE, MOBILE]], [ + + /(microsoft);\s(lumia[\s\w]+)/i // Microsoft Lumia + ], [VENDOR, MODEL, [TYPE, MOBILE]], [ + + /[\s\(;](xbox(?:\sone)?)[\s\);]/i // Microsoft Xbox + ], [MODEL, [VENDOR, 'Microsoft'], [TYPE, CONSOLE]], [ + /(kin\.[onetw]{3})/i // Microsoft Kin + ], [[MODEL, /\./g, ' '], [VENDOR, 'Microsoft'], [TYPE, MOBILE]], [ + + // Motorola + /\s(milestone|droid(?:[2-4x]|\s(?:bionic|x2|pro|razr))?(:?\s4g)?)[\w\s]+build\//i, + /mot[\s-]?(\w+)*/i, + /(XT\d{3,4}) build\//i, + /(nexus\s6)/i + ], [MODEL, [VENDOR, 'Motorola'], [TYPE, MOBILE]], [ + /android.+\s(mz60\d|xoom[\s2]{0,2})\sbuild\//i + ], [MODEL, [VENDOR, 'Motorola'], [TYPE, TABLET]], [ + + /hbbtv\/\d+\.\d+\.\d+\s+\([\w\s]*;\s*(\w[^;]*);([^;]*)/i // HbbTV devices + ], [[VENDOR, util.trim], [MODEL, util.trim], [TYPE, SMARTTV]], [ + + /hbbtv.+maple;(\d+)/i + ], [[MODEL, /^/, 'SmartTV'], [VENDOR, 'Samsung'], [TYPE, SMARTTV]], [ + + /\(dtv[\);].+(aquos)/i // Sharp + ], [MODEL, [VENDOR, 'Sharp'], [TYPE, SMARTTV]], [ + + /android.+((sch-i[89]0\d|shw-m380s|gt-p\d{4}|gt-n\d+|sgh-t8[56]9|nexus 10))/i, + /((SM-T\w+))/i + ], [[VENDOR, 'Samsung'], MODEL, [TYPE, TABLET]], [ // Samsung + /smart-tv.+(samsung)/i + ], [VENDOR, [TYPE, SMARTTV], MODEL], [ + /((s[cgp]h-\w+|gt-\w+|galaxy\snexus|sm-\w[\w\d]+))/i, + /(sam[sung]*)[\s-]*(\w+-?[\w-]*)*/i, + /sec-((sgh\w+))/i + ], [[VENDOR, 'Samsung'], MODEL, [TYPE, MOBILE]], [ + + /sie-(\w+)*/i // Siemens + ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [ + + /(maemo|nokia).*(n900|lumia\s\d+)/i, // Nokia + /(nokia)[\s_-]?([\w-]+)*/i + ], [[VENDOR, 'Nokia'], MODEL, [TYPE, MOBILE]], [ + + /android\s3\.[\s\w;-]{10}(a\d{3})/i // Acer + ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [ + + /android.+([vl]k\-?\d{3})\s+build/i // LG Tablet + ], [MODEL, [VENDOR, 'LG'], [TYPE, TABLET]], [ + /android\s3\.[\s\w;-]{10}(lg?)-([06cv9]{3,4})/i // LG Tablet + ], [[VENDOR, 'LG'], MODEL, [TYPE, TABLET]], [ + /(lg) netcast\.tv/i // LG SmartTV + ], [VENDOR, MODEL, [TYPE, SMARTTV]], [ + /(nexus\s[45])/i, // LG + /lg[e;\s\/-]+(\w+)*/i, + /android.+lg(\-?[\d\w]+)\s+build/i + ], [MODEL, [VENDOR, 'LG'], [TYPE, MOBILE]], [ + + /android.+(ideatab[a-z0-9\-\s]+)/i // Lenovo + ], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [ + + /linux;.+((jolla));/i // Jolla + ], [VENDOR, MODEL, [TYPE, MOBILE]], [ + + /((pebble))app\/[\d\.]+\s/i // Pebble + ], [VENDOR, MODEL, [TYPE, WEARABLE]], [ + + /android.+;\s(oppo)\s?([\w\s]+)\sbuild/i // OPPO + ], [VENDOR, MODEL, [TYPE, MOBILE]], [ + + /crkey/i // Google Chromecast + ], [[MODEL, 'Chromecast'], [VENDOR, 'Google']], [ + + /android.+;\s(glass)\s\d/i // Google Glass + ], [MODEL, [VENDOR, 'Google'], [TYPE, WEARABLE]], [ + + /android.+;\s(pixel c)\s/i // Google Pixel C + ], [MODEL, [VENDOR, 'Google'], [TYPE, TABLET]], [ + + /android.+;\s(pixel xl|pixel)\s/i // Google Pixel + ], [MODEL, [VENDOR, 'Google'], [TYPE, MOBILE]], [ + + /android.+(\w+)\s+build\/hm\1/i, // Xiaomi Hongmi 'numeric' models + /android.+(hm[\s\-_]*note?[\s_]*(?:\d\w)?)\s+build/i, // Xiaomi Hongmi + /android.+(mi[\s\-_]*(?:one|one[\s_]plus|note lte)?[\s_]*(?:\d\w)?)\s+build/i, // Xiaomi Mi + /android.+(redmi[\s\-_]*(?:note)?(?:[\s_]*[\w\s]+)?)\s+build/i // Redmi Phones + ], [[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, MOBILE]], [ + /android.+(mi[\s\-_]*(?:pad)?(?:[\s_]*[\w\s]+)?)\s+build/i // Mi Pad tablets + ],[[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, TABLET]], [ + /android.+;\s(m[1-5]\snote)\sbuild/i // Meizu Tablet + ], [MODEL, [VENDOR, 'Meizu'], [TYPE, TABLET]], [ + + /android.+a000(1)\s+build/i // OnePlus + ], [MODEL, [VENDOR, 'OnePlus'], [TYPE, MOBILE]], [ + + /android.+[;\/]\s*(RCT[\d\w]+)\s+build/i // RCA Tablets + ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [ + + /android.+[;\/]\s*(Venue[\d\s]*)\s+build/i // Dell Venue Tablets + ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [ + + /android.+[;\/]\s*(Q[T|M][\d\w]+)\s+build/i // Verizon Tablet + ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [ + + /android.+[;\/]\s+(Barnes[&\s]+Noble\s+|BN[RT])(V?.*)\s+build/i // Barnes & Noble Tablet + ], [[VENDOR, 'Barnes & Noble'], MODEL, [TYPE, TABLET]], [ + + /android.+[;\/]\s+(TM\d{3}.*\b)\s+build/i // Barnes & Noble Tablet + ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [ + + /android.+[;\/]\s*(zte)?.+(k\d{2})\s+build/i // ZTE K Series Tablet + ], [[VENDOR, 'ZTE'], MODEL, [TYPE, TABLET]], [ + + /android.+[;\/]\s*(gen\d{3})\s+build.*49h/i // Swiss GEN Mobile + ], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [ + + /android.+[;\/]\s*(zur\d{3})\s+build/i // Swiss ZUR Tablet + ], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [ + + /android.+[;\/]\s*((Zeki)?TB.*\b)\s+build/i // Zeki Tablets + ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [ + + /(android).+[;\/]\s+([YR]\d{2}x?.*)\s+build/i, + /android.+[;\/]\s+(Dragon[\-\s]+Touch\s+|DT)(.+)\s+build/i // Dragon Touch Tablet + ], [[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]], [ + + /android.+[;\/]\s*(NS-?.+)\s+build/i // Insignia Tablets + ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [ + + /android.+[;\/]\s*((NX|Next)-?.+)\s+build/i // NextBook Tablets + ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [ + + /android.+[;\/]\s*(Xtreme\_?)?(V(1[045]|2[015]|30|40|60|7[05]|90))\s+build/i + ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [ // Voice Xtreme Phones + + /android.+[;\/]\s*(LVTEL\-?)?(V1[12])\s+build/i // LvTel Phones + ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [ + + /android.+[;\/]\s*(V(100MD|700NA|7011|917G).*\b)\s+build/i // Envizen Tablets + ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [ + + /android.+[;\/]\s*(Le[\s\-]+Pan)[\s\-]+(.*\b)\s+build/i // Le Pan Tablets + ], [VENDOR, MODEL, [TYPE, TABLET]], [ + + /android.+[;\/]\s*(Trio[\s\-]*.*)\s+build/i // MachSpeed Tablets + ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [ + + /android.+[;\/]\s*(Trinity)[\-\s]*(T\d{3})\s+build/i // Trinity Tablets + ], [VENDOR, MODEL, [TYPE, TABLET]], [ + + /android.+[;\/]\s*TU_(1491)\s+build/i // Rotor Tablets + ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [ + + /android.+(KS(.+))\s+build/i // Amazon Kindle Tablets + ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [ + + /android.+(Gigaset)[\s\-]+(Q.+)\s+build/i // Gigaset Tablets + ], [VENDOR, MODEL, [TYPE, TABLET]], [ + + /\s(tablet|tab)[;\/]/i, // Unidentifiable Tablet + /\s(mobile)(?:[;\/]|\ssafari)/i // Unidentifiable Mobile + ], [[TYPE, util.lowerize], VENDOR, MODEL], [ + + /(android.+)[;\/].+build/i // Generic Android Device + ], [MODEL, [VENDOR, 'Generic']] + + + /*////////////////////////// + // TODO: move to string map + //////////////////////////// + + /(C6603)/i // Sony Xperia Z C6603 + ], [[MODEL, 'Xperia Z C6603'], [VENDOR, 'Sony'], [TYPE, MOBILE]], [ + /(C6903)/i // Sony Xperia Z 1 + ], [[MODEL, 'Xperia Z 1'], [VENDOR, 'Sony'], [TYPE, MOBILE]], [ + + /(SM-G900[F|H])/i // Samsung Galaxy S5 + ], [[MODEL, 'Galaxy S5'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ + /(SM-G7102)/i // Samsung Galaxy Grand 2 + ], [[MODEL, 'Galaxy Grand 2'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ + /(SM-G530H)/i // Samsung Galaxy Grand Prime + ], [[MODEL, 'Galaxy Grand Prime'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ + /(SM-G313HZ)/i // Samsung Galaxy V + ], [[MODEL, 'Galaxy V'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ + /(SM-T805)/i // Samsung Galaxy Tab S 10.5 + ], [[MODEL, 'Galaxy Tab S 10.5'], [VENDOR, 'Samsung'], [TYPE, TABLET]], [ + /(SM-G800F)/i // Samsung Galaxy S5 Mini + ], [[MODEL, 'Galaxy S5 Mini'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ + /(SM-T311)/i // Samsung Galaxy Tab 3 8.0 + ], [[MODEL, 'Galaxy Tab 3 8.0'], [VENDOR, 'Samsung'], [TYPE, TABLET]], [ + + /(T3C)/i // Advan Vandroid T3C + ], [MODEL, [VENDOR, 'Advan'], [TYPE, TABLET]], [ + /(ADVAN T1J\+)/i // Advan Vandroid T1J+ + ], [[MODEL, 'Vandroid T1J+'], [VENDOR, 'Advan'], [TYPE, TABLET]], [ + /(ADVAN S4A)/i // Advan Vandroid S4A + ], [[MODEL, 'Vandroid S4A'], [VENDOR, 'Advan'], [TYPE, MOBILE]], [ + + /(V972M)/i // ZTE V972M + ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [ + + /(i-mobile)\s(IQ\s[\d\.]+)/i // i-mobile IQ + ], [VENDOR, MODEL, [TYPE, MOBILE]], [ + /(IQ6.3)/i // i-mobile IQ IQ 6.3 + ], [[MODEL, 'IQ 6.3'], [VENDOR, 'i-mobile'], [TYPE, MOBILE]], [ + /(i-mobile)\s(i-style\s[\d\.]+)/i // i-mobile i-STYLE + ], [VENDOR, MODEL, [TYPE, MOBILE]], [ + /(i-STYLE2.1)/i // i-mobile i-STYLE 2.1 + ], [[MODEL, 'i-STYLE 2.1'], [VENDOR, 'i-mobile'], [TYPE, MOBILE]], [ + + /(mobiistar touch LAI 512)/i // mobiistar touch LAI 512 + ], [[MODEL, 'Touch LAI 512'], [VENDOR, 'mobiistar'], [TYPE, MOBILE]], [ + + ///////////// + // END TODO + ///////////*/ + + ], + + engine : [[ + + /windows.+\sedge\/([\w\.]+)/i // EdgeHTML + ], [VERSION, [NAME, 'EdgeHTML']], [ + + /(presto)\/([\w\.]+)/i, // Presto + /(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m + /(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i, // KHTML/Tasman/Links + /(icab)[\/\s]([23]\.[\d\.]+)/i // iCab + ], [NAME, VERSION], [ + + /rv\:([\w\.]+).*(gecko)/i // Gecko + ], [VERSION, NAME] + ], + + os : [[ + + // Windows based + /microsoft\s(windows)\s(vista|xp)/i // Windows (iTunes) + ], [NAME, VERSION], [ + /(windows)\snt\s6\.2;\s(arm)/i, // Windows RT + /(windows\sphone(?:\sos)*)[\s\/]?([\d\.\s]+\w)*/i, // Windows Phone + /(windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i + ], [NAME, [VERSION, mapper.str, maps.os.windows.version]], [ + /(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i + ], [[NAME, 'Windows'], [VERSION, mapper.str, maps.os.windows.version]], [ + + // Mobile/Embedded OS + /\((bb)(10);/i // BlackBerry 10 + ], [[NAME, 'BlackBerry'], VERSION], [ + /(blackberry)\w*\/?([\w\.]+)*/i, // Blackberry + /(tizen)[\/\s]([\w\.]+)/i, // Tizen + /(android|webos|palm\sos|qnx|bada|rim\stablet\sos|meego|contiki)[\/\s-]?([\w\.]+)*/i, + // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo/Contiki + /linux;.+(sailfish);/i // Sailfish OS + ], [NAME, VERSION], [ + /(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i // Symbian + ], [[NAME, 'Symbian'], VERSION], [ + /\((series40);/i // Series 40 + ], [NAME], [ + /mozilla.+\(mobile;.+gecko.+firefox/i // Firefox OS + ], [[NAME, 'Firefox OS'], VERSION], [ + + // Console + /(nintendo|playstation)\s([wids34portablevu]+)/i, // Nintendo/Playstation + + // GNU/Linux based + /(mint)[\/\s\(]?(\w+)*/i, // Mint + /(mageia|vectorlinux)[;\s]/i, // Mageia/VectorLinux + /(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|(?=\s)arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus)[\/\s-]?(?!chrom)([\w\.-]+)*/i, + // Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware + // Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus + /(hurd|linux)\s?([\w\.]+)*/i, // Hurd/Linux + /(gnu)\s?([\w\.]+)*/i // GNU + ], [NAME, VERSION], [ + + /(cros)\s[\w]+\s([\w\.]+\w)/i // Chromium OS + ], [[NAME, 'Chromium OS'], VERSION],[ + + // Solaris + /(sunos)\s?([\w\.]+\d)*/i // Solaris + ], [[NAME, 'Solaris'], VERSION], [ + + // BSD based + /\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly + ], [NAME, VERSION],[ + + /(haiku)\s(\w+)/i // Haiku + ], [NAME, VERSION],[ + + /cfnetwork\/.+darwin/i, + /ip[honead]+(?:.*os\s([\w]+)\slike\smac|;\sopera)/i // iOS + ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [ + + /(mac\sos\sx)\s?([\w\s\.]+\w)*/i, + /(macintosh|mac(?=_powerpc)\s)/i // Mac OS + ], [[NAME, 'Mac OS'], [VERSION, /_/g, '.']], [ + + // Other + /((?:open)?solaris)[\/\s-]?([\w\.]+)*/i, // Solaris + /(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i, // AIX + /(plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos|openvms)/i, + // Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS/OpenVMS + /(unix)\s?([\w\.]+)*/i // UNIX + ], [NAME, VERSION] + ] + }; + + + ///////////////// + // Constructor + //////////////// + /* + var Browser = function (name, version) { + this[NAME] = name; + this[VERSION] = version; + }; + var CPU = function (arch) { + this[ARCHITECTURE] = arch; + }; + var Device = function (vendor, model, type) { + this[VENDOR] = vendor; + this[MODEL] = model; + this[TYPE] = type; + }; + var Engine = Browser; + var OS = Browser; + */ + var UAParser = function (uastring, extensions) { + + if (typeof uastring === 'object') { + extensions = uastring; + uastring = undefined; + } + + if (!(this instanceof UAParser)) { + return new UAParser(uastring, extensions).getResult(); + } + + var ua = uastring || ((window && window.navigator && window.navigator.userAgent) ? window.navigator.userAgent : EMPTY); + var rgxmap = extensions ? util.extend(regexes, extensions) : regexes; + //var browser = new Browser(); + //var cpu = new CPU(); + //var device = new Device(); + //var engine = new Engine(); + //var os = new OS(); + + this.getBrowser = function () { + var browser = { name: undefined, version: undefined }; + mapper.rgx.call(browser, ua, rgxmap.browser); + browser.major = util.major(browser.version); // deprecated + return browser; + }; + this.getCPU = function () { + var cpu = { architecture: undefined }; + mapper.rgx.call(cpu, ua, rgxmap.cpu); + return cpu; + }; + this.getDevice = function () { + var device = { vendor: undefined, model: undefined, type: undefined }; + mapper.rgx.call(device, ua, rgxmap.device); + return device; + }; + this.getEngine = function () { + var engine = { name: undefined, version: undefined }; + mapper.rgx.call(engine, ua, rgxmap.engine); + return engine; + }; + this.getOS = function () { + var os = { name: undefined, version: undefined }; + mapper.rgx.call(os, ua, rgxmap.os); + return os; + }; + this.getResult = function () { + return { + ua : this.getUA(), + browser : this.getBrowser(), + engine : this.getEngine(), + os : this.getOS(), + device : this.getDevice(), + cpu : this.getCPU() + }; + }; + this.getUA = function () { + return ua; + }; + this.setUA = function (uastring) { + ua = uastring; + //browser = new Browser(); + //cpu = new CPU(); + //device = new Device(); + //engine = new Engine(); + //os = new OS(); + return this; + }; + return this; + }; + + UAParser.VERSION = LIBVERSION; + UAParser.BROWSER = { + NAME : NAME, + MAJOR : MAJOR, // deprecated + VERSION : VERSION + }; + UAParser.CPU = { + ARCHITECTURE : ARCHITECTURE + }; + UAParser.DEVICE = { + MODEL : MODEL, + VENDOR : VENDOR, + TYPE : TYPE, + CONSOLE : CONSOLE, + MOBILE : MOBILE, + SMARTTV : SMARTTV, + TABLET : TABLET, + WEARABLE: WEARABLE, + EMBEDDED: EMBEDDED + }; + UAParser.ENGINE = { + NAME : NAME, + VERSION : VERSION + }; + UAParser.OS = { + NAME : NAME, + VERSION : VERSION + }; + //UAParser.Utils = util; + + /////////// + // Export + ////////// + + + // check js environment + if (typeof(exports) !== UNDEF_TYPE) { + // nodejs env + if (typeof module !== UNDEF_TYPE && module.exports) { + exports = module.exports = UAParser; + } + // TODO: test!!!!!!!! + /* + if (require && require.main === module && process) { + // cli + var jsonize = function (arr) { + var res = []; + for (var i in arr) { + res.push(new UAParser(arr[i]).getResult()); + } + process.stdout.write(JSON.stringify(res, null, 2) + '\n'); + }; + if (process.stdin.isTTY) { + // via args + jsonize(process.argv.slice(2)); + } else { + // via pipe + var str = ''; + process.stdin.on('readable', function() { + var read = process.stdin.read(); + if (read !== null) { + str += read; + } + }); + process.stdin.on('end', function () { + jsonize(str.replace(/\n$/, '').split('\n')); + }); + } + } + */ + exports.UAParser = UAParser; + } else { + // requirejs env (optional) + if (typeof(define) === FUNC_TYPE && define.amd) { + define(function () { + return UAParser; + }); + } else if (window) { + // browser env + window.UAParser = UAParser; + } + } + + // jQuery/Zepto specific (optional) + // Note: + // In AMD env the global scope should be kept clean, but jQuery is an exception. + // jQuery always exports to global scope, unless jQuery.noConflict(true) is used, + // and we should catch that. + var $ = window && (window.jQuery || window.Zepto); + if (typeof $ !== UNDEF_TYPE) { + var parser = new UAParser(); + $.ua = parser.getResult(); + $.ua.get = function () { + return parser.getUA(); + }; + $.ua.set = function (uastring) { + parser.setUA(uastring); + var result = parser.getResult(); + for (var prop in result) { + $.ua[prop] = result[prop]; + } + }; + } + +})(typeof window === 'object' ? window : this); + +},{}],21:[function(require,module,exports){ +var v1 = require('./v1'); +var v4 = require('./v4'); + +var uuid = v4; +uuid.v1 = v1; +uuid.v4 = v4; + +module.exports = uuid; + +},{"./v1":24,"./v4":25}],22:[function(require,module,exports){ +/** + * Convert array of 16 byte values to UUID string format of the form: + * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + */ +var byteToHex = []; +for (var i = 0; i < 256; ++i) { + byteToHex[i] = (i + 0x100).toString(16).substr(1); +} + +function bytesToUuid(buf, offset) { + var i = offset || 0; + var bth = byteToHex; + return bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]]; +} + +module.exports = bytesToUuid; + +},{}],23:[function(require,module,exports){ +(function (global){ +// Unique ID creation requires a high quality random # generator. In the +// browser this is a little complicated due to unknown quality of Math.random() +// and inconsistent support for the `crypto` API. We do the best we can via +// feature-detection +var rng; + +var crypto = global.crypto || global.msCrypto; // for IE 11 +if (crypto && crypto.getRandomValues) { + // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto + var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef + rng = function whatwgRNG() { + crypto.getRandomValues(rnds8); + return rnds8; + }; +} + +if (!rng) { + // Math.random()-based (RNG) + // + // If all else fails, use Math.random(). It's fast, but is of unspecified + // quality. + var rnds = new Array(16); + rng = function() { + for (var i = 0, r; i < 16; i++) { + if ((i & 0x03) === 0) r = Math.random() * 0x100000000; + rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; + } + + return rnds; + }; +} + +module.exports = rng; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],24:[function(require,module,exports){ +var rng = require('./lib/rng'); +var bytesToUuid = require('./lib/bytesToUuid'); + +// **`v1()` - Generate time-based UUID** +// +// Inspired by https://github.com/LiosK/UUID.js +// and http://docs.python.org/library/uuid.html + +// random #'s we need to init node and clockseq +var _seedBytes = rng(); + +// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) +var _nodeId = [ + _seedBytes[0] | 0x01, + _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5] +]; + +// Per 4.2.2, randomize (14 bit) clockseq +var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff; + +// Previous uuid creation time +var _lastMSecs = 0, _lastNSecs = 0; + +// See https://github.com/broofa/node-uuid for API details +function v1(options, buf, offset) { + var i = buf && offset || 0; + var b = buf || []; + + options = options || {}; + + var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; + + // 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. + var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime(); + + // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; + + // Time since last uuid creation (in msecs) + var 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` + var 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` + var 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` + var node = options.node || _nodeId; + for (var n = 0; n < 6; ++n) { + b[i + n] = node[n]; + } + + return buf ? buf : bytesToUuid(b); +} + +module.exports = v1; + +},{"./lib/bytesToUuid":22,"./lib/rng":23}],25:[function(require,module,exports){ +var rng = require('./lib/rng'); +var bytesToUuid = require('./lib/bytesToUuid'); + +function v4(options, buf, offset) { + var i = buf && offset || 0; + + if (typeof(options) == 'string') { + buf = options == 'binary' ? new Array(16) : null; + options = null; + } + options = options || {}; + + var rnds = options.random || (options.rng || rng)(); + + // 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) { + for (var ii = 0; ii < 16; ++ii) { + buf[i + ii] = rnds[ii]; + } + } + + return buf || bytesToUuid(rnds); +} + +module.exports = v4; + +},{"./lib/bytesToUuid":22,"./lib/rng":23}],26:[function(require,module,exports){ +(function (global){ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ + +'use strict'; + +var adapterFactory = require('./adapter_factory.js'); +module.exports = adapterFactory({window: global.window}); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"./adapter_factory.js":27}],27:[function(require,module,exports){ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ + +'use strict'; + +var utils = require('./utils'); +// Shimming starts here. +module.exports = function(dependencies, opts) { + var window = dependencies && dependencies.window; + + var options = { + shimChrome: true, + shimFirefox: true, + shimEdge: true, + shimSafari: true, + }; + + for (var key in opts) { + if (hasOwnProperty.call(opts, key)) { + options[key] = opts[key]; + } + } + + // Utils. + var logging = utils.log; + var browserDetails = utils.detectBrowser(window); + + // Uncomment the line below if you want logging to occur, including logging + // for the switch statement below. Can also be turned on in the browser via + // adapter.disableLog(false), but then logging from the switch statement below + // will not appear. + // require('./utils').disableLog(false); + + // Browser shims. + var chromeShim = require('./chrome/chrome_shim') || null; + var edgeShim = require('./edge/edge_shim') || null; + var firefoxShim = require('./firefox/firefox_shim') || null; + var safariShim = require('./safari/safari_shim') || null; + var commonShim = require('./common_shim') || null; + + // Export to the adapter global object visible in the browser. + var adapter = { + browserDetails: browserDetails, + commonShim: commonShim, + extractVersion: utils.extractVersion, + disableLog: utils.disableLog, + disableWarnings: utils.disableWarnings + }; + + // Shim browser if found. + switch (browserDetails.browser) { + case 'chrome': + if (!chromeShim || !chromeShim.shimPeerConnection || + !options.shimChrome) { + logging('Chrome shim is not included in this adapter release.'); + return adapter; + } + logging('adapter.js shimming chrome.'); + // Export to the adapter global object visible in the browser. + adapter.browserShim = chromeShim; + commonShim.shimCreateObjectURL(window); + + chromeShim.shimGetUserMedia(window); + chromeShim.shimMediaStream(window); + chromeShim.shimSourceObject(window); + chromeShim.shimPeerConnection(window); + chromeShim.shimOnTrack(window); + chromeShim.shimAddTrackRemoveTrack(window); + chromeShim.shimGetSendersWithDtmf(window); + + commonShim.shimRTCIceCandidate(window); + commonShim.shimMaxMessageSize(window); + commonShim.shimSendThrowTypeError(window); + break; + case 'firefox': + if (!firefoxShim || !firefoxShim.shimPeerConnection || + !options.shimFirefox) { + logging('Firefox shim is not included in this adapter release.'); + return adapter; + } + logging('adapter.js shimming firefox.'); + // Export to the adapter global object visible in the browser. + adapter.browserShim = firefoxShim; + commonShim.shimCreateObjectURL(window); + + firefoxShim.shimGetUserMedia(window); + firefoxShim.shimSourceObject(window); + firefoxShim.shimPeerConnection(window); + firefoxShim.shimOnTrack(window); + firefoxShim.shimRemoveStream(window); + + commonShim.shimRTCIceCandidate(window); + commonShim.shimMaxMessageSize(window); + commonShim.shimSendThrowTypeError(window); + break; + case 'edge': + if (!edgeShim || !edgeShim.shimPeerConnection || !options.shimEdge) { + logging('MS edge shim is not included in this adapter release.'); + return adapter; + } + logging('adapter.js shimming edge.'); + // Export to the adapter global object visible in the browser. + adapter.browserShim = edgeShim; + commonShim.shimCreateObjectURL(window); + + edgeShim.shimGetUserMedia(window); + edgeShim.shimPeerConnection(window); + edgeShim.shimReplaceTrack(window); + + // the edge shim implements the full RTCIceCandidate object. + + commonShim.shimMaxMessageSize(window); + commonShim.shimSendThrowTypeError(window); + break; + case 'safari': + if (!safariShim || !options.shimSafari) { + logging('Safari shim is not included in this adapter release.'); + return adapter; + } + logging('adapter.js shimming safari.'); + // Export to the adapter global object visible in the browser. + adapter.browserShim = safariShim; + commonShim.shimCreateObjectURL(window); + + safariShim.shimRTCIceServerUrls(window); + safariShim.shimCallbacksAPI(window); + safariShim.shimLocalStreamsAPI(window); + safariShim.shimRemoteStreamsAPI(window); + safariShim.shimTrackEventTransceiver(window); + safariShim.shimGetUserMedia(window); + safariShim.shimCreateOfferLegacy(window); + + commonShim.shimRTCIceCandidate(window); + commonShim.shimMaxMessageSize(window); + commonShim.shimSendThrowTypeError(window); + break; + default: + logging('Unsupported browser!'); + break; + } + + return adapter; +}; + +},{"./chrome/chrome_shim":28,"./common_shim":30,"./edge/edge_shim":31,"./firefox/firefox_shim":33,"./safari/safari_shim":35,"./utils":36}],28:[function(require,module,exports){ + +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ +'use strict'; +var utils = require('../utils.js'); +var logging = utils.log; + +module.exports = { + shimGetUserMedia: require('./getusermedia'), + shimMediaStream: function(window) { + window.MediaStream = window.MediaStream || window.webkitMediaStream; + }, + + shimOnTrack: function(window) { + if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in + window.RTCPeerConnection.prototype)) { + Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', { + get: function() { + return this._ontrack; + }, + set: function(f) { + if (this._ontrack) { + this.removeEventListener('track', this._ontrack); + } + this.addEventListener('track', this._ontrack = f); + } + }); + var origSetRemoteDescription = + window.RTCPeerConnection.prototype.setRemoteDescription; + window.RTCPeerConnection.prototype.setRemoteDescription = function() { + var pc = this; + if (!pc._ontrackpoly) { + pc._ontrackpoly = function(e) { + // onaddstream does not fire when a track is added to an existing + // stream. But stream.onaddtrack is implemented so we use that. + e.stream.addEventListener('addtrack', function(te) { + var receiver; + if (window.RTCPeerConnection.prototype.getReceivers) { + receiver = pc.getReceivers().find(function(r) { + return r.track && r.track.id === te.track.id; + }); + } else { + receiver = {track: te.track}; + } + + var event = new Event('track'); + event.track = te.track; + event.receiver = receiver; + event.transceiver = {receiver: receiver}; + event.streams = [e.stream]; + pc.dispatchEvent(event); + }); + e.stream.getTracks().forEach(function(track) { + var receiver; + if (window.RTCPeerConnection.prototype.getReceivers) { + receiver = pc.getReceivers().find(function(r) { + return r.track && r.track.id === track.id; + }); + } else { + receiver = {track: track}; + } + var event = new Event('track'); + event.track = track; + event.receiver = receiver; + event.transceiver = {receiver: receiver}; + event.streams = [e.stream]; + pc.dispatchEvent(event); + }); + }; + pc.addEventListener('addstream', pc._ontrackpoly); + } + return origSetRemoteDescription.apply(pc, arguments); + }; + } else if (!('RTCRtpTransceiver' in window)) { + utils.wrapPeerConnectionEvent(window, 'track', function(e) { + if (!e.transceiver) { + e.transceiver = {receiver: e.receiver}; + } + return e; + }); + } + }, + + shimGetSendersWithDtmf: function(window) { + // Overrides addTrack/removeTrack, depends on shimAddTrackRemoveTrack. + if (typeof window === 'object' && window.RTCPeerConnection && + !('getSenders' in window.RTCPeerConnection.prototype) && + 'createDTMFSender' in window.RTCPeerConnection.prototype) { + var shimSenderWithDtmf = function(pc, track) { + return { + track: track, + get dtmf() { + if (this._dtmf === undefined) { + if (track.kind === 'audio') { + this._dtmf = pc.createDTMFSender(track); + } else { + this._dtmf = null; + } + } + return this._dtmf; + }, + _pc: pc + }; + }; + + // augment addTrack when getSenders is not available. + if (!window.RTCPeerConnection.prototype.getSenders) { + window.RTCPeerConnection.prototype.getSenders = function() { + this._senders = this._senders || []; + return this._senders.slice(); // return a copy of the internal state. + }; + var origAddTrack = window.RTCPeerConnection.prototype.addTrack; + window.RTCPeerConnection.prototype.addTrack = function(track, stream) { + var pc = this; + var sender = origAddTrack.apply(pc, arguments); + if (!sender) { + sender = shimSenderWithDtmf(pc, track); + pc._senders.push(sender); + } + return sender; + }; + + var origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack; + window.RTCPeerConnection.prototype.removeTrack = function(sender) { + var pc = this; + origRemoveTrack.apply(pc, arguments); + var idx = pc._senders.indexOf(sender); + if (idx !== -1) { + pc._senders.splice(idx, 1); + } + }; + } + var origAddStream = window.RTCPeerConnection.prototype.addStream; + window.RTCPeerConnection.prototype.addStream = function(stream) { + var pc = this; + pc._senders = pc._senders || []; + origAddStream.apply(pc, [stream]); + stream.getTracks().forEach(function(track) { + pc._senders.push(shimSenderWithDtmf(pc, track)); + }); + }; + + var origRemoveStream = window.RTCPeerConnection.prototype.removeStream; + window.RTCPeerConnection.prototype.removeStream = function(stream) { + var pc = this; + pc._senders = pc._senders || []; + origRemoveStream.apply(pc, [stream]); + + stream.getTracks().forEach(function(track) { + var sender = pc._senders.find(function(s) { + return s.track === track; + }); + if (sender) { + pc._senders.splice(pc._senders.indexOf(sender), 1); // remove sender + } + }); + }; + } else if (typeof window === 'object' && window.RTCPeerConnection && + 'getSenders' in window.RTCPeerConnection.prototype && + 'createDTMFSender' in window.RTCPeerConnection.prototype && + window.RTCRtpSender && + !('dtmf' in window.RTCRtpSender.prototype)) { + var origGetSenders = window.RTCPeerConnection.prototype.getSenders; + window.RTCPeerConnection.prototype.getSenders = function() { + var pc = this; + var senders = origGetSenders.apply(pc, []); + senders.forEach(function(sender) { + sender._pc = pc; + }); + return senders; + }; + + Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', { + get: function() { + if (this._dtmf === undefined) { + if (this.track.kind === 'audio') { + this._dtmf = this._pc.createDTMFSender(this.track); + } else { + this._dtmf = null; + } + } + return this._dtmf; + } + }); + } + }, + + shimSourceObject: function(window) { + var URL = window && window.URL; + + if (typeof window === 'object') { + if (window.HTMLMediaElement && + !('srcObject' in window.HTMLMediaElement.prototype)) { + // Shim the srcObject property, once, when HTMLMediaElement is found. + Object.defineProperty(window.HTMLMediaElement.prototype, 'srcObject', { + get: function() { + return this._srcObject; + }, + set: function(stream) { + var self = this; + // Use _srcObject as a private property for this shim + this._srcObject = stream; + if (this.src) { + URL.revokeObjectURL(this.src); + } + + if (!stream) { + this.src = ''; + return undefined; + } + this.src = URL.createObjectURL(stream); + // We need to recreate the blob url when a track is added or + // removed. Doing it manually since we want to avoid a recursion. + stream.addEventListener('addtrack', function() { + if (self.src) { + URL.revokeObjectURL(self.src); + } + self.src = URL.createObjectURL(stream); + }); + stream.addEventListener('removetrack', function() { + if (self.src) { + URL.revokeObjectURL(self.src); + } + self.src = URL.createObjectURL(stream); + }); + } + }); + } + } + }, + + shimAddTrackRemoveTrackWithNative: function(window) { + // shim addTrack/removeTrack with native variants in order to make + // the interactions with legacy getLocalStreams behave as in other browsers. + // Keeps a mapping stream.id => [stream, rtpsenders...] + window.RTCPeerConnection.prototype.getLocalStreams = function() { + var pc = this; + this._shimmedLocalStreams = this._shimmedLocalStreams || {}; + return Object.keys(this._shimmedLocalStreams).map(function(streamId) { + return pc._shimmedLocalStreams[streamId][0]; + }); + }; + + var origAddTrack = window.RTCPeerConnection.prototype.addTrack; + window.RTCPeerConnection.prototype.addTrack = function(track, stream) { + if (!stream) { + return origAddTrack.apply(this, arguments); + } + this._shimmedLocalStreams = this._shimmedLocalStreams || {}; + + var sender = origAddTrack.apply(this, arguments); + if (!this._shimmedLocalStreams[stream.id]) { + this._shimmedLocalStreams[stream.id] = [stream, sender]; + } else if (this._shimmedLocalStreams[stream.id].indexOf(sender) === -1) { + this._shimmedLocalStreams[stream.id].push(sender); + } + return sender; + }; + + var origAddStream = window.RTCPeerConnection.prototype.addStream; + window.RTCPeerConnection.prototype.addStream = function(stream) { + var pc = this; + this._shimmedLocalStreams = this._shimmedLocalStreams || {}; + + stream.getTracks().forEach(function(track) { + var alreadyExists = pc.getSenders().find(function(s) { + return s.track === track; + }); + if (alreadyExists) { + throw new DOMException('Track already exists.', + 'InvalidAccessError'); + } + }); + var existingSenders = pc.getSenders(); + origAddStream.apply(this, arguments); + var newSenders = pc.getSenders().filter(function(newSender) { + return existingSenders.indexOf(newSender) === -1; + }); + this._shimmedLocalStreams[stream.id] = [stream].concat(newSenders); + }; + + var origRemoveStream = window.RTCPeerConnection.prototype.removeStream; + window.RTCPeerConnection.prototype.removeStream = function(stream) { + this._shimmedLocalStreams = this._shimmedLocalStreams || {}; + delete this._shimmedLocalStreams[stream.id]; + return origRemoveStream.apply(this, arguments); + }; + + var origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack; + window.RTCPeerConnection.prototype.removeTrack = function(sender) { + var pc = this; + this._shimmedLocalStreams = this._shimmedLocalStreams || {}; + if (sender) { + Object.keys(this._shimmedLocalStreams).forEach(function(streamId) { + var idx = pc._shimmedLocalStreams[streamId].indexOf(sender); + if (idx !== -1) { + pc._shimmedLocalStreams[streamId].splice(idx, 1); + } + if (pc._shimmedLocalStreams[streamId].length === 1) { + delete pc._shimmedLocalStreams[streamId]; + } + }); + } + return origRemoveTrack.apply(this, arguments); + }; + }, + + shimAddTrackRemoveTrack: function(window) { + var browserDetails = utils.detectBrowser(window); + // shim addTrack and removeTrack. + if (window.RTCPeerConnection.prototype.addTrack && + browserDetails.version >= 65) { + return this.shimAddTrackRemoveTrackWithNative(window); + } + + // also shim pc.getLocalStreams when addTrack is shimmed + // to return the original streams. + var origGetLocalStreams = window.RTCPeerConnection.prototype + .getLocalStreams; + window.RTCPeerConnection.prototype.getLocalStreams = function() { + var pc = this; + var nativeStreams = origGetLocalStreams.apply(this); + pc._reverseStreams = pc._reverseStreams || {}; + return nativeStreams.map(function(stream) { + return pc._reverseStreams[stream.id]; + }); + }; + + var origAddStream = window.RTCPeerConnection.prototype.addStream; + window.RTCPeerConnection.prototype.addStream = function(stream) { + var pc = this; + pc._streams = pc._streams || {}; + pc._reverseStreams = pc._reverseStreams || {}; + + stream.getTracks().forEach(function(track) { + var alreadyExists = pc.getSenders().find(function(s) { + return s.track === track; + }); + if (alreadyExists) { + throw new DOMException('Track already exists.', + 'InvalidAccessError'); + } + }); + // Add identity mapping for consistency with addTrack. + // Unless this is being used with a stream from addTrack. + if (!pc._reverseStreams[stream.id]) { + var newStream = new window.MediaStream(stream.getTracks()); + pc._streams[stream.id] = newStream; + pc._reverseStreams[newStream.id] = stream; + stream = newStream; + } + origAddStream.apply(pc, [stream]); + }; + + var origRemoveStream = window.RTCPeerConnection.prototype.removeStream; + window.RTCPeerConnection.prototype.removeStream = function(stream) { + var pc = this; + pc._streams = pc._streams || {}; + pc._reverseStreams = pc._reverseStreams || {}; + + origRemoveStream.apply(pc, [(pc._streams[stream.id] || stream)]); + delete pc._reverseStreams[(pc._streams[stream.id] ? + pc._streams[stream.id].id : stream.id)]; + delete pc._streams[stream.id]; + }; + + window.RTCPeerConnection.prototype.addTrack = function(track, stream) { + var pc = this; + if (pc.signalingState === 'closed') { + throw new DOMException( + 'The RTCPeerConnection\'s signalingState is \'closed\'.', + 'InvalidStateError'); + } + var streams = [].slice.call(arguments, 1); + if (streams.length !== 1 || + !streams[0].getTracks().find(function(t) { + return t === track; + })) { + // this is not fully correct but all we can manage without + // [[associated MediaStreams]] internal slot. + throw new DOMException( + 'The adapter.js addTrack polyfill only supports a single ' + + ' stream which is associated with the specified track.', + 'NotSupportedError'); + } + + var alreadyExists = pc.getSenders().find(function(s) { + return s.track === track; + }); + if (alreadyExists) { + throw new DOMException('Track already exists.', + 'InvalidAccessError'); + } + + pc._streams = pc._streams || {}; + pc._reverseStreams = pc._reverseStreams || {}; + var oldStream = pc._streams[stream.id]; + if (oldStream) { + // this is using odd Chrome behaviour, use with caution: + // https://bugs.chromium.org/p/webrtc/issues/detail?id=7815 + // Note: we rely on the high-level addTrack/dtmf shim to + // create the sender with a dtmf sender. + oldStream.addTrack(track); + + // Trigger ONN async. + Promise.resolve().then(function() { + pc.dispatchEvent(new Event('negotiationneeded')); + }); + } else { + var newStream = new window.MediaStream([track]); + pc._streams[stream.id] = newStream; + pc._reverseStreams[newStream.id] = stream; + pc.addStream(newStream); + } + return pc.getSenders().find(function(s) { + return s.track === track; + }); + }; + + // replace the internal stream id with the external one and + // vice versa. + function replaceInternalStreamId(pc, description) { + var sdp = description.sdp; + Object.keys(pc._reverseStreams || []).forEach(function(internalId) { + var externalStream = pc._reverseStreams[internalId]; + var internalStream = pc._streams[externalStream.id]; + sdp = sdp.replace(new RegExp(internalStream.id, 'g'), + externalStream.id); + }); + return new RTCSessionDescription({ + type: description.type, + sdp: sdp + }); + } + function replaceExternalStreamId(pc, description) { + var sdp = description.sdp; + Object.keys(pc._reverseStreams || []).forEach(function(internalId) { + var externalStream = pc._reverseStreams[internalId]; + var internalStream = pc._streams[externalStream.id]; + sdp = sdp.replace(new RegExp(externalStream.id, 'g'), + internalStream.id); + }); + return new RTCSessionDescription({ + type: description.type, + sdp: sdp + }); + } + ['createOffer', 'createAnswer'].forEach(function(method) { + var nativeMethod = window.RTCPeerConnection.prototype[method]; + window.RTCPeerConnection.prototype[method] = function() { + var pc = this; + var args = arguments; + var isLegacyCall = arguments.length && + typeof arguments[0] === 'function'; + if (isLegacyCall) { + return nativeMethod.apply(pc, [ + function(description) { + var desc = replaceInternalStreamId(pc, description); + args[0].apply(null, [desc]); + }, + function(err) { + if (args[1]) { + args[1].apply(null, err); + } + }, arguments[2] + ]); + } + return nativeMethod.apply(pc, arguments) + .then(function(description) { + return replaceInternalStreamId(pc, description); + }); + }; + }); + + var origSetLocalDescription = + window.RTCPeerConnection.prototype.setLocalDescription; + window.RTCPeerConnection.prototype.setLocalDescription = function() { + var pc = this; + if (!arguments.length || !arguments[0].type) { + return origSetLocalDescription.apply(pc, arguments); + } + arguments[0] = replaceExternalStreamId(pc, arguments[0]); + return origSetLocalDescription.apply(pc, arguments); + }; + + // TODO: mangle getStats: https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamstats-streamidentifier + + var origLocalDescription = Object.getOwnPropertyDescriptor( + window.RTCPeerConnection.prototype, 'localDescription'); + Object.defineProperty(window.RTCPeerConnection.prototype, + 'localDescription', { + get: function() { + var pc = this; + var description = origLocalDescription.get.apply(this); + if (description.type === '') { + return description; + } + return replaceInternalStreamId(pc, description); + } + }); + + window.RTCPeerConnection.prototype.removeTrack = function(sender) { + var pc = this; + if (pc.signalingState === 'closed') { + throw new DOMException( + 'The RTCPeerConnection\'s signalingState is \'closed\'.', + 'InvalidStateError'); + } + // We can not yet check for sender instanceof RTCRtpSender + // since we shim RTPSender. So we check if sender._pc is set. + if (!sender._pc) { + throw new DOMException('Argument 1 of RTCPeerConnection.removeTrack ' + + 'does not implement interface RTCRtpSender.', 'TypeError'); + } + var isLocal = sender._pc === pc; + if (!isLocal) { + throw new DOMException('Sender was not created by this connection.', + 'InvalidAccessError'); + } + + // Search for the native stream the senders track belongs to. + pc._streams = pc._streams || {}; + var stream; + Object.keys(pc._streams).forEach(function(streamid) { + var hasTrack = pc._streams[streamid].getTracks().find(function(track) { + return sender.track === track; + }); + if (hasTrack) { + stream = pc._streams[streamid]; + } + }); + + if (stream) { + if (stream.getTracks().length === 1) { + // if this is the last track of the stream, remove the stream. This + // takes care of any shimmed _senders. + pc.removeStream(pc._reverseStreams[stream.id]); + } else { + // relying on the same odd chrome behaviour as above. + stream.removeTrack(sender.track); + } + pc.dispatchEvent(new Event('negotiationneeded')); + } + }; + }, + + shimPeerConnection: function(window) { + var browserDetails = utils.detectBrowser(window); + + // The RTCPeerConnection object. + if (!window.RTCPeerConnection && window.webkitRTCPeerConnection) { + window.RTCPeerConnection = function(pcConfig, pcConstraints) { + // Translate iceTransportPolicy to iceTransports, + // see https://code.google.com/p/webrtc/issues/detail?id=4869 + // this was fixed in M56 along with unprefixing RTCPeerConnection. + logging('PeerConnection'); + if (pcConfig && pcConfig.iceTransportPolicy) { + pcConfig.iceTransports = pcConfig.iceTransportPolicy; + } + + return new window.webkitRTCPeerConnection(pcConfig, pcConstraints); + }; + window.RTCPeerConnection.prototype = + window.webkitRTCPeerConnection.prototype; + // wrap static methods. Currently just generateCertificate. + if (window.webkitRTCPeerConnection.generateCertificate) { + Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', { + get: function() { + return window.webkitRTCPeerConnection.generateCertificate; + } + }); + } + } else { + // migrate from non-spec RTCIceServer.url to RTCIceServer.urls + var OrigPeerConnection = window.RTCPeerConnection; + window.RTCPeerConnection = function(pcConfig, pcConstraints) { + if (pcConfig && pcConfig.iceServers) { + var newIceServers = []; + for (var i = 0; i < pcConfig.iceServers.length; i++) { + var server = pcConfig.iceServers[i]; + if (!server.hasOwnProperty('urls') && + server.hasOwnProperty('url')) { + utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls'); + server = JSON.parse(JSON.stringify(server)); + server.urls = server.url; + newIceServers.push(server); + } else { + newIceServers.push(pcConfig.iceServers[i]); + } + } + pcConfig.iceServers = newIceServers; + } + return new OrigPeerConnection(pcConfig, pcConstraints); + }; + window.RTCPeerConnection.prototype = OrigPeerConnection.prototype; + // wrap static methods. Currently just generateCertificate. + Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', { + get: function() { + return OrigPeerConnection.generateCertificate; + } + }); + } + + var origGetStats = window.RTCPeerConnection.prototype.getStats; + window.RTCPeerConnection.prototype.getStats = function(selector, + successCallback, errorCallback) { + var pc = this; + var args = arguments; + + // If selector is a function then we are in the old style stats so just + // pass back the original getStats format to avoid breaking old users. + if (arguments.length > 0 && typeof selector === 'function') { + return origGetStats.apply(this, arguments); + } + + // When spec-style getStats is supported, return those when called with + // either no arguments or the selector argument is null. + if (origGetStats.length === 0 && (arguments.length === 0 || + typeof arguments[0] !== 'function')) { + return origGetStats.apply(this, []); + } + + var fixChromeStats_ = function(response) { + var standardReport = {}; + var reports = response.result(); + reports.forEach(function(report) { + var standardStats = { + id: report.id, + timestamp: report.timestamp, + type: { + localcandidate: 'local-candidate', + remotecandidate: 'remote-candidate' + }[report.type] || report.type + }; + report.names().forEach(function(name) { + standardStats[name] = report.stat(name); + }); + standardReport[standardStats.id] = standardStats; + }); + + return standardReport; + }; + + // shim getStats with maplike support + var makeMapStats = function(stats) { + return new Map(Object.keys(stats).map(function(key) { + return [key, stats[key]]; + })); + }; + + if (arguments.length >= 2) { + var successCallbackWrapper_ = function(response) { + args[1](makeMapStats(fixChromeStats_(response))); + }; + + return origGetStats.apply(this, [successCallbackWrapper_, + arguments[0]]); + } + + // promise-support + return new Promise(function(resolve, reject) { + origGetStats.apply(pc, [ + function(response) { + resolve(makeMapStats(fixChromeStats_(response))); + }, reject]); + }).then(successCallback, errorCallback); + }; + + // add promise support -- natively available in Chrome 51 + if (browserDetails.version < 51) { + ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'] + .forEach(function(method) { + var nativeMethod = window.RTCPeerConnection.prototype[method]; + window.RTCPeerConnection.prototype[method] = function() { + var args = arguments; + var pc = this; + var promise = new Promise(function(resolve, reject) { + nativeMethod.apply(pc, [args[0], resolve, reject]); + }); + if (args.length < 2) { + return promise; + } + return promise.then(function() { + args[1].apply(null, []); + }, + function(err) { + if (args.length >= 3) { + args[2].apply(null, [err]); + } + }); + }; + }); + } + + // promise support for createOffer and createAnswer. Available (without + // bugs) since M52: crbug/619289 + if (browserDetails.version < 52) { + ['createOffer', 'createAnswer'].forEach(function(method) { + var nativeMethod = window.RTCPeerConnection.prototype[method]; + window.RTCPeerConnection.prototype[method] = function() { + var pc = this; + if (arguments.length < 1 || (arguments.length === 1 && + typeof arguments[0] === 'object')) { + var opts = arguments.length === 1 ? arguments[0] : undefined; + return new Promise(function(resolve, reject) { + nativeMethod.apply(pc, [resolve, reject, opts]); + }); + } + return nativeMethod.apply(this, arguments); + }; + }); + } + + // shim implicit creation of RTCSessionDescription/RTCIceCandidate + ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'] + .forEach(function(method) { + var nativeMethod = window.RTCPeerConnection.prototype[method]; + window.RTCPeerConnection.prototype[method] = function() { + arguments[0] = new ((method === 'addIceCandidate') ? + window.RTCIceCandidate : + window.RTCSessionDescription)(arguments[0]); + return nativeMethod.apply(this, arguments); + }; + }); + + // support for addIceCandidate(null or undefined) + var nativeAddIceCandidate = + window.RTCPeerConnection.prototype.addIceCandidate; + window.RTCPeerConnection.prototype.addIceCandidate = function() { + if (!arguments[0]) { + if (arguments[1]) { + arguments[1].apply(null); + } + return Promise.resolve(); + } + return nativeAddIceCandidate.apply(this, arguments); + }; + } +}; + +},{"../utils.js":36,"./getusermedia":29}],29:[function(require,module,exports){ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ +'use strict'; +var utils = require('../utils.js'); +var logging = utils.log; + +// Expose public methods. +module.exports = function(window) { + var browserDetails = utils.detectBrowser(window); + var navigator = window && window.navigator; + + var constraintsToChrome_ = function(c) { + if (typeof c !== 'object' || c.mandatory || c.optional) { + return c; + } + var cc = {}; + Object.keys(c).forEach(function(key) { + if (key === 'require' || key === 'advanced' || key === 'mediaSource') { + return; + } + var r = (typeof c[key] === 'object') ? c[key] : {ideal: c[key]}; + if (r.exact !== undefined && typeof r.exact === 'number') { + r.min = r.max = r.exact; + } + var oldname_ = function(prefix, name) { + if (prefix) { + return prefix + name.charAt(0).toUpperCase() + name.slice(1); + } + return (name === 'deviceId') ? 'sourceId' : name; + }; + if (r.ideal !== undefined) { + cc.optional = cc.optional || []; + var oc = {}; + if (typeof r.ideal === 'number') { + oc[oldname_('min', key)] = r.ideal; + cc.optional.push(oc); + oc = {}; + oc[oldname_('max', key)] = r.ideal; + cc.optional.push(oc); + } else { + oc[oldname_('', key)] = r.ideal; + cc.optional.push(oc); + } + } + if (r.exact !== undefined && typeof r.exact !== 'number') { + cc.mandatory = cc.mandatory || {}; + cc.mandatory[oldname_('', key)] = r.exact; + } else { + ['min', 'max'].forEach(function(mix) { + if (r[mix] !== undefined) { + cc.mandatory = cc.mandatory || {}; + cc.mandatory[oldname_(mix, key)] = r[mix]; + } + }); + } + }); + if (c.advanced) { + cc.optional = (cc.optional || []).concat(c.advanced); + } + return cc; + }; + + var shimConstraints_ = function(constraints, func) { + if (browserDetails.version >= 61) { + return func(constraints); + } + constraints = JSON.parse(JSON.stringify(constraints)); + if (constraints && typeof constraints.audio === 'object') { + var remap = function(obj, a, b) { + if (a in obj && !(b in obj)) { + obj[b] = obj[a]; + delete obj[a]; + } + }; + constraints = JSON.parse(JSON.stringify(constraints)); + remap(constraints.audio, 'autoGainControl', 'googAutoGainControl'); + remap(constraints.audio, 'noiseSuppression', 'googNoiseSuppression'); + constraints.audio = constraintsToChrome_(constraints.audio); + } + if (constraints && typeof constraints.video === 'object') { + // Shim facingMode for mobile & surface pro. + var face = constraints.video.facingMode; + face = face && ((typeof face === 'object') ? face : {ideal: face}); + var getSupportedFacingModeLies = browserDetails.version < 66; + + if ((face && (face.exact === 'user' || face.exact === 'environment' || + face.ideal === 'user' || face.ideal === 'environment')) && + !(navigator.mediaDevices.getSupportedConstraints && + navigator.mediaDevices.getSupportedConstraints().facingMode && + !getSupportedFacingModeLies)) { + delete constraints.video.facingMode; + var matches; + if (face.exact === 'environment' || face.ideal === 'environment') { + matches = ['back', 'rear']; + } else if (face.exact === 'user' || face.ideal === 'user') { + matches = ['front']; + } + if (matches) { + // Look for matches in label, or use last cam for back (typical). + return navigator.mediaDevices.enumerateDevices() + .then(function(devices) { + devices = devices.filter(function(d) { + return d.kind === 'videoinput'; + }); + var dev = devices.find(function(d) { + return matches.some(function(match) { + return d.label.toLowerCase().indexOf(match) !== -1; + }); + }); + if (!dev && devices.length && matches.indexOf('back') !== -1) { + dev = devices[devices.length - 1]; // more likely the back cam + } + if (dev) { + constraints.video.deviceId = face.exact ? {exact: dev.deviceId} : + {ideal: dev.deviceId}; + } + constraints.video = constraintsToChrome_(constraints.video); + logging('chrome: ' + JSON.stringify(constraints)); + return func(constraints); + }); + } + } + constraints.video = constraintsToChrome_(constraints.video); + } + logging('chrome: ' + JSON.stringify(constraints)); + return func(constraints); + }; + + var shimError_ = function(e) { + return { + name: { + PermissionDeniedError: 'NotAllowedError', + InvalidStateError: 'NotReadableError', + DevicesNotFoundError: 'NotFoundError', + ConstraintNotSatisfiedError: 'OverconstrainedError', + TrackStartError: 'NotReadableError', + MediaDeviceFailedDueToShutdown: 'NotReadableError', + MediaDeviceKillSwitchOn: 'NotReadableError' + }[e.name] || e.name, + message: e.message, + constraint: e.constraintName, + toString: function() { + return this.name + (this.message && ': ') + this.message; + } + }; + }; + + var getUserMedia_ = function(constraints, onSuccess, onError) { + shimConstraints_(constraints, function(c) { + navigator.webkitGetUserMedia(c, onSuccess, function(e) { + if (onError) { + onError(shimError_(e)); + } + }); + }); + }; + + navigator.getUserMedia = getUserMedia_; + + // Returns the result of getUserMedia as a Promise. + var getUserMediaPromise_ = function(constraints) { + return new Promise(function(resolve, reject) { + navigator.getUserMedia(constraints, resolve, reject); + }); + }; + + if (!navigator.mediaDevices) { + navigator.mediaDevices = { + getUserMedia: getUserMediaPromise_, + enumerateDevices: function() { + return new Promise(function(resolve) { + var kinds = {audio: 'audioinput', video: 'videoinput'}; + return window.MediaStreamTrack.getSources(function(devices) { + resolve(devices.map(function(device) { + return {label: device.label, + kind: kinds[device.kind], + deviceId: device.id, + groupId: ''}; + })); + }); + }); + }, + getSupportedConstraints: function() { + return { + deviceId: true, echoCancellation: true, facingMode: true, + frameRate: true, height: true, width: true + }; + } + }; + } + + // A shim for getUserMedia method on the mediaDevices object. + // TODO(KaptenJansson) remove once implemented in Chrome stable. + if (!navigator.mediaDevices.getUserMedia) { + navigator.mediaDevices.getUserMedia = function(constraints) { + return getUserMediaPromise_(constraints); + }; + } else { + // Even though Chrome 45 has navigator.mediaDevices and a getUserMedia + // function which returns a Promise, it does not accept spec-style + // constraints. + var origGetUserMedia = navigator.mediaDevices.getUserMedia. + bind(navigator.mediaDevices); + navigator.mediaDevices.getUserMedia = function(cs) { + return shimConstraints_(cs, function(c) { + return origGetUserMedia(c).then(function(stream) { + if (c.audio && !stream.getAudioTracks().length || + c.video && !stream.getVideoTracks().length) { + stream.getTracks().forEach(function(track) { + track.stop(); + }); + throw new DOMException('', 'NotFoundError'); + } + return stream; + }, function(e) { + return Promise.reject(shimError_(e)); + }); + }); + }; + } + + // Dummy devicechange event methods. + // TODO(KaptenJansson) remove once implemented in Chrome stable. + if (typeof navigator.mediaDevices.addEventListener === 'undefined') { + navigator.mediaDevices.addEventListener = function() { + logging('Dummy mediaDevices.addEventListener called.'); + }; + } + if (typeof navigator.mediaDevices.removeEventListener === 'undefined') { + navigator.mediaDevices.removeEventListener = function() { + logging('Dummy mediaDevices.removeEventListener called.'); + }; + } +}; + +},{"../utils.js":36}],30:[function(require,module,exports){ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ +'use strict'; + +var SDPUtils = require('sdp'); +var utils = require('./utils'); + +module.exports = { + shimRTCIceCandidate: function(window) { + // foundation is arbitrarily chosen as an indicator for full support for + // https://w3c.github.io/webrtc-pc/#rtcicecandidate-interface + if (window.RTCIceCandidate && 'foundation' in + window.RTCIceCandidate.prototype) { + return; + } + + var NativeRTCIceCandidate = window.RTCIceCandidate; + window.RTCIceCandidate = function(args) { + // Remove the a= which shouldn't be part of the candidate string. + if (typeof args === 'object' && args.candidate && + args.candidate.indexOf('a=') === 0) { + args = JSON.parse(JSON.stringify(args)); + args.candidate = args.candidate.substr(2); + } + + // Augment the native candidate with the parsed fields. + var nativeCandidate = new NativeRTCIceCandidate(args); + var parsedCandidate = SDPUtils.parseCandidate(args.candidate); + var augmentedCandidate = Object.assign(nativeCandidate, + parsedCandidate); + + // Add a serializer that does not serialize the extra attributes. + augmentedCandidate.toJSON = function() { + return { + candidate: augmentedCandidate.candidate, + sdpMid: augmentedCandidate.sdpMid, + sdpMLineIndex: augmentedCandidate.sdpMLineIndex, + usernameFragment: augmentedCandidate.usernameFragment, + }; + }; + return augmentedCandidate; + }; + + // Hook up the augmented candidate in onicecandidate and + // addEventListener('icecandidate', ...) + utils.wrapPeerConnectionEvent(window, 'icecandidate', function(e) { + if (e.candidate) { + Object.defineProperty(e, 'candidate', { + value: new window.RTCIceCandidate(e.candidate), + writable: 'false' + }); + } + return e; + }); + }, + + // shimCreateObjectURL must be called before shimSourceObject to avoid loop. + + shimCreateObjectURL: function(window) { + var URL = window && window.URL; + + if (!(typeof window === 'object' && window.HTMLMediaElement && + 'srcObject' in window.HTMLMediaElement.prototype && + URL.createObjectURL && URL.revokeObjectURL)) { + // Only shim CreateObjectURL using srcObject if srcObject exists. + return undefined; + } + + var nativeCreateObjectURL = URL.createObjectURL.bind(URL); + var nativeRevokeObjectURL = URL.revokeObjectURL.bind(URL); + var streams = new Map(), newId = 0; + + URL.createObjectURL = function(stream) { + if ('getTracks' in stream) { + var url = 'polyblob:' + (++newId); + streams.set(url, stream); + utils.deprecated('URL.createObjectURL(stream)', + 'elem.srcObject = stream'); + return url; + } + return nativeCreateObjectURL(stream); + }; + URL.revokeObjectURL = function(url) { + nativeRevokeObjectURL(url); + streams.delete(url); + }; + + var dsc = Object.getOwnPropertyDescriptor(window.HTMLMediaElement.prototype, + 'src'); + Object.defineProperty(window.HTMLMediaElement.prototype, 'src', { + get: function() { + return dsc.get.apply(this); + }, + set: function(url) { + this.srcObject = streams.get(url) || null; + return dsc.set.apply(this, [url]); + } + }); + + var nativeSetAttribute = window.HTMLMediaElement.prototype.setAttribute; + window.HTMLMediaElement.prototype.setAttribute = function() { + if (arguments.length === 2 && + ('' + arguments[0]).toLowerCase() === 'src') { + this.srcObject = streams.get(arguments[1]) || null; + } + return nativeSetAttribute.apply(this, arguments); + }; + }, + + shimMaxMessageSize: function(window) { + if (window.RTCSctpTransport || !window.RTCPeerConnection) { + return; + } + var browserDetails = utils.detectBrowser(window); + + if (!('sctp' in window.RTCPeerConnection.prototype)) { + Object.defineProperty(window.RTCPeerConnection.prototype, 'sctp', { + get: function() { + return typeof this._sctp === 'undefined' ? null : this._sctp; + } + }); + } + + var sctpInDescription = function(description) { + var sections = SDPUtils.splitSections(description.sdp); + sections.shift(); + return sections.some(function(mediaSection) { + var mLine = SDPUtils.parseMLine(mediaSection); + return mLine && mLine.kind === 'application' + && mLine.protocol.indexOf('SCTP') !== -1; + }); + }; + + var getRemoteFirefoxVersion = function(description) { + // TODO: Is there a better solution for detecting Firefox? + var match = description.sdp.match(/mozilla...THIS_IS_SDPARTA-(\d+)/); + if (match === null || match.length < 2) { + return -1; + } + var version = parseInt(match[1], 10); + // Test for NaN (yes, this is ugly) + return version !== version ? -1 : version; + }; + + var getCanSendMaxMessageSize = function(remoteIsFirefox) { + // Every implementation we know can send at least 64 KiB. + // Note: Although Chrome is technically able to send up to 256 KiB, the + // data does not reach the other peer reliably. + // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=8419 + var canSendMaxMessageSize = 65536; + if (browserDetails.browser === 'firefox') { + if (browserDetails.version < 57) { + if (remoteIsFirefox === -1) { + // FF < 57 will send in 16 KiB chunks using the deprecated PPID + // fragmentation. + canSendMaxMessageSize = 16384; + } else { + // However, other FF (and RAWRTC) can reassemble PPID-fragmented + // messages. Thus, supporting ~2 GiB when sending. + canSendMaxMessageSize = 2147483637; + } + } else { + // Currently, all FF >= 57 will reset the remote maximum message size + // to the default value when a data channel is created at a later + // stage. :( + // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831 + canSendMaxMessageSize = + browserDetails.version === 57 ? 65535 : 65536; + } + } + return canSendMaxMessageSize; + }; + + var getMaxMessageSize = function(description, remoteIsFirefox) { + // Note: 65536 bytes is the default value from the SDP spec. Also, + // every implementation we know supports receiving 65536 bytes. + var maxMessageSize = 65536; + + // FF 57 has a slightly incorrect default remote max message size, so + // we need to adjust it here to avoid a failure when sending. + // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1425697 + if (browserDetails.browser === 'firefox' + && browserDetails.version === 57) { + maxMessageSize = 65535; + } + + var match = SDPUtils.matchPrefix(description.sdp, 'a=max-message-size:'); + if (match.length > 0) { + maxMessageSize = parseInt(match[0].substr(19), 10); + } else if (browserDetails.browser === 'firefox' && + remoteIsFirefox !== -1) { + // If the maximum message size is not present in the remote SDP and + // both local and remote are Firefox, the remote peer can receive + // ~2 GiB. + maxMessageSize = 2147483637; + } + return maxMessageSize; + }; + + var origSetRemoteDescription = + window.RTCPeerConnection.prototype.setRemoteDescription; + window.RTCPeerConnection.prototype.setRemoteDescription = function() { + var pc = this; + pc._sctp = null; + + if (sctpInDescription(arguments[0])) { + // Check if the remote is FF. + var isFirefox = getRemoteFirefoxVersion(arguments[0]); + + // Get the maximum message size the local peer is capable of sending + var canSendMMS = getCanSendMaxMessageSize(isFirefox); + + // Get the maximum message size of the remote peer. + var remoteMMS = getMaxMessageSize(arguments[0], isFirefox); + + // Determine final maximum message size + var maxMessageSize; + if (canSendMMS === 0 && remoteMMS === 0) { + maxMessageSize = Number.POSITIVE_INFINITY; + } else if (canSendMMS === 0 || remoteMMS === 0) { + maxMessageSize = Math.max(canSendMMS, remoteMMS); + } else { + maxMessageSize = Math.min(canSendMMS, remoteMMS); + } + + // Create a dummy RTCSctpTransport object and the 'maxMessageSize' + // attribute. + var sctp = {}; + Object.defineProperty(sctp, 'maxMessageSize', { + get: function() { + return maxMessageSize; + } + }); + pc._sctp = sctp; + } + + return origSetRemoteDescription.apply(pc, arguments); + }; + }, + + shimSendThrowTypeError: function(window) { + // Note: Although Firefox >= 57 has a native implementation, the maximum + // message size can be reset for all data channels at a later stage. + // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831 + + var origCreateDataChannel = + window.RTCPeerConnection.prototype.createDataChannel; + window.RTCPeerConnection.prototype.createDataChannel = function() { + var pc = this; + var dataChannel = origCreateDataChannel.apply(pc, arguments); + var origDataChannelSend = dataChannel.send; + + // Patch 'send' method + dataChannel.send = function() { + var dc = this; + var data = arguments[0]; + var length = data.length || data.size || data.byteLength; + if (length > pc.sctp.maxMessageSize) { + throw new DOMException('Message too large (can send a maximum of ' + + pc.sctp.maxMessageSize + ' bytes)', 'TypeError'); + } + return origDataChannelSend.apply(dc, arguments); + }; + + return dataChannel; + }; + } +}; + +},{"./utils":36,"sdp":19}],31:[function(require,module,exports){ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ +'use strict'; + +var utils = require('../utils'); +var shimRTCPeerConnection = require('rtcpeerconnection-shim'); + +module.exports = { + shimGetUserMedia: require('./getusermedia'), + shimPeerConnection: function(window) { + var browserDetails = utils.detectBrowser(window); + + if (window.RTCIceGatherer) { + // ORTC defines an RTCIceCandidate object but no constructor. + // Not implemented in Edge. + if (!window.RTCIceCandidate) { + window.RTCIceCandidate = function(args) { + return args; + }; + } + // ORTC does not have a session description object but + // other browsers (i.e. Chrome) that will support both PC and ORTC + // in the future might have this defined already. + if (!window.RTCSessionDescription) { + window.RTCSessionDescription = function(args) { + return args; + }; + } + // this adds an additional event listener to MediaStrackTrack that signals + // when a tracks enabled property was changed. Workaround for a bug in + // addStream, see below. No longer required in 15025+ + if (browserDetails.version < 15025) { + var origMSTEnabled = Object.getOwnPropertyDescriptor( + window.MediaStreamTrack.prototype, 'enabled'); + Object.defineProperty(window.MediaStreamTrack.prototype, 'enabled', { + set: function(value) { + origMSTEnabled.set.call(this, value); + var ev = new Event('enabled'); + ev.enabled = value; + this.dispatchEvent(ev); + } + }); + } + } + + // ORTC defines the DTMF sender a bit different. + // https://github.com/w3c/ortc/issues/714 + if (window.RTCRtpSender && !('dtmf' in window.RTCRtpSender.prototype)) { + Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', { + get: function() { + if (this._dtmf === undefined) { + if (this.track.kind === 'audio') { + this._dtmf = new window.RTCDtmfSender(this); + } else if (this.track.kind === 'video') { + this._dtmf = null; + } + } + return this._dtmf; + } + }); + } + + window.RTCPeerConnection = + shimRTCPeerConnection(window, browserDetails.version); + }, + shimReplaceTrack: function(window) { + // ORTC has replaceTrack -- https://github.com/w3c/ortc/issues/614 + if (window.RTCRtpSender && + !('replaceTrack' in window.RTCRtpSender.prototype)) { + window.RTCRtpSender.prototype.replaceTrack = + window.RTCRtpSender.prototype.setTrack; + } + } +}; + +},{"../utils":36,"./getusermedia":32,"rtcpeerconnection-shim":10}],32:[function(require,module,exports){ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ +'use strict'; + +// Expose public methods. +module.exports = function(window) { + var navigator = window && window.navigator; + + var shimError_ = function(e) { + return { + name: {PermissionDeniedError: 'NotAllowedError'}[e.name] || e.name, + message: e.message, + constraint: e.constraint, + toString: function() { + return this.name; + } + }; + }; + + // getUserMedia error shim. + var origGetUserMedia = navigator.mediaDevices.getUserMedia. + bind(navigator.mediaDevices); + navigator.mediaDevices.getUserMedia = function(c) { + return origGetUserMedia(c).catch(function(e) { + return Promise.reject(shimError_(e)); + }); + }; +}; + +},{}],33:[function(require,module,exports){ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ +'use strict'; + +var utils = require('../utils'); + +module.exports = { + shimGetUserMedia: require('./getusermedia'), + shimOnTrack: function(window) { + if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in + window.RTCPeerConnection.prototype)) { + Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', { + get: function() { + return this._ontrack; + }, + set: function(f) { + if (this._ontrack) { + this.removeEventListener('track', this._ontrack); + this.removeEventListener('addstream', this._ontrackpoly); + } + this.addEventListener('track', this._ontrack = f); + this.addEventListener('addstream', this._ontrackpoly = function(e) { + e.stream.getTracks().forEach(function(track) { + var event = new Event('track'); + event.track = track; + event.receiver = {track: track}; + event.transceiver = {receiver: event.receiver}; + event.streams = [e.stream]; + this.dispatchEvent(event); + }.bind(this)); + }.bind(this)); + } + }); + } + if (typeof window === 'object' && window.RTCTrackEvent && + ('receiver' in window.RTCTrackEvent.prototype) && + !('transceiver' in window.RTCTrackEvent.prototype)) { + Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', { + get: function() { + return {receiver: this.receiver}; + } + }); + } + }, + + shimSourceObject: function(window) { + // Firefox has supported mozSrcObject since FF22, unprefixed in 42. + if (typeof window === 'object') { + if (window.HTMLMediaElement && + !('srcObject' in window.HTMLMediaElement.prototype)) { + // Shim the srcObject property, once, when HTMLMediaElement is found. + Object.defineProperty(window.HTMLMediaElement.prototype, 'srcObject', { + get: function() { + return this.mozSrcObject; + }, + set: function(stream) { + this.mozSrcObject = stream; + } + }); + } + } + }, + + shimPeerConnection: function(window) { + var browserDetails = utils.detectBrowser(window); + + if (typeof window !== 'object' || !(window.RTCPeerConnection || + window.mozRTCPeerConnection)) { + return; // probably media.peerconnection.enabled=false in about:config + } + // The RTCPeerConnection object. + if (!window.RTCPeerConnection) { + window.RTCPeerConnection = function(pcConfig, pcConstraints) { + if (browserDetails.version < 38) { + // .urls is not supported in FF < 38. + // create RTCIceServers with a single url. + if (pcConfig && pcConfig.iceServers) { + var newIceServers = []; + for (var i = 0; i < pcConfig.iceServers.length; i++) { + var server = pcConfig.iceServers[i]; + if (server.hasOwnProperty('urls')) { + for (var j = 0; j < server.urls.length; j++) { + var newServer = { + url: server.urls[j] + }; + if (server.urls[j].indexOf('turn') === 0) { + newServer.username = server.username; + newServer.credential = server.credential; + } + newIceServers.push(newServer); + } + } else { + newIceServers.push(pcConfig.iceServers[i]); + } + } + pcConfig.iceServers = newIceServers; + } + } + return new window.mozRTCPeerConnection(pcConfig, pcConstraints); + }; + window.RTCPeerConnection.prototype = + window.mozRTCPeerConnection.prototype; + + // wrap static methods. Currently just generateCertificate. + if (window.mozRTCPeerConnection.generateCertificate) { + Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', { + get: function() { + return window.mozRTCPeerConnection.generateCertificate; + } + }); + } + + window.RTCSessionDescription = window.mozRTCSessionDescription; + window.RTCIceCandidate = window.mozRTCIceCandidate; + } + + // shim away need for obsolete RTCIceCandidate/RTCSessionDescription. + ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'] + .forEach(function(method) { + var nativeMethod = window.RTCPeerConnection.prototype[method]; + window.RTCPeerConnection.prototype[method] = function() { + arguments[0] = new ((method === 'addIceCandidate') ? + window.RTCIceCandidate : + window.RTCSessionDescription)(arguments[0]); + return nativeMethod.apply(this, arguments); + }; + }); + + // support for addIceCandidate(null or undefined) + var nativeAddIceCandidate = + window.RTCPeerConnection.prototype.addIceCandidate; + window.RTCPeerConnection.prototype.addIceCandidate = function() { + if (!arguments[0]) { + if (arguments[1]) { + arguments[1].apply(null); + } + return Promise.resolve(); + } + return nativeAddIceCandidate.apply(this, arguments); + }; + + // shim getStats with maplike support + var makeMapStats = function(stats) { + var map = new Map(); + Object.keys(stats).forEach(function(key) { + map.set(key, stats[key]); + map[key] = stats[key]; + }); + return map; + }; + + var modernStatsTypes = { + inboundrtp: 'inbound-rtp', + outboundrtp: 'outbound-rtp', + candidatepair: 'candidate-pair', + localcandidate: 'local-candidate', + remotecandidate: 'remote-candidate' + }; + + var nativeGetStats = window.RTCPeerConnection.prototype.getStats; + window.RTCPeerConnection.prototype.getStats = function( + selector, + onSucc, + onErr + ) { + return nativeGetStats.apply(this, [selector || null]) + .then(function(stats) { + if (browserDetails.version < 48) { + stats = makeMapStats(stats); + } + if (browserDetails.version < 53 && !onSucc) { + // Shim only promise getStats with spec-hyphens in type names + // Leave callback version alone; misc old uses of forEach before Map + try { + stats.forEach(function(stat) { + stat.type = modernStatsTypes[stat.type] || stat.type; + }); + } catch (e) { + if (e.name !== 'TypeError') { + throw e; + } + // Avoid TypeError: "type" is read-only, in old versions. 34-43ish + stats.forEach(function(stat, i) { + stats.set(i, Object.assign({}, stat, { + type: modernStatsTypes[stat.type] || stat.type + })); + }); + } + } + return stats; + }) + .then(onSucc, onErr); + }; + }, + + shimRemoveStream: function(window) { + if (!window.RTCPeerConnection || + 'removeStream' in window.RTCPeerConnection.prototype) { + return; + } + window.RTCPeerConnection.prototype.removeStream = function(stream) { + var pc = this; + utils.deprecated('removeStream', 'removeTrack'); + this.getSenders().forEach(function(sender) { + if (sender.track && stream.getTracks().indexOf(sender.track) !== -1) { + pc.removeTrack(sender); + } + }); + }; + } +}; + +},{"../utils":36,"./getusermedia":34}],34:[function(require,module,exports){ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ +'use strict'; + +var utils = require('../utils'); +var logging = utils.log; + +// Expose public methods. +module.exports = function(window) { + var browserDetails = utils.detectBrowser(window); + var navigator = window && window.navigator; + var MediaStreamTrack = window && window.MediaStreamTrack; + + var shimError_ = function(e) { + return { + name: { + InternalError: 'NotReadableError', + NotSupportedError: 'TypeError', + PermissionDeniedError: 'NotAllowedError', + SecurityError: 'NotAllowedError' + }[e.name] || e.name, + message: { + 'The operation is insecure.': 'The request is not allowed by the ' + + 'user agent or the platform in the current context.' + }[e.message] || e.message, + constraint: e.constraint, + toString: function() { + return this.name + (this.message && ': ') + this.message; + } + }; + }; + + // getUserMedia constraints shim. + var getUserMedia_ = function(constraints, onSuccess, onError) { + var constraintsToFF37_ = function(c) { + if (typeof c !== 'object' || c.require) { + return c; + } + var require = []; + Object.keys(c).forEach(function(key) { + if (key === 'require' || key === 'advanced' || key === 'mediaSource') { + return; + } + var r = c[key] = (typeof c[key] === 'object') ? + c[key] : {ideal: c[key]}; + if (r.min !== undefined || + r.max !== undefined || r.exact !== undefined) { + require.push(key); + } + if (r.exact !== undefined) { + if (typeof r.exact === 'number') { + r. min = r.max = r.exact; + } else { + c[key] = r.exact; + } + delete r.exact; + } + if (r.ideal !== undefined) { + c.advanced = c.advanced || []; + var oc = {}; + if (typeof r.ideal === 'number') { + oc[key] = {min: r.ideal, max: r.ideal}; + } else { + oc[key] = r.ideal; + } + c.advanced.push(oc); + delete r.ideal; + if (!Object.keys(r).length) { + delete c[key]; + } + } + }); + if (require.length) { + c.require = require; + } + return c; + }; + constraints = JSON.parse(JSON.stringify(constraints)); + if (browserDetails.version < 38) { + logging('spec: ' + JSON.stringify(constraints)); + if (constraints.audio) { + constraints.audio = constraintsToFF37_(constraints.audio); + } + if (constraints.video) { + constraints.video = constraintsToFF37_(constraints.video); + } + logging('ff37: ' + JSON.stringify(constraints)); + } + return navigator.mozGetUserMedia(constraints, onSuccess, function(e) { + onError(shimError_(e)); + }); + }; + + // Returns the result of getUserMedia as a Promise. + var getUserMediaPromise_ = function(constraints) { + return new Promise(function(resolve, reject) { + getUserMedia_(constraints, resolve, reject); + }); + }; + + // Shim for mediaDevices on older versions. + if (!navigator.mediaDevices) { + navigator.mediaDevices = {getUserMedia: getUserMediaPromise_, + addEventListener: function() { }, + removeEventListener: function() { } + }; + } + navigator.mediaDevices.enumerateDevices = + navigator.mediaDevices.enumerateDevices || function() { + return new Promise(function(resolve) { + var infos = [ + {kind: 'audioinput', deviceId: 'default', label: '', groupId: ''}, + {kind: 'videoinput', deviceId: 'default', label: '', groupId: ''} + ]; + resolve(infos); + }); + }; + + if (browserDetails.version < 41) { + // Work around http://bugzil.la/1169665 + var orgEnumerateDevices = + navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices); + navigator.mediaDevices.enumerateDevices = function() { + return orgEnumerateDevices().then(undefined, function(e) { + if (e.name === 'NotFoundError') { + return []; + } + throw e; + }); + }; + } + if (browserDetails.version < 49) { + var origGetUserMedia = navigator.mediaDevices.getUserMedia. + bind(navigator.mediaDevices); + navigator.mediaDevices.getUserMedia = function(c) { + return origGetUserMedia(c).then(function(stream) { + // Work around https://bugzil.la/802326 + if (c.audio && !stream.getAudioTracks().length || + c.video && !stream.getVideoTracks().length) { + stream.getTracks().forEach(function(track) { + track.stop(); + }); + throw new DOMException('The object can not be found here.', + 'NotFoundError'); + } + return stream; + }, function(e) { + return Promise.reject(shimError_(e)); + }); + }; + } + if (!(browserDetails.version > 55 && + 'autoGainControl' in navigator.mediaDevices.getSupportedConstraints())) { + var remap = function(obj, a, b) { + if (a in obj && !(b in obj)) { + obj[b] = obj[a]; + delete obj[a]; + } + }; + + var nativeGetUserMedia = navigator.mediaDevices.getUserMedia. + bind(navigator.mediaDevices); + navigator.mediaDevices.getUserMedia = function(c) { + if (typeof c === 'object' && typeof c.audio === 'object') { + c = JSON.parse(JSON.stringify(c)); + remap(c.audio, 'autoGainControl', 'mozAutoGainControl'); + remap(c.audio, 'noiseSuppression', 'mozNoiseSuppression'); + } + return nativeGetUserMedia(c); + }; + + if (MediaStreamTrack && MediaStreamTrack.prototype.getSettings) { + var nativeGetSettings = MediaStreamTrack.prototype.getSettings; + MediaStreamTrack.prototype.getSettings = function() { + var obj = nativeGetSettings.apply(this, arguments); + remap(obj, 'mozAutoGainControl', 'autoGainControl'); + remap(obj, 'mozNoiseSuppression', 'noiseSuppression'); + return obj; + }; + } + + if (MediaStreamTrack && MediaStreamTrack.prototype.applyConstraints) { + var nativeApplyConstraints = MediaStreamTrack.prototype.applyConstraints; + MediaStreamTrack.prototype.applyConstraints = function(c) { + if (this.kind === 'audio' && typeof c === 'object') { + c = JSON.parse(JSON.stringify(c)); + remap(c, 'autoGainControl', 'mozAutoGainControl'); + remap(c, 'noiseSuppression', 'mozNoiseSuppression'); + } + return nativeApplyConstraints.apply(this, [c]); + }; + } + } + navigator.getUserMedia = function(constraints, onSuccess, onError) { + if (browserDetails.version < 44) { + return getUserMedia_(constraints, onSuccess, onError); + } + // Replace Firefox 44+'s deprecation warning with unprefixed version. + utils.deprecated('navigator.getUserMedia', + 'navigator.mediaDevices.getUserMedia'); + navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError); + }; +}; + +},{"../utils":36}],35:[function(require,module,exports){ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ +'use strict'; +var utils = require('../utils'); + +module.exports = { + shimLocalStreamsAPI: function(window) { + if (typeof window !== 'object' || !window.RTCPeerConnection) { + return; + } + if (!('getLocalStreams' in window.RTCPeerConnection.prototype)) { + window.RTCPeerConnection.prototype.getLocalStreams = function() { + if (!this._localStreams) { + this._localStreams = []; + } + return this._localStreams; + }; + } + if (!('getStreamById' in window.RTCPeerConnection.prototype)) { + window.RTCPeerConnection.prototype.getStreamById = function(id) { + var result = null; + if (this._localStreams) { + this._localStreams.forEach(function(stream) { + if (stream.id === id) { + result = stream; + } + }); + } + if (this._remoteStreams) { + this._remoteStreams.forEach(function(stream) { + if (stream.id === id) { + result = stream; + } + }); + } + return result; + }; + } + if (!('addStream' in window.RTCPeerConnection.prototype)) { + var _addTrack = window.RTCPeerConnection.prototype.addTrack; + window.RTCPeerConnection.prototype.addStream = function(stream) { + if (!this._localStreams) { + this._localStreams = []; + } + if (this._localStreams.indexOf(stream) === -1) { + this._localStreams.push(stream); + } + var pc = this; + stream.getTracks().forEach(function(track) { + _addTrack.call(pc, track, stream); + }); + }; + + window.RTCPeerConnection.prototype.addTrack = function(track, stream) { + if (stream) { + if (!this._localStreams) { + this._localStreams = [stream]; + } else if (this._localStreams.indexOf(stream) === -1) { + this._localStreams.push(stream); + } + } + return _addTrack.call(this, track, stream); + }; + } + if (!('removeStream' in window.RTCPeerConnection.prototype)) { + window.RTCPeerConnection.prototype.removeStream = function(stream) { + if (!this._localStreams) { + this._localStreams = []; + } + var index = this._localStreams.indexOf(stream); + if (index === -1) { + return; + } + this._localStreams.splice(index, 1); + var pc = this; + var tracks = stream.getTracks(); + this.getSenders().forEach(function(sender) { + if (tracks.indexOf(sender.track) !== -1) { + pc.removeTrack(sender); + } + }); + }; + } + }, + shimRemoteStreamsAPI: function(window) { + if (typeof window !== 'object' || !window.RTCPeerConnection) { + return; + } + if (!('getRemoteStreams' in window.RTCPeerConnection.prototype)) { + window.RTCPeerConnection.prototype.getRemoteStreams = function() { + return this._remoteStreams ? this._remoteStreams : []; + }; + } + if (!('onaddstream' in window.RTCPeerConnection.prototype)) { + Object.defineProperty(window.RTCPeerConnection.prototype, 'onaddstream', { + get: function() { + return this._onaddstream; + }, + set: function(f) { + var pc = this; + if (this._onaddstream) { + this.removeEventListener('addstream', this._onaddstream); + this.removeEventListener('track', this._onaddstreampoly); + } + this.addEventListener('addstream', this._onaddstream = f); + this.addEventListener('track', this._onaddstreampoly = function(e) { + e.streams.forEach(function(stream) { + if (!pc._remoteStreams) { + pc._remoteStreams = []; + } + if (pc._remoteStreams.indexOf(stream) >= 0) { + return; + } + pc._remoteStreams.push(stream); + var event = new Event('addstream'); + event.stream = stream; + pc.dispatchEvent(event); + }); + }); + } + }); + } + }, + shimCallbacksAPI: function(window) { + if (typeof window !== 'object' || !window.RTCPeerConnection) { + return; + } + var prototype = window.RTCPeerConnection.prototype; + var createOffer = prototype.createOffer; + var createAnswer = prototype.createAnswer; + var setLocalDescription = prototype.setLocalDescription; + var setRemoteDescription = prototype.setRemoteDescription; + var addIceCandidate = prototype.addIceCandidate; + + prototype.createOffer = function(successCallback, failureCallback) { + var options = (arguments.length >= 2) ? arguments[2] : arguments[0]; + var promise = createOffer.apply(this, [options]); + if (!failureCallback) { + return promise; + } + promise.then(successCallback, failureCallback); + return Promise.resolve(); + }; + + prototype.createAnswer = function(successCallback, failureCallback) { + var options = (arguments.length >= 2) ? arguments[2] : arguments[0]; + var promise = createAnswer.apply(this, [options]); + if (!failureCallback) { + return promise; + } + promise.then(successCallback, failureCallback); + return Promise.resolve(); + }; + + var withCallback = function(description, successCallback, failureCallback) { + var promise = setLocalDescription.apply(this, [description]); + if (!failureCallback) { + return promise; + } + promise.then(successCallback, failureCallback); + return Promise.resolve(); + }; + prototype.setLocalDescription = withCallback; + + withCallback = function(description, successCallback, failureCallback) { + var promise = setRemoteDescription.apply(this, [description]); + if (!failureCallback) { + return promise; + } + promise.then(successCallback, failureCallback); + return Promise.resolve(); + }; + prototype.setRemoteDescription = withCallback; + + withCallback = function(candidate, successCallback, failureCallback) { + var promise = addIceCandidate.apply(this, [candidate]); + if (!failureCallback) { + return promise; + } + promise.then(successCallback, failureCallback); + return Promise.resolve(); + }; + prototype.addIceCandidate = withCallback; + }, + shimGetUserMedia: function(window) { + var navigator = window && window.navigator; + + if (!navigator.getUserMedia) { + if (navigator.webkitGetUserMedia) { + navigator.getUserMedia = navigator.webkitGetUserMedia.bind(navigator); + } else if (navigator.mediaDevices && + navigator.mediaDevices.getUserMedia) { + navigator.getUserMedia = function(constraints, cb, errcb) { + navigator.mediaDevices.getUserMedia(constraints) + .then(cb, errcb); + }.bind(navigator); + } + } + }, + shimRTCIceServerUrls: function(window) { + // migrate from non-spec RTCIceServer.url to RTCIceServer.urls + var OrigPeerConnection = window.RTCPeerConnection; + window.RTCPeerConnection = function(pcConfig, pcConstraints) { + if (pcConfig && pcConfig.iceServers) { + var newIceServers = []; + for (var i = 0; i < pcConfig.iceServers.length; i++) { + var server = pcConfig.iceServers[i]; + if (!server.hasOwnProperty('urls') && + server.hasOwnProperty('url')) { + utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls'); + server = JSON.parse(JSON.stringify(server)); + server.urls = server.url; + delete server.url; + newIceServers.push(server); + } else { + newIceServers.push(pcConfig.iceServers[i]); + } + } + pcConfig.iceServers = newIceServers; + } + return new OrigPeerConnection(pcConfig, pcConstraints); + }; + window.RTCPeerConnection.prototype = OrigPeerConnection.prototype; + // wrap static methods. Currently just generateCertificate. + if ('generateCertificate' in window.RTCPeerConnection) { + Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', { + get: function() { + return OrigPeerConnection.generateCertificate; + } + }); + } + }, + shimTrackEventTransceiver: function(window) { + // Add event.transceiver member over deprecated event.receiver + if (typeof window === 'object' && window.RTCPeerConnection && + ('receiver' in window.RTCTrackEvent.prototype) && + // can't check 'transceiver' in window.RTCTrackEvent.prototype, as it is + // defined for some reason even when window.RTCTransceiver is not. + !window.RTCTransceiver) { + Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', { + get: function() { + return {receiver: this.receiver}; + } + }); + } + }, + + shimCreateOfferLegacy: function(window) { + var origCreateOffer = window.RTCPeerConnection.prototype.createOffer; + window.RTCPeerConnection.prototype.createOffer = function(offerOptions) { + var pc = this; + if (offerOptions) { + var audioTransceiver = pc.getTransceivers().find(function(transceiver) { + return transceiver.sender.track && + transceiver.sender.track.kind === 'audio'; + }); + if (offerOptions.offerToReceiveAudio === false && audioTransceiver) { + if (audioTransceiver.direction === 'sendrecv') { + if (audioTransceiver.setDirection) { + audioTransceiver.setDirection('sendonly'); + } else { + audioTransceiver.direction = 'sendonly'; + } + } else if (audioTransceiver.direction === 'recvonly') { + if (audioTransceiver.setDirection) { + audioTransceiver.setDirection('inactive'); + } else { + audioTransceiver.direction = 'inactive'; + } + } + } else if (offerOptions.offerToReceiveAudio === true && + !audioTransceiver) { + pc.addTransceiver('audio'); + } + + var videoTransceiver = pc.getTransceivers().find(function(transceiver) { + return transceiver.sender.track && + transceiver.sender.track.kind === 'video'; + }); + if (offerOptions.offerToReceiveVideo === false && videoTransceiver) { + if (videoTransceiver.direction === 'sendrecv') { + videoTransceiver.setDirection('sendonly'); + } else if (videoTransceiver.direction === 'recvonly') { + videoTransceiver.setDirection('inactive'); + } + } else if (offerOptions.offerToReceiveVideo === true && + !videoTransceiver) { + pc.addTransceiver('video'); + } + } + return origCreateOffer.apply(pc, arguments); + }; + } +}; + +},{"../utils":36}],36:[function(require,module,exports){ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ +'use strict'; + +var logDisabled_ = true; +var deprecationWarnings_ = true; + +/** + * Extract browser version out of the provided user agent string. + * + * @param {!string} uastring userAgent string. + * @param {!string} expr Regular expression used as match criteria. + * @param {!number} pos position in the version string to be returned. + * @return {!number} browser version. + */ +function extractVersion(uastring, expr, pos) { + var match = uastring.match(expr); + return match && match.length >= pos && parseInt(match[pos], 10); +} + +// Wraps the peerconnection event eventNameToWrap in a function +// which returns the modified event object. +function wrapPeerConnectionEvent(window, eventNameToWrap, wrapper) { + if (!window.RTCPeerConnection) { + return; + } + var proto = window.RTCPeerConnection.prototype; + var nativeAddEventListener = proto.addEventListener; + proto.addEventListener = function(nativeEventName, cb) { + if (nativeEventName !== eventNameToWrap) { + return nativeAddEventListener.apply(this, arguments); + } + var wrappedCallback = function(e) { + cb(wrapper(e)); + }; + this._eventMap = this._eventMap || {}; + this._eventMap[cb] = wrappedCallback; + return nativeAddEventListener.apply(this, [nativeEventName, + wrappedCallback]); + }; + + var nativeRemoveEventListener = proto.removeEventListener; + proto.removeEventListener = function(nativeEventName, cb) { + if (nativeEventName !== eventNameToWrap || !this._eventMap + || !this._eventMap[cb]) { + return nativeRemoveEventListener.apply(this, arguments); + } + var unwrappedCb = this._eventMap[cb]; + delete this._eventMap[cb]; + return nativeRemoveEventListener.apply(this, [nativeEventName, + unwrappedCb]); + }; + + Object.defineProperty(proto, 'on' + eventNameToWrap, { + get: function() { + return this['_on' + eventNameToWrap]; + }, + set: function(cb) { + if (this['_on' + eventNameToWrap]) { + this.removeEventListener(eventNameToWrap, + this['_on' + eventNameToWrap]); + delete this['_on' + eventNameToWrap]; + } + if (cb) { + this.addEventListener(eventNameToWrap, + this['_on' + eventNameToWrap] = cb); + } + } + }); +} + +// Utility methods. +module.exports = { + extractVersion: extractVersion, + wrapPeerConnectionEvent: wrapPeerConnectionEvent, + disableLog: function(bool) { + if (typeof bool !== 'boolean') { + return new Error('Argument type: ' + typeof bool + + '. Please use a boolean.'); + } + logDisabled_ = bool; + return (bool) ? 'adapter.js logging disabled' : + 'adapter.js logging enabled'; + }, + + /** + * Disable or enable deprecation warnings + * @param {!boolean} bool set to true to disable warnings. + */ + disableWarnings: function(bool) { + if (typeof bool !== 'boolean') { + return new Error('Argument type: ' + typeof bool + + '. Please use a boolean.'); + } + deprecationWarnings_ = !bool; + return 'adapter.js deprecation warnings ' + (bool ? 'disabled' : 'enabled'); + }, + + log: function() { + if (typeof window === 'object') { + if (logDisabled_) { + return; + } + if (typeof console !== 'undefined' && typeof console.log === 'function') { + console.log.apply(console, arguments); + } + } + }, + + /** + * Shows a deprecation warning suggesting the modern and spec-compatible API. + */ + deprecated: function(oldMethod, newMethod) { + if (!deprecationWarnings_) { + return; + } + console.warn(oldMethod + ' is deprecated, please use ' + newMethod + + ' instead.'); + }, + + /** + * Browser detector. + * + * @return {object} result containing browser and version + * properties. + */ + detectBrowser: function(window) { + var navigator = window && window.navigator; + + // Returned result object. + var result = {}; + result.browser = null; + result.version = null; + + // Fail early if it's not a browser + if (typeof window === 'undefined' || !window.navigator) { + result.browser = 'Not a browser.'; + return result; + } + + if (navigator.mozGetUserMedia) { // Firefox. + result.browser = 'firefox'; + result.version = extractVersion(navigator.userAgent, + /Firefox\/(\d+)\./, 1); + } else if (navigator.webkitGetUserMedia) { + // Chrome, Chromium, Webview, Opera. + // Version matches Chrome/WebRTC version. + result.browser = 'chrome'; + result.version = extractVersion(navigator.userAgent, + /Chrom(e|ium)\/(\d+)\./, 2); + } else if (navigator.mediaDevices && + navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)) { // Edge. + result.browser = 'edge'; + result.version = extractVersion(navigator.userAgent, + /Edge\/(\d+).(\d+)$/, 2); + } else if (navigator.mediaDevices && + navigator.userAgent.match(/AppleWebKit\/(\d+)\./)) { // Safari. + result.browser = 'safari'; + result.version = extractVersion(navigator.userAgent, + /AppleWebKit\/(\d+)\./, 1); + } else { // Default fallthrough: not supported. + result.browser = 'Not a supported browser.'; + return result; + } + + return result; + } +}; + +},{}],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); + 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.4 - git.io/ee + * Unlicense - http://unlicense.org/ + * Oliver Caldwell - http://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; + } +}(this || {})); + +},{}],39:[function(require,module,exports){ +(function (process,global){ +'use strict'; +// Last Updated On: 2017-12-09 2:29:22 PM UTC +// ________________ +// DetectRTC v1.3.6 +// Open-Sourced: https://github.com/muaz-khan/DetectRTC +// -------------------------------------------------- +// Muaz Khan - www.MuazKhan.com +// MIT License - www.WebRTC-Experiment.com/licence +// -------------------------------------------------- +(function () { + var browserFakeUserAgent = 'Fake/5.0 (FakeOS) AppleWebKit/123 (KHTML, like Gecko) Fake/12.3.4567.89 Fake/123.45'; + var isNodejs = typeof process === 'object' && typeof process.versions === 'object' && process.versions.node && /*node-process*/ !process.browser; + if (isNodejs) { + var version = process.versions.node.toString().replace('v', ''); + browserFakeUserAgent = 'Nodejs/' + version + ' (NodeOS) AppleWebKit/' + version + ' (KHTML, like Gecko) Nodejs/' + version + ' Nodejs/' + version; + } + (function (that) { + if (typeof window !== 'undefined') { + return; + } + if (typeof window === 'undefined' && typeof global !== 'undefined') { + global.navigator = { + userAgent: browserFakeUserAgent, + getUserMedia: function () { } + }; + /*global window:true */ + that.window = global; + } + else if (typeof window === 'undefined') { + // window = this; + } + if (typeof location === 'undefined') { + /*global location:true */ + that.location = { + protocol: 'file:', + href: '', + hash: '' + }; + } + if (typeof screen === 'undefined') { + /*global screen:true */ + that.screen = { + width: 0, + height: 0 + }; + } + })(typeof global !== 'undefined' ? global : window); + /*global navigator:true */ + var navigator = window.navigator; + if (typeof navigator !== 'undefined') { + if (typeof navigator.webkitGetUserMedia !== 'undefined') { + navigator.getUserMedia = navigator.webkitGetUserMedia; + } + if (typeof navigator.mozGetUserMedia !== 'undefined') { + navigator.getUserMedia = navigator.mozGetUserMedia; + } + } + else { + navigator = { + getUserMedia: function () { }, + userAgent: browserFakeUserAgent + }; + } + var isMobileDevice = !!(/Android|webOS|iPhone|iPad|iPod|BB10|BlackBerry|IEMobile|Opera Mini|Mobile|mobile/i.test(navigator.userAgent || '')); + var isEdge = navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob); + var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; + var isFirefox = typeof window.InstallTrigger !== 'undefined'; + var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); + var isChrome = !!window.chrome && !isOpera; + var isIE = typeof document !== 'undefined' && !!document.documentMode && !isEdge; + // this one can also be used: + // https://www.websocket.org/js/stuff.js (DetectBrowser.js) + function getBrowserInfo() { + var nVer = navigator.appVersion; + var nAgt = navigator.userAgent; + var browserName = navigator.appName; + var fullVersion = '' + parseFloat(navigator.appVersion); + var majorVersion = parseInt(navigator.appVersion, 10); + var nameOffset, verOffset, ix; + // In Opera, the true version is after 'Opera' or after 'Version' + if (isOpera) { + browserName = 'Opera'; + try { + fullVersion = navigator.userAgent.split('OPR/')[1].split(' ')[0]; + majorVersion = fullVersion.split('.')[0]; + } + catch (e) { + fullVersion = '0.0.0.0'; + majorVersion = 0; + } + } + else if (isIE) { + verOffset = nAgt.indexOf('rv:'); + if (verOffset > 0) { + fullVersion = nAgt.substring(verOffset + 3); + } + else { + verOffset = nAgt.indexOf('MSIE'); + fullVersion = nAgt.substring(verOffset + 5); + } + browserName = 'IE'; + } + else if (isChrome) { + verOffset = nAgt.indexOf('Chrome'); + browserName = 'Chrome'; + fullVersion = nAgt.substring(verOffset + 7); + } + else if (isSafari) { + verOffset = nAgt.indexOf('Safari'); + browserName = 'Safari'; + fullVersion = nAgt.substring(verOffset + 7); + if ((verOffset = nAgt.indexOf('Version')) !== -1) { + fullVersion = nAgt.substring(verOffset + 8); + } + if (navigator.userAgent.indexOf('Version/') !== -1) { + fullVersion = navigator.userAgent.split('Version/')[1].split(' ')[0]; + } + } + else if (isFirefox) { + verOffset = nAgt.indexOf('Firefox'); + browserName = 'Firefox'; + fullVersion = nAgt.substring(verOffset + 8); + } + else if ((nameOffset = nAgt.lastIndexOf(' ') + 1) < (verOffset = nAgt.lastIndexOf('/'))) { + browserName = nAgt.substring(nameOffset, verOffset); + fullVersion = nAgt.substring(verOffset + 1); + if (browserName.toLowerCase() === browserName.toUpperCase()) { + browserName = navigator.appName; + } + } + if (isEdge) { + browserName = 'Edge'; + fullVersion = navigator.userAgent.split('Edge/')[1]; + // fullVersion = parseInt(navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)[2], 10).toString(); + } + // trim the fullVersion string at semicolon/space/bracket if present + if ((ix = fullVersion.search(/[; \)]/)) !== -1) { + fullVersion = fullVersion.substring(0, ix); + } + majorVersion = parseInt('' + fullVersion, 10); + if (isNaN(majorVersion)) { + fullVersion = '' + parseFloat(navigator.appVersion); + majorVersion = parseInt(navigator.appVersion, 10); + } + return { + fullVersion: fullVersion, + version: majorVersion, + name: browserName, + isPrivateBrowsing: false + }; + } + // via: https://gist.github.com/cou929/7973956 + function retry(isDone, next) { + var currentTrial = 0, maxRetry = 50, interval = 10, isTimeout = false; + var id = window.setInterval(function () { + if (isDone()) { + window.clearInterval(id); + next(isTimeout); + } + if (currentTrial++ > maxRetry) { + window.clearInterval(id); + isTimeout = true; + next(isTimeout); + } + }, 10); + } + function isIE10OrLater(userAgent) { + var ua = userAgent.toLowerCase(); + if (ua.indexOf('msie') === 0 && ua.indexOf('trident') === 0) { + return false; + } + var match = /(?:msie|rv:)\s?([\d\.]+)/.exec(ua); + if (match && parseInt(match[1], 10) >= 10) { + return true; + } + return false; + } + function detectPrivateMode(callback) { + var isPrivate; + try { + if (window.webkitRequestFileSystem) { + window.webkitRequestFileSystem(window.TEMPORARY, 1, function () { + isPrivate = false; + }, function (e) { + isPrivate = true; + }); + } + else if (window.indexedDB && /Firefox/.test(window.navigator.userAgent)) { + var db; + try { + db = window.indexedDB.open('test'); + db.onerror = function () { + return true; + }; + } + catch (e) { + isPrivate = true; + } + if (typeof isPrivate === 'undefined') { + retry(function isDone() { + return db.readyState === 'done' ? true : false; + }, function next(isTimeout) { + if (!isTimeout) { + isPrivate = db.result ? false : true; + } + }); + } + } + else if (isIE10OrLater(window.navigator.userAgent)) { + isPrivate = false; + try { + if (!window.indexedDB) { + isPrivate = true; + } + } + catch (e) { + isPrivate = true; + } + } + else if (window.localStorage && /Safari/.test(window.navigator.userAgent)) { + try { + window.localStorage.setItem('test', 1); + } + catch (e) { + isPrivate = true; + } + if (typeof isPrivate === 'undefined') { + isPrivate = false; + window.localStorage.removeItem('test'); + } + } + } + catch (e) { + isPrivate = false; + } + retry(function isDone() { + return typeof isPrivate !== 'undefined' ? true : false; + }, function next(isTimeout) { + callback(isPrivate); + }); + } + var isMobile = { + Android: function () { + return navigator.userAgent.match(/Android/i); + }, + BlackBerry: function () { + return navigator.userAgent.match(/BlackBerry|BB10/i); + }, + iOS: function () { + return navigator.userAgent.match(/iPhone|iPad|iPod/i); + }, + Opera: function () { + return navigator.userAgent.match(/Opera Mini/i); + }, + Windows: function () { + return navigator.userAgent.match(/IEMobile/i); + }, + any: function () { + return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows()); + }, + getOsName: function () { + var osName = 'Unknown OS'; + if (isMobile.Android()) { + osName = 'Android'; + } + if (isMobile.BlackBerry()) { + osName = 'BlackBerry'; + } + if (isMobile.iOS()) { + osName = 'iOS'; + } + if (isMobile.Opera()) { + osName = 'Opera Mini'; + } + if (isMobile.Windows()) { + osName = 'Windows'; + } + return osName; + } + }; + // via: http://jsfiddle.net/ChristianL/AVyND/ + function detectDesktopOS() { + var unknown = '-'; + var nVer = navigator.appVersion; + var nAgt = navigator.userAgent; + var os = unknown; + var clientStrings = [{ + s: 'Windows 10', + r: /(Windows 10.0|Windows NT 10.0)/ + }, { + s: 'Windows 8.1', + r: /(Windows 8.1|Windows NT 6.3)/ + }, { + s: 'Windows 8', + r: /(Windows 8|Windows NT 6.2)/ + }, { + s: 'Windows 7', + r: /(Windows 7|Windows NT 6.1)/ + }, { + s: 'Windows Vista', + r: /Windows NT 6.0/ + }, { + s: 'Windows Server 2003', + r: /Windows NT 5.2/ + }, { + s: 'Windows XP', + r: /(Windows NT 5.1|Windows XP)/ + }, { + s: 'Windows 2000', + r: /(Windows NT 5.0|Windows 2000)/ + }, { + s: 'Windows ME', + r: /(Win 9x 4.90|Windows ME)/ + }, { + s: 'Windows 98', + r: /(Windows 98|Win98)/ + }, { + s: 'Windows 95', + r: /(Windows 95|Win95|Windows_95)/ + }, { + s: 'Windows NT 4.0', + r: /(Windows NT 4.0|WinNT4.0|WinNT|Windows NT)/ + }, { + s: 'Windows CE', + r: /Windows CE/ + }, { + s: 'Windows 3.11', + r: /Win16/ + }, { + s: 'Android', + r: /Android/ + }, { + s: 'Open BSD', + r: /OpenBSD/ + }, { + s: 'Sun OS', + r: /SunOS/ + }, { + s: 'Linux', + r: /(Linux|X11)/ + }, { + s: 'iOS', + r: /(iPhone|iPad|iPod)/ + }, { + s: 'Mac OS X', + r: /Mac OS X/ + }, { + s: 'Mac OS', + r: /(MacPPC|MacIntel|Mac_PowerPC|Macintosh)/ + }, { + s: 'QNX', + r: /QNX/ + }, { + s: 'UNIX', + r: /UNIX/ + }, { + s: 'BeOS', + r: /BeOS/ + }, { + s: 'OS/2', + r: /OS\/2/ + }, { + s: 'Search Bot', + r: /(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/ + }]; + for (var i = 0, cs; cs = clientStrings[i]; i++) { + if (cs.r.test(nAgt)) { + os = cs.s; + break; + } + } + var osVersion = unknown; + if (/Windows/.test(os)) { + if (/Windows (.*)/.test(os)) { + osVersion = /Windows (.*)/.exec(os)[1]; + } + os = 'Windows'; + } + switch (os) { + case 'Mac OS X': + if (/Mac OS X (10[\.\_\d]+)/.test(nAgt)) { + osVersion = /Mac OS X (10[\.\_\d]+)/.exec(nAgt)[1]; + } + break; + case 'Android': + if (/Android ([\.\_\d]+)/.test(nAgt)) { + osVersion = /Android ([\.\_\d]+)/.exec(nAgt)[1]; + } + break; + case 'iOS': + if (/OS (\d+)_(\d+)_?(\d+)?/.test(nAgt)) { + osVersion = /OS (\d+)_(\d+)_?(\d+)?/.exec(nVer); + osVersion = osVersion[1] + '.' + osVersion[2] + '.' + (osVersion[3] | 0); + } + break; + } + return { + osName: os, + osVersion: osVersion + }; + } + var osName = 'Unknown OS'; + var osVersion = 'Unknown OS Version'; + function getAndroidVersion(ua) { + ua = (ua || navigator.userAgent).toLowerCase(); + var match = ua.match(/android\s([0-9\.]*)/); + return match ? match[1] : false; + } + var osInfo = detectDesktopOS(); + if (osInfo && osInfo.osName && osInfo.osName != '-') { + osName = osInfo.osName; + osVersion = osInfo.osVersion; + } + else if (isMobile.any()) { + osName = isMobile.getOsName(); + if (osName == 'Android') { + osVersion = getAndroidVersion(); + } + } + var isNodejs = typeof process === 'object' && typeof process.versions === 'object' && process.versions.node; + if (osName === 'Unknown OS' && isNodejs) { + osName = 'Nodejs'; + osVersion = process.versions.node.toString().replace('v', ''); + } + var isCanvasSupportsStreamCapturing = false; + var isVideoSupportsStreamCapturing = false; + ['captureStream', 'mozCaptureStream', 'webkitCaptureStream'].forEach(function (item) { + if (typeof document === 'undefined' || typeof document.createElement !== 'function') { + return; + } + if (!isCanvasSupportsStreamCapturing && item in document.createElement('canvas')) { + isCanvasSupportsStreamCapturing = true; + } + if (!isVideoSupportsStreamCapturing && item in document.createElement('video')) { + isVideoSupportsStreamCapturing = true; + } + }); + // via: https://github.com/diafygi/webrtc-ips + function DetectLocalIPAddress(callback, stream) { + if (!DetectRTC.isWebRTCSupported) { + return; + } + getIPs(function (ip) { + if (ip.match(/^(192\.168\.|169\.254\.|10\.|172\.(1[6-9]|2\d|3[01]))/)) { + callback('Local: ' + ip); + } + else { + callback('Public: ' + ip); + } + }, stream); + } + function getIPs(callback, stream) { + if (typeof document === 'undefined' || typeof document.getElementById !== 'function') { + return; + } + var ipDuplicates = {}; + var RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; + if (!RTCPeerConnection) { + var iframe = document.getElementById('iframe'); + if (!iframe) { + return; + } + var win = iframe.contentWindow; + RTCPeerConnection = win.RTCPeerConnection || win.mozRTCPeerConnection || win.webkitRTCPeerConnection; + } + if (!RTCPeerConnection) { + return; + } + var peerConfig = null; + if (DetectRTC.browser === 'Chrome' && DetectRTC.browser.version < 58) { + // todo: add support for older Opera + peerConfig = { + optional: [{ + RtpDataChannels: true + }] + }; + } + var servers = { + iceServers: [{ + urls: 'stun:stun.l.google.com:19302' + }] + }; + var pc = new RTCPeerConnection(servers, peerConfig); + if (stream) { + if (pc.addStream) { + pc.addStream(stream); + } + else if (pc.addTrack && stream.getTracks()[0]) { + pc.addTrack(stream.getTracks()[0], stream); + } + } + function handleCandidate(candidate) { + var ipRegex = /([0-9]{1,3}(\.[0-9]{1,3}){3})/; + var match = ipRegex.exec(candidate); + if (!match) { + return; + } + var ipAddress = match[1]; + if (ipDuplicates[ipAddress] === undefined) { + callback(ipAddress); + } + ipDuplicates[ipAddress] = true; + } + // listen for candidate events + pc.onicecandidate = function (ice) { + if (ice.candidate) { + handleCandidate(ice.candidate.candidate); + } + }; + // create data channel + if (!stream) { + try { + pc.createDataChannel('sctp', {}); + } + catch (e) { } + } + // create an offer sdp + if (DetectRTC.isPromisesSupported) { + pc.createOffer().then(function (result) { + pc.setLocalDescription(result).then(afterCreateOffer); + }); + } + else { + pc.createOffer(function (result) { + pc.setLocalDescription(result, afterCreateOffer, function () { }); + }, function () { }); + } + function afterCreateOffer() { + var lines = pc.localDescription.sdp.split('\n'); + lines.forEach(function (line) { + if (line.indexOf('a=candidate:') === 0) { + handleCandidate(line); + } + }); + } + } + var MediaDevices = []; + var audioInputDevices = []; + var audioOutputDevices = []; + var videoInputDevices = []; + if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) { + // Firefox 38+ seems having support of enumerateDevices + // Thanks @xdumaine/enumerateDevices + navigator.enumerateDevices = function (callback) { + var enumerateDevices = navigator.mediaDevices.enumerateDevices(); + if (enumerateDevices && enumerateDevices.then) { + navigator.mediaDevices.enumerateDevices().then(callback).catch(function () { + callback([]); + }); + } + else { + callback([]); + } + }; + } + // Media Devices detection + var canEnumerate = false; + /*global MediaStreamTrack:true */ + if (typeof MediaStreamTrack !== 'undefined' && 'getSources' in MediaStreamTrack) { + canEnumerate = true; + } + else if (navigator.mediaDevices && !!navigator.mediaDevices.enumerateDevices) { + canEnumerate = true; + } + var hasMicrophone = false; + var hasSpeakers = false; + var hasWebcam = false; + var isWebsiteHasMicrophonePermissions = false; + var isWebsiteHasWebcamPermissions = false; + // http://dev.w3.org/2011/webrtc/editor/getusermedia.html#mediadevices + function checkDeviceSupport(callback) { + if (!canEnumerate) { + if (callback) { + callback(); + } + return; + } + if (!navigator.enumerateDevices && window.MediaStreamTrack && window.MediaStreamTrack.getSources) { + navigator.enumerateDevices = window.MediaStreamTrack.getSources.bind(window.MediaStreamTrack); + } + if (!navigator.enumerateDevices && navigator.enumerateDevices) { + navigator.enumerateDevices = navigator.enumerateDevices.bind(navigator); + } + if (!navigator.enumerateDevices) { + if (callback) { + callback(); + } + return; + } + MediaDevices = []; + audioInputDevices = []; + audioOutputDevices = []; + videoInputDevices = []; + hasMicrophone = false; + hasSpeakers = false; + hasWebcam = false; + isWebsiteHasMicrophonePermissions = false; + isWebsiteHasWebcamPermissions = false; + // to prevent duplication + var alreadyUsedDevices = {}; + navigator.enumerateDevices(function (devices) { + devices.forEach(function (_device) { + var device = {}; + for (var d in _device) { + try { + if (typeof _device[d] !== 'function') { + device[d] = _device[d]; + } + } + catch (e) { } + } + if (alreadyUsedDevices[device.deviceId + device.label + device.kind]) { + return; + } + // if it is MediaStreamTrack.getSources + if (device.kind === 'audio') { + device.kind = 'audioinput'; + } + if (device.kind === 'video') { + device.kind = 'videoinput'; + } + if (!device.deviceId) { + device.deviceId = device.id; + } + if (!device.id) { + device.id = device.deviceId; + } + if (!device.label) { + device.isCustomLabel = true; + if (device.kind === 'videoinput') { + device.label = 'Camera ' + (videoInputDevices.length + 1); + } + else if (device.kind === 'audioinput') { + device.label = 'Microphone ' + (audioInputDevices.length + 1); + } + else if (device.kind === 'audiooutput') { + device.label = 'Speaker ' + (audioOutputDevices.length + 1); + } + else { + device.label = 'Please invoke getUserMedia once.'; + } + if (typeof DetectRTC !== 'undefined' && DetectRTC.browser.isChrome && DetectRTC.browser.version >= 46 && !/^(https:|chrome-extension:)$/g.test(location.protocol || '')) { + if (typeof document !== 'undefined' && typeof document.domain === 'string' && document.domain.search && document.domain.search(/localhost|127.0./g) === -1) { + device.label = 'HTTPs is required to get label of this ' + device.kind + ' device.'; + } + } + } + else { + // Firefox on Android still returns empty label + if (device.kind === 'videoinput' && !isWebsiteHasWebcamPermissions) { + isWebsiteHasWebcamPermissions = true; + } + if (device.kind === 'audioinput' && !isWebsiteHasMicrophonePermissions) { + isWebsiteHasMicrophonePermissions = true; + } + } + if (device.kind === 'audioinput') { + hasMicrophone = true; + if (audioInputDevices.indexOf(device) === -1) { + audioInputDevices.push(device); + } + } + if (device.kind === 'audiooutput') { + hasSpeakers = true; + if (audioOutputDevices.indexOf(device) === -1) { + audioOutputDevices.push(device); + } + } + if (device.kind === 'videoinput') { + hasWebcam = true; + if (videoInputDevices.indexOf(device) === -1) { + videoInputDevices.push(device); + } + } + // there is no 'videoouput' in the spec. + MediaDevices.push(device); + alreadyUsedDevices[device.deviceId + device.label + device.kind] = device; + }); + if (typeof DetectRTC !== 'undefined') { + // to sync latest outputs + DetectRTC.MediaDevices = MediaDevices; + DetectRTC.hasMicrophone = hasMicrophone; + DetectRTC.hasSpeakers = hasSpeakers; + DetectRTC.hasWebcam = hasWebcam; + DetectRTC.isWebsiteHasWebcamPermissions = isWebsiteHasWebcamPermissions; + DetectRTC.isWebsiteHasMicrophonePermissions = isWebsiteHasMicrophonePermissions; + DetectRTC.audioInputDevices = audioInputDevices; + DetectRTC.audioOutputDevices = audioOutputDevices; + DetectRTC.videoInputDevices = videoInputDevices; + } + if (callback) { + callback(); + } + }); + } + var DetectRTC = window.DetectRTC || {}; + // ---------- + // DetectRTC.browser.name || DetectRTC.browser.version || DetectRTC.browser.fullVersion + DetectRTC.browser = getBrowserInfo(); + detectPrivateMode(function (isPrivateBrowsing) { + DetectRTC.browser.isPrivateBrowsing = !!isPrivateBrowsing; + }); + // DetectRTC.isChrome || DetectRTC.isFirefox || DetectRTC.isEdge + DetectRTC.browser['is' + DetectRTC.browser.name] = true; + // ----------- + DetectRTC.osName = osName; + DetectRTC.osVersion = osVersion; + var isNodeWebkit = typeof process === 'object' && typeof process.versions === 'object' && process.versions['node-webkit']; + // --------- Detect if system supports WebRTC 1.0 or WebRTC 1.1. + var isWebRTCSupported = false; + ['RTCPeerConnection', 'webkitRTCPeerConnection', 'mozRTCPeerConnection', 'RTCIceGatherer'].forEach(function (item) { + if (isWebRTCSupported) { + return; + } + if (item in window) { + isWebRTCSupported = true; + } + }); + DetectRTC.isWebRTCSupported = isWebRTCSupported; + //------- + DetectRTC.isORTCSupported = typeof RTCIceGatherer !== 'undefined'; + // --------- Detect if WebAudio API are supported + var webAudio = { + isSupported: false, + isCreateMediaStreamSourceSupported: false + }; + ['AudioContext', 'webkitAudioContext', 'mozAudioContext', 'msAudioContext'].forEach(function (item) { + if (webAudio.isSupported) { + return; + } + if (item in window) { + webAudio.isSupported = true; + if (window[item] && 'createMediaStreamSource' in window[item].prototype) { + webAudio.isCreateMediaStreamSourceSupported = true; + } + } + }); + DetectRTC.isAudioContextSupported = webAudio.isSupported; + DetectRTC.isCreateMediaStreamSourceSupported = webAudio.isCreateMediaStreamSourceSupported; + // ---------- Detect if SCTP/RTP channels are supported. + var isRtpDataChannelsSupported = false; + if (DetectRTC.browser.isChrome && DetectRTC.browser.version > 31) { + isRtpDataChannelsSupported = true; + } + DetectRTC.isRtpDataChannelsSupported = isRtpDataChannelsSupported; + var isSCTPSupportd = false; + if (DetectRTC.browser.isFirefox && DetectRTC.browser.version > 28) { + isSCTPSupportd = true; + } + else if (DetectRTC.browser.isChrome && DetectRTC.browser.version > 25) { + isSCTPSupportd = true; + } + else if (DetectRTC.browser.isOpera && DetectRTC.browser.version >= 11) { + isSCTPSupportd = true; + } + DetectRTC.isSctpDataChannelsSupported = isSCTPSupportd; + // --------- + DetectRTC.isMobileDevice = isMobileDevice; // "isMobileDevice" boolean is defined in "getBrowserInfo.js" + // ------ + var isGetUserMediaSupported = false; + if (navigator.getUserMedia) { + isGetUserMediaSupported = true; + } + else if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { + isGetUserMediaSupported = true; + } + if (DetectRTC.browser.isChrome && DetectRTC.browser.version >= 46 && !/^(https:|chrome-extension:)$/g.test(location.protocol || '')) { + if (typeof document !== 'undefined' && typeof document.domain === 'string' && document.domain.search && document.domain.search(/localhost|127.0./g) === -1) { + isGetUserMediaSupported = 'Requires HTTPs'; + } + } + if (DetectRTC.osName === 'Nodejs') { + isGetUserMediaSupported = false; + } + DetectRTC.isGetUserMediaSupported = isGetUserMediaSupported; + var displayResolution = ''; + if (screen.width) { + var width = (screen.width) ? screen.width : ''; + var height = (screen.height) ? screen.height : ''; + displayResolution += '' + width + ' x ' + height; + } + DetectRTC.displayResolution = displayResolution; + function getAspectRatio(w, h) { + function gcd(a, b) { + return (b == 0) ? a : gcd(b, a % b); + } + var r = gcd(w, h); + return (w / r) / (h / r); + } + DetectRTC.displayAspectRatio = getAspectRatio(screen.width, screen.height).toFixed(2); + // ---------- + DetectRTC.isCanvasSupportsStreamCapturing = isCanvasSupportsStreamCapturing; + DetectRTC.isVideoSupportsStreamCapturing = isVideoSupportsStreamCapturing; + if (DetectRTC.browser.name == 'Chrome' && DetectRTC.browser.version >= 53) { + if (!DetectRTC.isCanvasSupportsStreamCapturing) { + DetectRTC.isCanvasSupportsStreamCapturing = 'Requires chrome flag: enable-experimental-web-platform-features'; + } + if (!DetectRTC.isVideoSupportsStreamCapturing) { + DetectRTC.isVideoSupportsStreamCapturing = 'Requires chrome flag: enable-experimental-web-platform-features'; + } + } + // ------ + DetectRTC.DetectLocalIPAddress = DetectLocalIPAddress; + DetectRTC.isWebSocketsSupported = 'WebSocket' in window && 2 === window.WebSocket.CLOSING; + DetectRTC.isWebSocketsBlocked = !DetectRTC.isWebSocketsSupported; + if (DetectRTC.osName === 'Nodejs') { + DetectRTC.isWebSocketsSupported = true; + DetectRTC.isWebSocketsBlocked = false; + } + DetectRTC.checkWebSocketsSupport = function (callback) { + callback = callback || function () { }; + try { + var starttime; + var websocket = new WebSocket('wss://echo.websocket.org:443/'); + websocket.onopen = function () { + DetectRTC.isWebSocketsBlocked = false; + starttime = (new Date).getTime(); + websocket.send('ping'); + }; + websocket.onmessage = function () { + DetectRTC.WebsocketLatency = (new Date).getTime() - starttime + 'ms'; + callback(); + websocket.close(); + websocket = null; + }; + websocket.onerror = function () { + DetectRTC.isWebSocketsBlocked = true; + callback(); + }; + } + catch (e) { + DetectRTC.isWebSocketsBlocked = true; + callback(); + } + }; + // ------- + DetectRTC.load = function (callback) { + callback = callback || function () { }; + checkDeviceSupport(callback); + }; + // check for microphone/camera support! + if (typeof checkDeviceSupport === 'function') { + // checkDeviceSupport(); + } + if (typeof MediaDevices !== 'undefined') { + DetectRTC.MediaDevices = MediaDevices; + } + else { + DetectRTC.MediaDevices = []; + } + DetectRTC.hasMicrophone = hasMicrophone; + DetectRTC.hasSpeakers = hasSpeakers; + DetectRTC.hasWebcam = hasWebcam; + DetectRTC.isWebsiteHasWebcamPermissions = isWebsiteHasWebcamPermissions; + DetectRTC.isWebsiteHasMicrophonePermissions = isWebsiteHasMicrophonePermissions; + DetectRTC.audioInputDevices = audioInputDevices; + DetectRTC.audioOutputDevices = audioOutputDevices; + DetectRTC.videoInputDevices = videoInputDevices; + // ------ + var isSetSinkIdSupported = false; + if (typeof document !== 'undefined' && typeof document.createElement === 'function' && 'setSinkId' in document.createElement('video')) { + isSetSinkIdSupported = true; + } + DetectRTC.isSetSinkIdSupported = isSetSinkIdSupported; + // ----- + var isRTPSenderReplaceTracksSupported = false; + if (DetectRTC.browser.isFirefox && typeof mozRTCPeerConnection !== 'undefined' /*&& DetectRTC.browser.version > 39*/) { + /*global mozRTCPeerConnection:true */ + if ('getSenders' in mozRTCPeerConnection.prototype) { + isRTPSenderReplaceTracksSupported = true; + } + } + else if (DetectRTC.browser.isChrome && typeof webkitRTCPeerConnection !== 'undefined') { + /*global webkitRTCPeerConnection:true */ + if ('getSenders' in webkitRTCPeerConnection.prototype) { + isRTPSenderReplaceTracksSupported = true; + } + } + DetectRTC.isRTPSenderReplaceTracksSupported = isRTPSenderReplaceTracksSupported; + //------ + var isRemoteStreamProcessingSupported = false; + if (DetectRTC.browser.isFirefox && DetectRTC.browser.version > 38) { + isRemoteStreamProcessingSupported = true; + } + DetectRTC.isRemoteStreamProcessingSupported = isRemoteStreamProcessingSupported; + //------- + var isApplyConstraintsSupported = false; + /*global MediaStreamTrack:true */ + if (typeof MediaStreamTrack !== 'undefined' && 'applyConstraints' in MediaStreamTrack.prototype) { + isApplyConstraintsSupported = true; + } + DetectRTC.isApplyConstraintsSupported = isApplyConstraintsSupported; + //------- + var isMultiMonitorScreenCapturingSupported = false; + if (DetectRTC.browser.isFirefox && DetectRTC.browser.version >= 43) { + // version 43 merely supports platforms for multi-monitors + // version 44 will support exact multi-monitor selection i.e. you can select any monitor for screen capturing. + isMultiMonitorScreenCapturingSupported = true; + } + DetectRTC.isMultiMonitorScreenCapturingSupported = isMultiMonitorScreenCapturingSupported; + DetectRTC.isPromisesSupported = !!('Promise' in window); + if (typeof DetectRTC === 'undefined') { + window.DetectRTC = {}; + } + var MediaStream = window.MediaStream; + if (typeof MediaStream === 'undefined' && typeof webkitMediaStream !== 'undefined') { + MediaStream = webkitMediaStream; + } + if (typeof MediaStream !== 'undefined') { + DetectRTC.MediaStream = Object.keys(MediaStream.prototype); + } + else + DetectRTC.MediaStream = false; + if (typeof MediaStreamTrack !== 'undefined') { + DetectRTC.MediaStreamTrack = Object.keys(MediaStreamTrack.prototype); + } + else + DetectRTC.MediaStreamTrack = false; + var RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; + if (typeof RTCPeerConnection !== 'undefined') { + DetectRTC.RTCPeerConnection = Object.keys(RTCPeerConnection.prototype); + } + else + DetectRTC.RTCPeerConnection = false; + window.DetectRTC = DetectRTC; + if (typeof module !== 'undefined' /* && !!module.exports*/) { + module.exports = DetectRTC; + } + if (typeof define === 'function' && define.amd) { + define('DetectRTC', [], function () { + return DetectRTC; + }); + } +})(); + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"_process":9}],40:[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]; + // Check it's empty + 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; + +},{}],41:[function(require,module,exports){ +/* + * (C) Copyright 2014 Kurento (http://kurento.org/) + * + * 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. + * + */ +var JsonRpcClient = require('./jsonrpcclient'); +exports.JsonRpcClient = JsonRpcClient; + +},{"./jsonrpcclient":42}],42:[function(require,module,exports){ +/* + * (C) Copyright 2014 Kurento (http://kurento.org/) + * + * 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. + * + */ +var RpcBuilder = require('../'); +var WebSocketWithReconnection = require('./transports/webSocketWithReconnection'); +Date.now = Date.now || function () { + return +new Date; +}; +var PING_INTERVAL = 5000; +var RECONNECTING = 'RECONNECTING'; +var CONNECTED = 'CONNECTED'; +var DISCONNECTED = 'DISCONNECTED'; +var Logger = console; +/** + * + * heartbeat: interval in ms for each heartbeat message, + * sendCloseMessage : true / false, before closing the connection, it sends a closeSession message + *
+ * ws : {
+ * 	uri : URI to conntect to,
+ *  useSockJS : true (use SockJS) / false (use WebSocket) by default,
+ * 	onconnected : callback method to invoke when connection is successful,
+ * 	ondisconnect : callback method to invoke when the connection is lost,
+ * 	onreconnecting : callback method to invoke when the client is reconnecting,
+ * 	onreconnected : callback method to invoke when the client succesfully reconnects,
+ * 	onerror : callback method to invoke when there is an error
+ * },
+ * rpc : {
+ * 	requestTimeout : timeout for a request,
+ * 	sessionStatusChanged: callback method for changes in session status,
+ * 	mediaRenegotiation: mediaRenegotiation
+ * }
+ * 
+ */ +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; + } + 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; + enabledPings = true; + updateNotReconnectIfLessThan(); + usePing(); + 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; + 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) { + if (method !== 'ping') { + Logger.debug('Request: method:' + method + " params:" + JSON.stringify(params)); + } + 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"); + } + } + /* + * If configuration.hearbeat has any value, the ping-pong will work with the interval + * of configuration.hearbeat + */ + function usePing() { + if (!pingPongStarted) { + Logger.debug("Starting ping (if configured)"); + pingPongStarted = true; + if (configuration.heartbeat != undefined) { + pingInterval = setInterval(sendPing, configuration.heartbeat); + sendPing(); + } + } + } + this.close = function () { + Logger.debug("Closing jsonRpcClient explicitly by client"); + if (pingInterval != undefined) { + Logger.debug("Clearing ping interval"); + clearInterval(pingInterval); + } + pingPongStarted = false; + enabledPings = false; + if (configuration.sendCloseMessage) { + Logger.debug("Sending close message"); + this.send('closeSession', null, function (error, result) { + if (error) { + Logger.error("Error sending close message: " + JSON.stringify(error)); + } + ws.close(); + }); + } + else { + ws.close(); + } + }; + // This method is only for testing + this.forceClose = function (millis) { + ws.forceClose(millis); + }; + this.reconnect = function () { + ws.reconnectWs(); + }; +} +module.exports = JsonRpcClient; + +},{"../":45,"./transports/webSocketWithReconnection":44}],43:[function(require,module,exports){ +/* + * (C) Copyright 2014 Kurento (http://kurento.org/) + * + * 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. + * + */ +var WebSocketWithReconnection = require('./webSocketWithReconnection'); +exports.WebSocketWithReconnection = WebSocketWithReconnection; + +},{"./webSocketWithReconnection":44}],44:[function(require,module,exports){ +(function (global){ +/* + * (C) Copyright 2013-2015 Kurento (http://kurento.org/) + * + * 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. + */ +"use strict"; +var BrowserWebSocket = global.WebSocket || global.MozWebSocket; +var Logger = console; +/** + * Get either the `WebSocket` or `MozWebSocket` globals + * in the browser or try to resolve WebSocket-compatible + * interface exposed by `ws` for Node-like environment. + */ +/*var WebSocket = BrowserWebSocket; +if (!WebSocket && typeof window === 'undefined') { + try { + WebSocket = require('ws'); + } catch (e) { } +}*/ +//var SockJS = require('sockjs-client'); +var MAX_RETRIES = 2000; // Forever... +var RETRY_TIME_MS = 3000; // FIXME: Implement exponential wait times... +var CONNECTING = 0; +var OPEN = 1; +var CLOSING = 2; +var CLOSED = 3; +/* +config = { + uri : wsUri, + useSockJS : true (use SockJS) / false (use WebSocket) by default, + onconnected : callback method to invoke when connection is successful, + ondisconnect : callback method to invoke when the connection is lost, + onreconnecting : callback method to invoke when the client is reconnecting, + onreconnected : callback method to invoke when the client succesfully reconnects, + }; +*/ +function WebSocketWithReconnection(config) { + var closing = false; + var registerMessageHandler; + var wsUri = config.uri; + var useSockJS = config.useSockJS; + var reconnecting = false; + var forcingDisconnection = false; + var ws; + if (useSockJS) { + ws = new SockJS(wsUri); + } + else { + ws = new WebSocket(wsUri); + } + ws.onopen = function () { + logConnected(ws, 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); + } + }; + function logConnected(ws, wsUri) { + try { + Logger.debug("WebSocket connected to " + wsUri); + } + catch (e) { + Logger.error(e); + } + } + var reconnectionOnClose = function () { + if (ws.readyState === CLOSED) { + if (closing) { + Logger.debug("Connection closed by user"); + } + else { + Logger.debug("Connection closed unexpectecly. Reconnecting..."); + reconnectToSameUri(MAX_RETRIES, 1); + } + } + else { + Logger.debug("Close callback from previous websocket. Ignoring it"); + } + }; + ws.onclose = reconnectionOnClose; + function reconnectToSameUri(maxRetries, numRetries) { + Logger.debug("reconnectToSameUri (attempt #" + numRetries + ", max=" + maxRetries + ")"); + if (numRetries === 1) { + if (reconnecting) { + Logger.warn("Trying to reconnectToNewUri when reconnecting... Ignoring this reconnection."); + return; + } + else { + reconnecting = true; + } + if (config.onreconnecting) { + config.onreconnecting(); + } + } + if (forcingDisconnection) { + reconnectToNewUri(maxRetries, numRetries, wsUri); + } + else { + if (config.newWsUriOnReconnection) { + config.newWsUriOnReconnection(function (error, newWsUri) { + if (error) { + Logger.debug(error); + setTimeout(function () { + reconnectToSameUri(maxRetries, numRetries + 1); + }, RETRY_TIME_MS); + } + else { + reconnectToNewUri(maxRetries, numRetries, newWsUri); + } + }); + } + else { + reconnectToNewUri(maxRetries, numRetries, wsUri); + } + } + } + // TODO Test retries. How to force not connection? + function reconnectToNewUri(maxRetries, numRetries, reconnectWsUri) { + Logger.debug("Reconnection attempt #" + numRetries); + ws.close(); + wsUri = reconnectWsUri || wsUri; + var newWs; + if (useSockJS) { + newWs = new SockJS(wsUri); + } + else { + newWs = new WebSocket(wsUri); + } + newWs.onopen = function () { + Logger.debug("Reconnected after " + numRetries + " attempts..."); + logConnected(newWs, wsUri); + reconnecting = false; + registerMessageHandler(); + if (config.onreconnected()) { + config.onreconnected(); + } + newWs.onclose = reconnectionOnClose; + }; + var onErrorOrClose = function (error) { + Logger.warn("Reconnection error: ", error); + if (numRetries === maxRetries) { + if (config.ondisconnect) { + config.ondisconnect(); + } + } + else { + setTimeout(function () { + reconnectToSameUri(maxRetries, numRetries + 1); + }, RETRY_TIME_MS); + } + }; + newWs.onerror = onErrorOrClose; + ws = newWs; + } + this.close = function () { + closing = true; + ws.close(); + }; + // This method is only for testing + this.forceClose = function (millis) { + Logger.debug("Testing: Force WebSocket close"); + if (millis) { + Logger.debug("Testing: Change wsUri for " + millis + " millis to simulate net failure"); + var goodWsUri = wsUri; + wsUri = "wss://21.234.12.34.4:443/"; + forcingDisconnection = true; + setTimeout(function () { + Logger.debug("Testing: Recover good wsUri " + goodWsUri); + wsUri = goodWsUri; + forcingDisconnection = false; + }, millis); + } + ws.close(); + }; + this.reconnectWs = function () { + Logger.debug("reconnectWs"); + reconnectToSameUri(MAX_RETRIES, 1, wsUri); + }; + this.send = function (message) { + ws.send(message); + }; + this.addEventListener = function (type, callback) { + registerMessageHandler = function () { + ws.addEventListener(type, callback); + }; + registerMessageHandler(); + }; +} +module.exports = WebSocketWithReconnection; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],45:[function(require,module,exports){ +/* + * (C) Copyright 2014 Kurento (http://kurento.org/) + * + * 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. + * + */ +var defineProperty_IE8 = false; +if (Object.defineProperty) { + try { + Object.defineProperty({}, "x", {}); + } + catch (e) { + defineProperty_IE8 = true; + } +} +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind +if (!Function.prototype.bind) { + Function.prototype.bind = function (oThis) { + if (typeof this !== 'function') { + // closest thing possible to the ECMAScript 5 + // internal IsCallable 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; + // Transport as a function + if (transport instanceof Function) + return { send: transport }; + // WebSocket & DataChannel + if (transport.send instanceof Function) + return transport; + // Message API (Inter-window & WebWorker) + if (transport.postMessage instanceof Function) { + transport.send = transport.postMessage; + return transport; + } + // Stream API + if (transport.write instanceof Function) { + transport.send = transport.write; + return transport; + } + // Transports that only can receive messages, but not send + if (transport.onmessage !== undefined) + return; + if (transport.pause instanceof Function) + return; + throw new SyntaxError("Transport is not a function nor a valid object"); +} +; +/** + * Representation of a RPC notification + * + * @class + * + * @constructor + * + * @param {String} method -method of the notification + * @param params - parameters of the notification + */ +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 }); + } +} +; +/** + * @class + * + * @constructor + * + * @param {object} packer + * + * @param {object} [options] + * + * @param {object} [transport] + * + * @param {Function} [onRequest] + */ +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) { + // Remove listener from old transport + if (transport) { + // W3C transports + if (transport.removeEventListener) + transport.removeEventListener('message', transportMessage); + else if (transport.removeListener) + transport.removeListener('data', transportMessage); + } + ; + // Set listener on new transport + if (value) { + // W3C transports + 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 = {}; + /** + * Store the response to prevent to process duplicate request later + */ + function storeResponse(message, id, dest) { + var response = { + message: message, + /** Timeout to auto-clean old responses */ + timeout: setTimeout(function () { + responses.remove(id, dest); + }, response_timeout) + }; + responses.set(response, id, dest); + } + ; + /** + * Store the response to ignore duplicated messages later + */ + function storeProcessedResponse(ack, from) { + var timeout = setTimeout(function () { + processedResponses.remove(ack, from); + }, duplicates_timeout); + processedResponses.set(timeout, ack, from); + } + ; + /** + * Representation of a RPC request + * + * @class + * @extends RpcNotification + * + * @constructor + * + * @param {String} method -method of the notification + * @param params - parameters of the notification + * @param {Integer} id - identifier of the request + * @param [from] - source of the notification + */ + 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); + /** + * @constant {Boolean} duplicated + */ + 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); + /** + * Generate a response to this request + * + * @param {Error} [error] + * @param {*} [result] + * + * @returns {string} + */ + this.reply = function (error, result, transport) { + // Fix optional parameters + 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); + // Duplicated request, remove old response timeout + if (response) + clearTimeout(response.timeout); + if (from != undefined) { + if (error) + error.dest = from; + if (result) + result.dest = from; + } + ; + var message; + // New request or overriden one, create new response with provided data + if (error || result != undefined) { + if (self.peerID != undefined) { + if (error) + error.from = self.peerID; + else + result.from = self.peerID; + } + // Protocol indicates that responses has own request methods + 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); + // Store the response to prevent to process a duplicated request later + storeResponse(message, id, from); + // Return the stored response so it can be directly send back + 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); + // Start duplicated responses timeout + storeProcessedResponse(key.id, key.dest); + } + ; + /** + * Allow to cancel a request and don't wait for a response + * + * If `message` is not given, cancel all the request + */ + this.cancel = function (message) { + if (message) + return cancel(message); + for (var message in message2Key) + cancel(message); + }; + this.close = function () { + // Prevent to receive new messages + var transport = this.getTransport(); + if (transport && transport.close) + transport.close(); + // Request & processed responses + this.cancel(); + processedResponses.forEach(clearTimeout); + // Responses + responses.forEach(function (response) { + clearTimeout(response.timeout); + }); + }; + /** + * Generates and encode a JsonRPC 2.0 message + * + * @param {String} method -method of the notification + * @param params - parameters of the notification + * @param [dest] - destination of the notification + * @param {object} [transport] - transport where to send the message + * @param [callback] - function called when a response to this request is + * received. If not defined, a notification will be send instead + * + * @returns {string} A raw JsonRPC 2.0 request or notification string + */ + this.encode = function (method, params, dest, transport, callback) { + // Fix optional parameters + 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; + } + ; + // Encode message + 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); + } + ; + // Return the packed message + message = packer.pack(message); + transport = transport || this.getTransport(); + if (transport) + return transport.send(message); + return message; + }; + /** + * Decode and process a JsonRPC 2.0 message + * + * @param {string} message - string with the content of the message + * + * @returns {RpcNotification|RpcRequest|undefined} - the representation of the + * notification or the request. If a response was processed, it will return + * `undefined` to notify that it was processed + * + * @throws {TypeError} - Message is not defined + */ + this.decode = function (message, transport) { + if (!message) + throw new TypeError("Message is not defined"); + try { + message = packer.unpack(message); + } + catch (e) { + // Ignore invalid messages + 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; + // Ignore messages send by us + if (self.peerID != undefined && from == self.peerID) + return; + // Notification + if (id == undefined && ack == undefined) { + var notification = new RpcNotification(method, params); + if (self.emit('request', notification)) + return; + return notification; + } + ; + function processRequest() { + // If we have a transport and it's a duplicated request, reply inmediatly + 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); + // Update duplicated responses timeout + clearTimeout(timeout); + storeProcessedResponse(ack, from); + } + ; + // Request, or response with own method + if (method) { + // Check if it's a response with own 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); + } + // Request + return processRequest(); + } + ; + var error = message.error; + var result = message.result; + // Ignore responses not send to us + if (error && error.dest && error.dest != self.peerID) + return; + if (result && result.dest && result.dest != self.peerID) + return; + // Response + 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); + } + ; + // Process response + 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":40,"./clients":41,"./clients/transports":43,"./packers":48,"events":1,"inherits":6}],46:[function(require,module,exports){ +/** + * JsonRPC 2.0 packer + */ +/** + * Pack a JsonRPC 2.0 message + * + * @param {Object} message - object to be packaged. It requires to have all the + * fields needed by the JsonRPC 2.0 message that it's going to be generated + * + * @return {String} - the stringified JsonRPC 2.0 message + */ +function pack(message, id) { + var result = { + jsonrpc: "2.0" + }; + // Request + if (message.method) { + result.method = message.method; + if (message.params) + result.params = message.params; + // Request is a notification + 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); +} +; +/** + * Unpack a JsonRPC 2.0 message + * + * @param {String} message - string with the content of the JsonRPC 2.0 message + * + * @throws {TypeError} - Invalid JsonRPC version + * + * @return {Object} - object filled with the JsonRPC 2.0 message content + */ +function unpack(message) { + var result = message; + if (typeof message === 'string' || message instanceof String) { + result = JSON.parse(message); + } + // Check if it's a valid message + var version = result.jsonrpc; + if (version !== '2.0') + throw new TypeError("Invalid JsonRPC version '" + version + "': " + message); + // Response + 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; + // Check only result or error is defined, not both or none + 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 unpacked message + return result; +} +; +exports.pack = pack; +exports.unpack = unpack; + +},{}],47:[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; + +},{}],48:[function(require,module,exports){ +var JsonRPC = require('./JsonRPC'); +var XmlRPC = require('./XmlRPC'); +exports.JsonRPC = JsonRPC; +exports.XmlRPC = XmlRPC; + +},{"./JsonRPC":46,"./XmlRPC":47}],49:[function(require,module,exports){ +/* + * (C) Copyright 2014-2015 Kurento (http://kurento.org/) + * + * 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. + */ +var freeice = require('freeice'); +var inherits = require('inherits'); +var UAParser = require('ua-parser-js'); +var uuid = require('uuid'); +var hark = require('hark'); +var EventEmitter = require('events').EventEmitter; +var recursive = require('merge').recursive.bind(undefined, true); +var sdpTranslator = require('sdp-translator'); +var logger = window.Logger || console; +// var gUM = navigator.mediaDevices.getUserMedia || function (constraints) { +// return new Promise(navigator.getUserMedia(constraints, function (stream) { +// videoStream = stream +// start() +// }).eror(callback)); +// } +/*try { + require('kurento-browser-extensions') +} catch (error) { + if (typeof getScreenConstraints === 'undefined') { + logger.warn('screen sharing is not available') + + getScreenConstraints = function getScreenConstraints(sendSource, callback) { + callback(new Error("This library is not enabled for screen sharing")) + } + } +}*/ +var MEDIA_CONSTRAINTS = { + audio: true, + video: { + width: 640, + framerate: 15 + } +}; +// Somehow, the UAParser constructor gets an empty window object. +// We need to pass the user agent string in order to get information +var ua = (window && window.navigator) ? window.navigator.userAgent : ''; +var parser = new UAParser(ua); +var browser = parser.getBrowser(); +var usePlanB = false; +if (browser.name === 'Chrome' || browser.name === 'Chromium') { + logger.debug(browser.name + ": using SDP PlanB"); + usePlanB = true; +} +function noop(error) { + if (error) + logger.error(error); +} +function trackStop(track) { + track.stop && track.stop(); +} +function streamStop(stream) { + stream.getTracks().forEach(trackStop); +} +/** + * Returns a string representation of a SessionDescription object. + */ +var dumpSDP = function (description) { + if (typeof description === 'undefined' || description === null) { + return ''; + } + return 'type: ' + description.type + '\r\n' + description.sdp; +}; +function bufferizeCandidates(pc, onerror) { + var candidatesQueue = []; + pc.addEventListener('signalingstatechange', function () { + if (this.signalingState === 'stable') { + while (candidatesQueue.length) { + var entry = candidatesQueue.shift(); + this.addIceCandidate(entry.candidate, entry.callback, entry.callback); + } + } + }); + return function (candidate, callback) { + callback = callback || onerror; + switch (pc.signalingState) { + case 'closed': + callback(new Error('PeerConnection object is closed')); + break; + case 'stable': + if (pc.remoteDescription) { + pc.addIceCandidate(candidate, callback, callback); + } + break; + default: + candidatesQueue.push({ + candidate: candidate, + callback: callback + }); + } + }; +} +/* Simulcast utilities */ +function removeFIDFromOffer(sdp) { + var n = sdp.indexOf("a=ssrc-group:FID"); + if (n > 0) { + return sdp.slice(0, n); + } + else { + return sdp; + } +} +function getSimulcastInfo(videoStream) { + var videoTracks = videoStream.getVideoTracks(); + if (!videoTracks.length) { + logger.warn('No video tracks available in the video stream'); + return ''; + } + var lines = [ + 'a=x-google-flag:conference', + 'a=ssrc-group:SIM 1 2 3', + 'a=ssrc:1 cname:localVideo', + 'a=ssrc:1 msid:' + videoStream.id + ' ' + videoTracks[0].id, + 'a=ssrc:1 mslabel:' + videoStream.id, + 'a=ssrc:1 label:' + videoTracks[0].id, + 'a=ssrc:2 cname:localVideo', + 'a=ssrc:2 msid:' + videoStream.id + ' ' + videoTracks[0].id, + 'a=ssrc:2 mslabel:' + videoStream.id, + 'a=ssrc:2 label:' + videoTracks[0].id, + 'a=ssrc:3 cname:localVideo', + 'a=ssrc:3 msid:' + videoStream.id + ' ' + videoTracks[0].id, + 'a=ssrc:3 mslabel:' + videoStream.id, + 'a=ssrc:3 label:' + videoTracks[0].id + ]; + lines.push(''); + return lines.join('\n'); +} +/** + * Wrapper object of an RTCPeerConnection. This object is aimed to simplify the + * development of WebRTC-based applications. + * + * @constructor module:kurentoUtils.WebRtcPeer + * + * @param {String} mode Mode in which the PeerConnection will be configured. + * Valid values are: 'recv', 'send', and 'sendRecv' + * @param localVideo Video tag for the local stream + * @param remoteVideo Video tag for the remote stream + * @param {MediaStream} videoStream Stream to be used as primary source + * (typically video and audio, or only video if combined with audioStream) for + * localVideo and to be added as stream to the RTCPeerConnection + * @param {MediaStream} audioStream Stream to be used as second source + * (typically for audio) for localVideo and to be added as stream to the + * RTCPeerConnection + */ +function WebRtcPeer(mode, options, callback) { + if (!(this instanceof WebRtcPeer)) { + return new WebRtcPeer(mode, options, callback); + } + WebRtcPeer.super_.call(this); + if (options instanceof Function) { + callback = options; + options = undefined; + } + options = options || {}; + callback = (callback || noop).bind(this); + var self = this; + var localVideo = options.localVideo; + var remoteVideo = options.remoteVideo; + var videoStream = options.videoStream; + var audioStream = options.audioStream; + var mediaConstraints = options.mediaConstraints; + var connectionConstraints = options.connectionConstraints; + var pc = options.peerConnection; + var sendSource = options.sendSource || 'webcam'; + var dataChannelConfig = options.dataChannelConfig; + var useDataChannels = options.dataChannels || false; + var dataChannel; + var guid = uuid.v4(); + var configuration = recursive({ + iceServers: freeice() + }, options.configuration); + var onicecandidate = options.onicecandidate; + if (onicecandidate) + this.on('icecandidate', onicecandidate); + var oncandidategatheringdone = options.oncandidategatheringdone; + if (oncandidategatheringdone) { + this.on('candidategatheringdone', oncandidategatheringdone); + } + var simulcast = options.simulcast; + var multistream = options.multistream; + var interop = new sdpTranslator.Interop(); + var candidatesQueueOut = []; + var candidategatheringdone = false; + Object.defineProperties(this, { + 'peerConnection': { + get: function () { + return pc; + } + }, + 'id': { + value: options.id || guid, + writable: false + }, + 'remoteVideo': { + get: function () { + return remoteVideo; + } + }, + 'localVideo': { + get: function () { + return localVideo; + } + }, + 'dataChannel': { + get: function () { + return dataChannel; + } + }, + /** + * @member {(external:ImageData|undefined)} currentFrame + */ + 'currentFrame': { + get: function () { + // [ToDo] Find solution when we have a remote stream but we didn't set + // a remoteVideo tag + if (!remoteVideo) + return; + if (remoteVideo.readyState < remoteVideo.HAVE_CURRENT_DATA) + throw new Error('No video stream data available'); + var canvas = document.createElement('canvas'); + canvas.width = remoteVideo.videoWidth; + canvas.height = remoteVideo.videoHeight; + canvas.getContext('2d').drawImage(remoteVideo, 0, 0); + return canvas; + } + } + }); + // Init PeerConnection + if (!pc) { + pc = new RTCPeerConnection(configuration); + if (useDataChannels && !dataChannel) { + var dcId = 'WebRtcPeer-' + self.id; + var dcOptions = undefined; + if (dataChannelConfig) { + dcId = dataChannelConfig.id || dcId; + dcOptions = dataChannelConfig.options; + } + dataChannel = pc.createDataChannel(dcId, dcOptions); + if (dataChannelConfig) { + dataChannel.onopen = dataChannelConfig.onopen; + dataChannel.onclose = dataChannelConfig.onclose; + dataChannel.onmessage = dataChannelConfig.onmessage; + dataChannel.onbufferedamountlow = dataChannelConfig.onbufferedamountlow; + dataChannel.onerror = dataChannelConfig.onerror || noop; + } + } + } + pc.addEventListener('icecandidate', function (event) { + var candidate = event.candidate; + if (EventEmitter.listenerCount(self, 'icecandidate') || + EventEmitter.listenerCount(self, 'candidategatheringdone')) { + if (candidate) { + var cand; + if (multistream && usePlanB) { + cand = interop.candidateToUnifiedPlan(candidate); + } + else { + cand = candidate; + } + self.emit('icecandidate', cand); + candidategatheringdone = false; + } + else if (!candidategatheringdone) { + self.emit('candidategatheringdone'); + candidategatheringdone = true; + } + } + else if (!candidategatheringdone) { + // Not listening to 'icecandidate' or 'candidategatheringdone' events, queue + // the candidate until one of them is listened + candidatesQueueOut.push(candidate); + if (!candidate) + candidategatheringdone = true; + } + }); + pc.ontrack = options.onaddstream; + pc.onnegotiationneeded = options.onnegotiationneeded; + this.on('newListener', function (event, listener) { + if (event === 'icecandidate' || event === 'candidategatheringdone') { + while (candidatesQueueOut.length) { + var candidate = candidatesQueueOut.shift(); + if (!candidate === (event === 'candidategatheringdone')) { + listener(candidate); + } + } + } + }); + var addIceCandidate = bufferizeCandidates(pc); + /** + * Callback function invoked when an ICE candidate is received. Developers are + * expected to invoke this function in order to complete the SDP negotiation. + * + * @function module:kurentoUtils.WebRtcPeer.prototype.addIceCandidate + * + * @param iceCandidate - Literal object with the ICE candidate description + * @param callback - Called when the ICE candidate has been added. + */ + this.addIceCandidate = function (iceCandidate, callback) { + var candidate; + if (multistream && usePlanB) { + candidate = interop.candidateToPlanB(iceCandidate); + } + else { + candidate = new RTCIceCandidate(iceCandidate); + } + logger.debug('Remote ICE candidate received', iceCandidate); + callback = (callback || noop).bind(this); + addIceCandidate(candidate, callback); + }; + this.generateOffer = function (callback) { + callback = callback.bind(this); + var offerAudio = true; + var offerVideo = true; + // Constraints must have both blocks + if (mediaConstraints) { + offerAudio = (typeof mediaConstraints.audio === 'boolean') ? + mediaConstraints.audio : true; + offerVideo = (typeof mediaConstraints.video === 'boolean') ? + mediaConstraints.video : true; + } + var browserDependantConstraints = { + offerToReceiveAudio: (mode !== 'sendonly' && offerAudio), + offerToReceiveVideo: (mode !== 'sendonly' && offerVideo) + }; + //FIXME: clarify possible constraints passed to createOffer() + /*var constraints = recursive(browserDependantConstraints, + connectionConstraints)*/ + var constraints = browserDependantConstraints; + logger.debug('constraints: ' + JSON.stringify(constraints)); + pc.createOffer(constraints).then(function (offer) { + logger.debug('Created SDP offer'); + offer = mangleSdpToAddSimulcast(offer); + return pc.setLocalDescription(offer); + }).then(function () { + var localDescription = pc.localDescription; + logger.debug('Local description set', localDescription.sdp); + if (multistream && usePlanB) { + localDescription = interop.toUnifiedPlan(localDescription); + logger.debug('offer::origPlanB->UnifiedPlan', dumpSDP(localDescription)); + } + callback(null, localDescription.sdp, self.processAnswer.bind(self)); + }).catch(callback); + }; + this.getLocalSessionDescriptor = function () { + return pc.localDescription; + }; + this.getRemoteSessionDescriptor = function () { + return pc.remoteDescription; + }; + function setRemoteVideo() { + if (remoteVideo) { + var stream = pc.getRemoteStreams()[0]; + var url = stream ? URL.createObjectURL(stream) : ''; + remoteVideo.pause(); + remoteVideo.src = url; + remoteVideo.load(); + logger.debug('Remote URL:', url); + } + } + this.showLocalVideo = function () { + localVideo.src = URL.createObjectURL(videoStream); + localVideo.muted = true; + }; + this.send = function (data) { + if (dataChannel && dataChannel.readyState === 'open') { + dataChannel.send(data); + } + else { + logger.warn('Trying to send data over a non-existing or closed data channel'); + } + }; + /** + * Callback function invoked when a SDP answer is received. Developers are + * expected to invoke this function in order to complete the SDP negotiation. + * + * @function module:kurentoUtils.WebRtcPeer.prototype.processAnswer + * + * @param sdpAnswer - Description of sdpAnswer + * @param callback - + * Invoked after the SDP answer is processed, or there is an error. + */ + this.processAnswer = function (sdpAnswer, callback) { + callback = (callback || noop).bind(this); + var answer = new RTCSessionDescription({ + type: 'answer', + sdp: sdpAnswer + }); + if (multistream && usePlanB) { + var planBAnswer = interop.toPlanB(answer); + logger.debug('asnwer::planB', dumpSDP(planBAnswer)); + answer = planBAnswer; + } + logger.debug('SDP answer received, setting remote description'); + if (pc.signalingState === 'closed') { + return callback('PeerConnection is closed'); + } + pc.setRemoteDescription(answer, function () { + setRemoteVideo(); + callback(); + }, callback); + }; + /** + * Callback function invoked when a SDP offer is received. Developers are + * expected to invoke this function in order to complete the SDP negotiation. + * + * @function module:kurentoUtils.WebRtcPeer.prototype.processOffer + * + * @param sdpOffer - Description of sdpOffer + * @param callback - Called when the remote description has been set + * successfully. + */ + this.processOffer = function (sdpOffer, callback) { + callback = callback.bind(this); + var offer = new RTCSessionDescription({ + type: 'offer', + sdp: sdpOffer + }); + if (multistream && usePlanB) { + var planBOffer = interop.toPlanB(offer); + logger.debug('offer::planB', dumpSDP(planBOffer)); + offer = planBOffer; + } + logger.debug('SDP offer received, setting remote description'); + if (pc.signalingState === 'closed') { + return callback('PeerConnection is closed'); + } + pc.setRemoteDescription(offer).then(function () { + return setRemoteVideo(); + }).then(function () { + return pc.createAnswer(); + }).then(function (answer) { + answer = mangleSdpToAddSimulcast(answer); + logger.debug('Created SDP answer'); + return pc.setLocalDescription(answer); + }).then(function () { + var localDescription = pc.localDescription; + if (multistream && usePlanB) { + localDescription = interop.toUnifiedPlan(localDescription); + logger.debug('answer::origPlanB->UnifiedPlan', dumpSDP(localDescription)); + } + logger.debug('Local description set', localDescription.sdp); + callback(null, localDescription.sdp); + }).catch(callback); + }; + function mangleSdpToAddSimulcast(answer) { + if (simulcast) { + if (browser.name === 'Chrome' || browser.name === 'Chromium') { + logger.debug('Adding multicast info'); + answer = new RTCSessionDescription({ + 'type': answer.type, + 'sdp': removeFIDFromOffer(answer.sdp) + getSimulcastInfo(videoStream) + }); + } + else { + logger.warn('Simulcast is only available in Chrome browser.'); + } + } + return answer; + } + /** + * This function creates the RTCPeerConnection object taking into account the + * properties received in the constructor. It starts the SDP negotiation + * process: generates the SDP offer and invokes the onsdpoffer callback. This + * callback is expected to send the SDP offer, in order to obtain an SDP + * answer from another peer. + */ + function start() { + if (pc.signalingState === 'closed') { + callback('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue'); + } + if (videoStream && localVideo) { + self.showLocalVideo(); + } + if (videoStream) { + pc.addStream(videoStream); + } + if (audioStream) { + pc.addStream(audioStream); + } + // [Hack] https://code.google.com/p/chromium/issues/detail?id=443558 + var browser = parser.getBrowser(); + if (mode === 'sendonly' && + (browser.name === 'Chrome' || browser.name === 'Chromium') && + browser.major === 39) { + mode = 'sendrecv'; + } + callback(); + } + if (mode !== 'recvonly' && !videoStream && !audioStream) { + function getMedia(constraints) { + if (constraints === undefined) { + constraints = MEDIA_CONSTRAINTS; + } + navigator.mediaDevices.getUserMedia(constraints).then(function (stream) { + videoStream = stream; + start(); + }).catch(callback); + } + if (sendSource === 'webcam') { + getMedia(mediaConstraints); + } + else { + getScreenConstraints(sendSource, function (error, constraints_) { + if (error) + return callback(error); + constraints = [mediaConstraints]; + constraints.unshift(constraints_); + getMedia(recursive.apply(undefined, constraints)); + }, guid); + } + } + else { + setTimeout(start, 0); + } + this.on('_dispose', function () { + if (localVideo) { + localVideo.pause(); + localVideo.src = ''; + localVideo.load(); + //Unmute local video in case the video tag is later used for remote video + localVideo.muted = false; + } + if (remoteVideo) { + remoteVideo.pause(); + remoteVideo.src = ''; + remoteVideo.load(); + } + self.removeAllListeners(); + if (window.cancelChooseDesktopMedia !== undefined) { + window.cancelChooseDesktopMedia(guid); + } + }); +} +inherits(WebRtcPeer, EventEmitter); +function createEnableDescriptor(type) { + var method = 'get' + type + 'Tracks'; + return { + enumerable: true, + get: function () { + // [ToDo] Should return undefined if not all tracks have the same value? + if (!this.peerConnection) + return; + var streams = this.peerConnection.getLocalStreams(); + if (!streams.length) + return; + for (var i = 0, stream; stream = streams[i]; i++) { + var tracks = stream[method](); + for (var j = 0, track; track = tracks[j]; j++) + if (!track.enabled) + return false; + } + return true; + }, + set: function (value) { + function trackSetEnable(track) { + track.enabled = value; + } + this.peerConnection.getLocalStreams().forEach(function (stream) { + stream[method]().forEach(trackSetEnable); + }); + } + }; +} +Object.defineProperties(WebRtcPeer.prototype, { + 'enabled': { + enumerable: true, + get: function () { + return this.audioEnabled && this.videoEnabled; + }, + set: function (value) { + this.audioEnabled = this.videoEnabled = value; + } + }, + 'audioEnabled': createEnableDescriptor('Audio'), + 'videoEnabled': createEnableDescriptor('Video') +}); +WebRtcPeer.prototype.getLocalStream = function (index) { + if (this.peerConnection) { + return this.peerConnection.getLocalStreams()[index || 0]; + } +}; +WebRtcPeer.prototype.getRemoteStream = function (index) { + if (this.peerConnection) { + return this.peerConnection.getRemoteStreams()[index || 0]; + } +}; +/** + * @description This method frees the resources used by WebRtcPeer. + * + * @function module:kurentoUtils.WebRtcPeer.prototype.dispose + */ +WebRtcPeer.prototype.dispose = function () { + logger.debug('Disposing WebRtcPeer'); + var pc = this.peerConnection; + var dc = this.dataChannel; + try { + if (dc) { + if (dc.signalingState === 'closed') + return; + dc.close(); + } + if (pc) { + if (pc.signalingState === 'closed') + return; + pc.getLocalStreams().forEach(streamStop); + // FIXME This is not yet implemented in firefox + // if(videoStream) pc.removeStream(videoStream); + // if(audioStream) pc.removeStream(audioStream); + pc.close(); + } + } + catch (err) { + logger.warn('Exception disposing webrtc peer ' + err); + } + this.emit('_dispose'); +}; +// +// Specialized child classes +// +function WebRtcPeerRecvonly(options, callback) { + if (!(this instanceof WebRtcPeerRecvonly)) { + return new WebRtcPeerRecvonly(options, callback); + } + WebRtcPeerRecvonly.super_.call(this, 'recvonly', options, callback); +} +inherits(WebRtcPeerRecvonly, WebRtcPeer); +function WebRtcPeerSendonly(options, callback) { + if (!(this instanceof WebRtcPeerSendonly)) { + return new WebRtcPeerSendonly(options, callback); + } + WebRtcPeerSendonly.super_.call(this, 'sendonly', options, callback); +} +inherits(WebRtcPeerSendonly, WebRtcPeer); +function WebRtcPeerSendrecv(options, callback) { + if (!(this instanceof WebRtcPeerSendrecv)) { + return new WebRtcPeerSendrecv(options, callback); + } + WebRtcPeerSendrecv.super_.call(this, 'sendrecv', options, callback); +} +inherits(WebRtcPeerSendrecv, WebRtcPeer); +function harkUtils(stream, options) { + return hark(stream, options); +} +exports.bufferizeCandidates = bufferizeCandidates; +exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly; +exports.WebRtcPeerSendonly = WebRtcPeerSendonly; +exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv; +exports.hark = harkUtils; + +},{"events":1,"freeice":2,"hark":5,"inherits":6,"merge":7,"sdp-translator":16,"ua-parser-js":20,"uuid":21}],50:[function(require,module,exports){ +/* + * (C) Copyright 2014 Kurento (http://kurento.org/) + * + * 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. + * + */ +/** + * This module contains a set of reusable components that have been found useful + * during the development of the WebRTC applications with Kurento. + * + * @module kurentoUtils + * + * @copyright 2014 Kurento (http://kurento.org/) + * @license ALv2 + */ +var WebRtcPeer = require('./WebRtcPeer'); +exports.WebRtcPeer = WebRtcPeer; + +},{"./WebRtcPeer":49}],51:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var OpenVidu_1 = require("./OpenVidu"); +//This export with --standalone option allows using OpenVidu from bowser with namespace +//export { OpenVidu } from './OpenVidu'; +//This "hack" allows to use OpenVidu from the global space window +if (window) { + window["OpenVidu"] = OpenVidu_1.OpenVidu; +} +//Command to generate bundle.js without namespace +//watchify Main.ts -p [ tsify ] --exclude kurento-browser-extensions --debug -o ../static/js/OpenVidu.js -v + +},{"./OpenVidu":52}],52:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/* + * (C) Copyright 2017 OpenVidu (http://openvidu.io/) + * + * 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. + * + */ +var OpenViduInternal_1 = require("../OpenViduInternal/OpenViduInternal"); +var Session_1 = require("./Session"); +var Publisher_1 = require("./Publisher"); +var OpenViduError_1 = require("../OpenViduInternal/OpenViduError"); +var LocalRecorder_1 = require("../OpenViduInternal/LocalRecorder"); +var adapter = require("webrtc-adapter"); +var screenSharingAuto = require("../ScreenSharing/Screen-Capturing-Auto.js"); +var DetectRTC = require("../KurentoUtils/DetectRTC"); +if (window) { + window["adapter"] = adapter; +} +var OpenVidu = /** @class */ (function () { + function OpenVidu() { + this.openVidu = new OpenViduInternal_1.OpenViduInternal(); + console.info("'OpenVidu' initialized"); + } + ; + OpenVidu.prototype.initSession = function (param1, param2) { + if (typeof param2 == "string") { + return new Session_1.Session(this.openVidu.initSession(param2), this); + } + else { + return new Session_1.Session(this.openVidu.initSession(param1), this); + } + }; + OpenVidu.prototype.initPublisher = function (parentId, cameraOptions, callback) { + var publisher; + if (cameraOptions != null) { + cameraOptions.audio = cameraOptions.audio != null ? cameraOptions.audio : true; + cameraOptions.video = cameraOptions.video != null ? cameraOptions.video : true; + if (!cameraOptions.screen) { + // Webcam and/or microphone is being requested + var cameraOptionsAux = { + sendAudio: cameraOptions.audio != null ? cameraOptions.audio : true, + sendVideo: cameraOptions.video != null ? cameraOptions.video : true, + activeAudio: cameraOptions.audioActive != null ? cameraOptions.audioActive : true, + activeVideo: cameraOptions.videoActive != null ? cameraOptions.videoActive : true, + dataChannel: true, + mediaConstraints: this.openVidu.generateMediaConstraints(cameraOptions) + }; + cameraOptions = cameraOptionsAux; + publisher = new Publisher_1.Publisher(this.openVidu.initPublisherTagged(parentId, cameraOptions, true, callback), parentId, false); + console.info("'Publisher' initialized"); + return publisher; + } + else { + // Screen share is being requested + publisher = new Publisher_1.Publisher(this.openVidu.initPublisherScreen(parentId, true, callback), parentId, true); + if (DetectRTC.browser.name === 'Firefox' && DetectRTC.browser.version >= 52) { + screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) { + cameraOptions = { + sendAudio: cameraOptions.audio, + sendVideo: cameraOptions.video, + activeAudio: cameraOptions.audioActive != null ? cameraOptions.audioActive : true, + activeVideo: cameraOptions.videoActive != null ? cameraOptions.videoActive : true, + dataChannel: true, + mediaConstraints: { + video: screenConstraints.video, + audio: false + } + }; + publisher.stream.configureScreenOptions(cameraOptions); + console.info("'Publisher' initialized"); + publisher.stream.ee.emitEvent('can-request-screen'); + }); + return publisher; + } + else if (DetectRTC.browser.name === 'Chrome') { + // Screen is being requested + /*screenSharing.isChromeExtensionAvailable((availability) => { + switch (availability) { + case 'available': + console.warn('EXTENSION AVAILABLE!!!'); + screenSharing.getScreenConstraints((error, screenConstraints) => { + if (!error) { + console.warn(screenConstraints); + } + }); + break; + case 'unavailable': + console.warn('EXTENSION NOT AVAILABLE!!!'); + break; + case 'isFirefox': + console.warn('IT IS FIREFOX!!!'); + screenSharing.getScreenConstraints((error, screenConstraints) => { + if (!error) { + console.warn(screenConstraints); + } + }); + break; + } + });*/ + screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) { + if (error === 'not-installed') { + var error_1 = new OpenViduError_1.OpenViduError("SCREEN_EXTENSION_NOT_INSTALLED" /* SCREEN_EXTENSION_NOT_INSTALLED */, 'https://chrome.google.com/webstore/detail/screen-capturing/ajhifddimkapgcifgcodmmfdlknahffk'); + console.error(error_1); + if (callback) + callback(error_1); + return; + } + else if (error === 'permission-denied') { + var error_2 = new OpenViduError_1.OpenViduError("SCREEN_CAPTURE_DENIED" /* SCREEN_CAPTURE_DENIED */, 'You must allow access to one window of your desktop'); + console.error(error_2); + if (callback) + callback(error_2); + return; + } + cameraOptions = { + sendAudio: cameraOptions.audio != null ? cameraOptions.audio : true, + sendVideo: cameraOptions.video != null ? cameraOptions.video : true, + activeAudio: cameraOptions.audioActive != null ? cameraOptions.audioActive : true, + activeVideo: cameraOptions.videoActive != null ? cameraOptions.videoActive : true, + dataChannel: true, + mediaConstraints: { + video: screenConstraints.video, + audio: false + } + }; + publisher.stream.configureScreenOptions(cameraOptions); + publisher.stream.ee.emitEvent('can-request-screen'); + }, function (error) { + console.error('getScreenId error', error); + return; + }); + console.info("'Publisher' initialized"); + return publisher; + } + else { + console.error('Screen sharing not supported on ' + DetectRTC.browser.name); + if (!!callback) + callback(new OpenViduError_1.OpenViduError("SCREEN_SHARING_NOT_SUPPORTED" /* SCREEN_SHARING_NOT_SUPPORTED */, 'Screen sharing not supported on ' + DetectRTC.browser.name + ' ' + DetectRTC.browser.version)); + } + } + } + else { + cameraOptions = { + sendAudio: true, + sendVideo: true, + activeAudio: true, + activeVideo: true, + dataChannel: true, + mediaConstraints: { + audio: true, + video: { width: { ideal: 1280 } } + } + }; + publisher = new Publisher_1.Publisher(this.openVidu.initPublisherTagged(parentId, cameraOptions, true, callback), parentId, false); + console.info("'Publisher' initialized"); + return publisher; + } + }; + OpenVidu.prototype.reinitPublisher = function (publisher) { + if (publisher.stream.typeOfVideo !== 'SCREEN') { + publisher = new Publisher_1.Publisher(this.openVidu.initPublisherTagged(publisher.stream.getParentId(), publisher.stream.outboundOptions, false), publisher.stream.getParentId(), false); + console.info("'Publisher' initialized"); + return publisher; + } + else { + publisher = new Publisher_1.Publisher(this.openVidu.initPublisherScreen(publisher.stream.getParentId(), false), publisher.stream.getParentId(), true); + if (DetectRTC.browser.name === 'Firefox' && DetectRTC.browser.version >= 52) { + screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) { + publisher.stream.outboundOptions.mediaConstraints.video = screenConstraints.video; + publisher.stream.configureScreenOptions(publisher.stream.outboundOptions); + console.info("'Publisher' initialized"); + publisher.stream.ee.emitEvent('can-request-screen'); + }); + return publisher; + } + else if (DetectRTC.browser.name === 'Chrome') { + screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) { + if (error === 'not-installed') { + var error_3 = new OpenViduError_1.OpenViduError("SCREEN_EXTENSION_NOT_INSTALLED" /* SCREEN_EXTENSION_NOT_INSTALLED */, 'https://chrome.google.com/webstore/detail/screen-capturing/ajhifddimkapgcifgcodmmfdlknahffk'); + console.error(error_3); + return; + } + else if (error === 'permission-denied') { + var error_4 = new OpenViduError_1.OpenViduError("SCREEN_CAPTURE_DENIED" /* SCREEN_CAPTURE_DENIED */, 'You must allow access to one window of your desktop'); + console.error(error_4); + return; + } + publisher.stream.outboundOptions.mediaConstraints.video = screenConstraints.video; + publisher.stream.configureScreenOptions(publisher.stream.outboundOptions); + publisher.stream.ee.emitEvent('can-request-screen'); + }, function (error) { + console.error('getScreenId error', error); + return; + }); + console.info("'Publisher' initialized"); + return publisher; + } + else { + console.error('Screen sharing not supported on ' + DetectRTC.browser.name); + } + } + }; + OpenVidu.prototype.checkSystemRequirements = function () { + var defaultWebRTCSupport = DetectRTC.isWebRTCSupported; + var browser = DetectRTC.browser.name; + var version = DetectRTC.browser.version; + if ((browser !== 'Chrome') && (browser !== 'Firefox') && (browser !== 'Opera')) { + return 0; + } + else { + return defaultWebRTCSupport ? 1 : 0; + } + }; + OpenVidu.prototype.getDevices = function (callback) { + navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) { + callback(null, deviceInfos); + }).catch(function (error) { + console.error("Error getting devices", error); + callback(error, null); + }); + }; + OpenVidu.prototype.enableProdMode = function () { + console.log = function () { }; + console.debug = function () { }; + console.info = function () { }; + console.warn = function () { }; + }; + OpenVidu.prototype.initLocalRecorder = function (stream) { + return new LocalRecorder_1.LocalRecorder(stream); + }; + return OpenVidu; +}()); +exports.OpenVidu = OpenVidu; + +},{"../KurentoUtils/DetectRTC":39,"../OpenViduInternal/LocalRecorder":57,"../OpenViduInternal/OpenViduError":58,"../OpenViduInternal/OpenViduInternal":59,"../ScreenSharing/Screen-Capturing-Auto.js":63,"./Publisher":53,"./Session":54,"webrtc-adapter":26}],53:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var EventEmitter = require("wolfy87-eventemitter"); +var Publisher = /** @class */ (function () { + function Publisher(stream, parentId, isScreenRequested) { + var _this = this; + this.ee = new EventEmitter(); + this.accessAllowed = false; + this.isScreenRequested = false; + this.stream = stream; + this.isScreenRequested = isScreenRequested; + // Listens to the deactivation of the default behaviour upon the deletion of a Stream object + this.ee.addListener('stream-destroyed-default', function (event) { + var s = event.stream; + s.addOnceEventListener('video-removed', function () { + _this.ee.emitEvent('videoElementDestroyed'); + }); + s.removeVideo(); + }); + if (document.getElementById(parentId) != null) { + this.element = document.getElementById(parentId); + } + } + Publisher.prototype.publishAudio = function (value) { + this.stream.getWebRtcPeer().audioEnabled = value; + }; + Publisher.prototype.publishVideo = function (value) { + this.stream.getWebRtcPeer().videoEnabled = value; + }; + Publisher.prototype.destroy = function () { + if (!!this.session) + this.session.unpublish(this); + this.stream.dispose(); + this.stream.removeVideo(this.element); + return this; + }; + Publisher.prototype.subscribeToRemote = function () { + this.stream.subscribeToMyRemote(); + }; + Publisher.prototype.on = function (eventName, callback) { + var _this = this; + this.ee.addListener(eventName, function (event) { + if (event) { + console.info("Event '" + eventName + "' triggered by 'Publisher'", event); + } + else { + console.info("Event '" + eventName + "' triggered by 'Publisher'"); + } + callback(event); + }); + if (eventName == 'streamCreated') { + if (this.stream.isPublisherPublished) { + this.ee.emitEvent('streamCreated', [{ stream: this.stream }]); + } + else { + this.stream.addEventListener('stream-created-by-publisher', function () { + _this.ee.emitEvent('streamCreated', [{ stream: _this.stream }]); + }); + } + } + if (eventName == 'videoElementCreated') { + if (this.stream.isVideoELementCreated) { + this.ee.emitEvent('videoElementCreated', [{ + element: this.stream.getVideoElement() + }]); + } + else { + this.stream.addEventListener('video-element-created-by-stream', function (element) { + _this.id = element.id; + _this.ee.emitEvent('videoElementCreated', [{ + element: element.element + }]); + }); + } + } + if (eventName == 'videoPlaying') { + var video = this.stream.getVideoElement(); + if (!this.stream.displayMyRemote() && video && + video.currentTime > 0 && + video.paused == false && + video.ended == false && + video.readyState == 4) { + this.ee.emitEvent('videoPlaying', [{ + element: this.stream.getVideoElement() + }]); + } + else { + this.stream.addEventListener('video-is-playing', function (element) { + _this.ee.emitEvent('videoPlaying', [{ + element: element.element + }]); + }); + } + } + if (eventName == 'remoteVideoPlaying') { + var video = this.stream.getVideoElement(); + if (this.stream.displayMyRemote() && video && + video.currentTime > 0 && + video.paused == false && + video.ended == false && + video.readyState == 4) { + this.ee.emitEvent('remoteVideoPlaying', [{ + element: this.stream.getVideoElement() + }]); + } + else { + this.stream.addEventListener('remote-video-is-playing', function (element) { + _this.ee.emitEvent('remoteVideoPlaying', [{ + element: element.element + }]); + }); + } + } + if (eventName == 'accessAllowed') { + if (this.stream.accessIsAllowed) { + this.ee.emitEvent('accessAllowed'); + } + else { + this.stream.addEventListener('access-allowed-by-publisher', function () { + _this.ee.emitEvent('accessAllowed'); + }); + } + } + if (eventName == 'accessDenied') { + if (this.stream.accessIsDenied) { + this.ee.emitEvent('accessDenied'); + } + else { + this.stream.addEventListener('access-denied-by-publisher', function () { + _this.ee.emitEvent('accessDenied'); + }); + } + } + }; + return Publisher; +}()); +exports.Publisher = Publisher; + +},{"wolfy87-eventemitter":38}],54:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var OpenViduError_1 = require("../OpenViduInternal/OpenViduError"); +var Subscriber_1 = require("./Subscriber"); +var EventEmitter = require("wolfy87-eventemitter"); +var DetectRTC = require("../KurentoUtils/DetectRTC"); +var Session = /** @class */ (function () { + function Session(session, openVidu) { + var _this = this; + this.session = session; + this.openVidu = openVidu; + this.ee = new EventEmitter(); + this.sessionId = session.getSessionId(); + // Listens to the deactivation of the default behaviour upon the deletion of a Stream object + this.session.addEventListener('stream-destroyed-default', function (event) { + event.stream.removeVideo(); + }); + // Listens to the deactivation of the default behaviour upon the disconnection of a Session + this.session.addEventListener('session-disconnected-default', function () { + var s; + for (var streamId in _this.session.getRemoteStreams()) { + _this.session.getRemoteStreams()[streamId].removeVideo(); + } + if (_this.connection && (Object.keys(_this.connection.getStreams()).length > 0)) { + for (var streamId in _this.connection.getStreams()) { + _this.connection.getStreams()[streamId].removeVideo(); + } + } + }); + // Sets or updates the value of 'connection' property. Triggered by SessionInternal when succesful connection + this.session.addEventListener('update-connection-object', function (event) { + _this.connection = event.connection; + }); + } + Session.prototype.connect = function (param1, param2, param3) { + // Early configuration to deactivate automatic subscription to streams + if (param3) { + if (this.openVidu.checkSystemRequirements()) { + this.session.configure({ + sessionId: this.session.getSessionId(), + participantId: param1, + metadata: this.session.stringClientMetadata(param2), + subscribeToStreams: false + }); + this.session.connect(param1, param3); + } + else { + param3(new OpenViduError_1.OpenViduError("BROWSER_NOT_SUPPORTED" /* BROWSER_NOT_SUPPORTED */, 'Browser ' + DetectRTC.browser.name + ' ' + DetectRTC.browser.version + ' is not supported in OpenVidu')); + } + } + else { + if (this.openVidu.checkSystemRequirements()) { + this.session.configure({ + sessionId: this.session.getSessionId(), + participantId: param1, + metadata: '', + subscribeToStreams: false + }); + this.session.connect(param1, param2); + } + else { + param2(new OpenViduError_1.OpenViduError("BROWSER_NOT_SUPPORTED" /* BROWSER_NOT_SUPPORTED */, 'Browser ' + DetectRTC.browser.name + ' ' + DetectRTC.browser.version + ' is not supported in OpenVidu')); + } + } + }; + Session.prototype.disconnect = function () { + var _this = this; + this.openVidu.openVidu.close(false); + this.session.emitEvent('sessionDisconnected', [{ + preventDefault: function () { _this.session.removeEvent('session-disconnected-default'); } + }]); + this.session.emitEvent('session-disconnected-default', [{}]); + }; + Session.prototype.publish = function (publisher) { + var _this = this; + if (!publisher.stream.isPublisherPublished) { + if (publisher.isScreenRequested) { + if (!publisher.stream.isScreenRequestedReady) { + publisher.stream.addOnceEventListener('screen-ready', function () { + _this.streamPublish(publisher); + }); + } + else { + this.streamPublish(publisher); + } + } + else { + this.streamPublish(publisher); + } + } + else { + publisher = this.openVidu.reinitPublisher(publisher); + if (publisher.isScreenRequested && !publisher.stream.isScreenRequestedReady) { + publisher.stream.addOnceEventListener('screen-ready', function () { + _this.streamPublish(publisher); + }); + } + else { + this.streamPublish(publisher); + } + } + }; + Session.prototype.streamPublish = function (publisher) { + publisher.session = this; + this.connection.addStream(publisher.stream); + publisher.stream.publish(); + }; + Session.prototype.unpublish = function (publisher) { + this.session.unpublish(publisher); + }; + Session.prototype.on = function (eventName, callback) { + this.session.addEventListener(eventName, function (event) { + if (event) { + console.info("Event '" + eventName + "' triggered by 'Session'", event); + } + else { + console.info("Event '" + eventName + "' triggered by 'Session'"); + } + callback(event); + }); + }; + Session.prototype.once = function (eventName, callback) { + this.session.addOnceEventListener(eventName, function (event) { + callback(event); + }); + }; + Session.prototype.off = function (eventName, eventHandler) { + this.session.removeListener(eventName, eventHandler); + }; + Session.prototype.subscribe = function (param1, param2, param3) { + // Subscription + this.session.subscribe(param1); + var subscriber = new Subscriber_1.Subscriber(param1, param2); + param1.playOnlyVideo(param2, null); + return subscriber; + }; + Session.prototype.unsubscribe = function (subscriber) { + this.session.unsubscribe(subscriber.stream); + subscriber.stream.removeVideo(); + }; + Session.prototype.signal = function (signal, completionHandler) { + var signalMessage = {}; + if (signal.to && signal.to.length > 0) { + var connectionIds = []; + for (var i = 0; i < signal.to.length; i++) { + connectionIds.push(signal.to[i].connectionId); + } + signalMessage['to'] = connectionIds; + } + else { + signalMessage['to'] = []; + } + signalMessage['data'] = signal.data ? signal.data : ''; + signalMessage['type'] = signal.type ? signal.type : ''; + this.openVidu.openVidu.sendMessage(JSON.stringify(signalMessage)); + }; + return Session; +}()); +exports.Session = Session; + +},{"../KurentoUtils/DetectRTC":39,"../OpenViduInternal/OpenViduError":58,"./Subscriber":55,"wolfy87-eventemitter":38}],55:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var EventEmitter = require("wolfy87-eventemitter"); +var Subscriber = /** @class */ (function () { + function Subscriber(stream, parentId) { + var _this = this; + this.ee = new EventEmitter(); + this.stream = stream; + if (document.getElementById(parentId) != null) { + this.element = document.getElementById(parentId); + } + // Listens to deletion of the HTML video element of the Subscriber + this.stream.addEventListener('video-removed', function () { + _this.ee.emitEvent('videoElementDestroyed'); + }); + } + Subscriber.prototype.on = function (eventName, callback) { + var _this = this; + this.ee.addListener(eventName, function (event) { + if (event) { + console.info("Event '" + eventName + "' triggered by 'Subscriber'", event); + } + else { + console.info("Event '" + eventName + "' triggered by 'Subscriber'"); + } + callback(event); + }); + if (eventName == 'videoElementCreated') { + if (this.stream.isVideoELementCreated) { + this.ee.emitEvent('videoElementCreated', [{ + element: this.stream.getVideoElement() + }]); + } + else { + this.stream.addOnceEventListener('video-element-created-by-stream', function (element) { + _this.id = element.id; + _this.ee.emitEvent('videoElementCreated', [{ + element: element + }]); + }); + } + } + if (eventName == 'videoPlaying') { + var video = this.stream.getVideoElement(); + if (!this.stream.displayMyRemote() && video && + video.currentTime > 0 && + video.paused == false && + video.ended == false && + video.readyState == 4) { + this.ee.emitEvent('videoPlaying', [{ + element: this.stream.getVideoElement() + }]); + } + else { + this.stream.addOnceEventListener('video-is-playing', function (element) { + _this.ee.emitEvent('videoPlaying', [{ + element: element.element + }]); + }); + } + } + }; + return Subscriber; +}()); +exports.Subscriber = Subscriber; + +},{"wolfy87-eventemitter":38}],56:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Stream_1 = require("./Stream"); +var Connection = /** @class */ (function () { + function Connection(openVidu, local, room, options) { + this.openVidu = openVidu; + this.local = local; + this.room = room; + this.options = options; + this.streams = {}; + console.info("'Connection' created (" + (local ? "local" : "remote") + ")" + (local ? "" : ", with 'connectionId' [" + (options ? options.id : '') + "] ")); + if (options && !local) { + this.connectionId = options.id; + if (options.metadata) { + this.data = options.metadata; + } + if (options.streams) { + this.initRemoteStreams(options); + } + } + } + Connection.prototype.addStream = function (stream) { + stream.connection = this; + this.streams[stream.streamId] = stream; + //this.room.getStreams()[stream.streamId] = stream; + }; + Connection.prototype.removeStream = function (key) { + delete this.streams[key]; + //delete this.room.getStreams()[key]; + delete this.inboundStreamsOpts; + }; + Connection.prototype.setOptions = function (options) { + this.options = options; + }; + Connection.prototype.getStreams = function () { + return this.streams; + }; + Connection.prototype.dispose = function () { + for (var key in this.streams) { + this.streams[key].dispose(); + } + }; + Connection.prototype.sendIceCandidate = function (candidate) { + console.debug((this.local ? "Local" : "Remote"), "candidate for", this.connectionId, JSON.stringify(candidate)); + this.openVidu.sendRequest("onIceCandidate", { + endpointName: this.connectionId, + candidate: candidate.candidate, + sdpMid: candidate.sdpMid, + sdpMLineIndex: candidate.sdpMLineIndex + }, function (error, response) { + if (error) { + console.error("Error sending ICE candidate: " + + JSON.stringify(error)); + } + }); + }; + Connection.prototype.initRemoteStreams = function (options) { + var opts; + for (var _i = 0, _a = options.streams; _i < _a.length; _i++) { + opts = _a[_i]; + var streamOptions = { + id: opts.id, + connection: this, + recvAudio: (opts.audioActive == null ? true : opts.audioActive), + recvVideo: (opts.videoActive == null ? true : opts.videoActive), + typeOfVideo: opts.typeOfVideo, + }; + var stream = new Stream_1.Stream(this.openVidu, false, this.room, streamOptions); + this.addStream(stream); + this.inboundStreamsOpts = streamOptions; + } + console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + "] is now configured for receiving Streams with options: ", this.inboundStreamsOpts); + }; + return Connection; +}()); +exports.Connection = Connection; + +},{"./Stream":61}],57:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var LocalRecoderState; +(function (LocalRecoderState) { + LocalRecoderState["READY"] = "READY"; + LocalRecoderState["RECORDING"] = "RECORDING"; + LocalRecoderState["PAUSED"] = "PAUSED"; + LocalRecoderState["FINISHED"] = "FINISHED"; +})(LocalRecoderState = exports.LocalRecoderState || (exports.LocalRecoderState = {})); +var LocalRecorder = /** @class */ (function () { + function LocalRecorder(stream) { + this.chunks = []; + this.count = 0; + this.stream = stream; + this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection'; + this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord'; + this.state = "READY" /* READY */; + } + LocalRecorder.prototype.record = function () { + var _this = this; + if (typeof MediaRecorder === 'undefined') { + console.error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder'); + throw (Error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder')); + } + if (this.state !== "READY" /* READY */) { + throw (Error('\'LocalRecord.record()\' needs \'LocalRecord.state\' to be \'READY\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.clean()\' or init a new LocalRecorder before')); + } + console.log("Starting local recording of stream '" + this.stream.streamId + "' of connection '" + this.connectionId + "'"); + if (typeof MediaRecorder.isTypeSupported == 'function') { + var options = void 0; + if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) { + options = { mimeType: 'video/webm;codecs=vp9' }; + } + else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) { + options = { mimeType: 'video/webm;codecs=h264' }; + } + else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) { + options = { mimeType: 'video/webm;codecs=vp8' }; + } + console.log('Using mimeType ' + options.mimeType); + this.mediaRecorder = new MediaRecorder(this.stream.getMediaStream(), options); + } + else { + console.warn('isTypeSupported is not supported, using default codecs for browser'); + this.mediaRecorder = new MediaRecorder(this.stream.getMediaStream()); + } + this.mediaRecorder.start(10); + this.mediaRecorder.ondataavailable = function (e) { + _this.chunks.push(e.data); + }; + this.mediaRecorder.onerror = function (e) { + console.error('MediaRecorder error: ', e); + }; + this.mediaRecorder.onstart = function () { + console.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ")"); + }; + this.mediaRecorder.onstop = function () { + _this.onStopDefault(); + }; + this.mediaRecorder.onpause = function () { + console.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ")"); + }; + this.mediaRecorder.onresume = function () { + console.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ")"); + }; + this.mediaRecorder.onwarning = function (e) { + console.log('MediaRecorder warning: ' + e); + }; + this.state = "RECORDING" /* RECORDING */; + }; + LocalRecorder.prototype.stop = function () { + var _this = this; + return new Promise(function (resolve, reject) { + try { + if (_this.state === "READY" /* READY */ || _this.state === "FINISHED" /* 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(); + resolve(); + }; + } + catch (e) { + reject(e); + } + try { + _this.mediaRecorder.stop(); + } + catch (e) { + reject(e); + } + }); + }; + LocalRecorder.prototype.pause = function () { + if (this.state !== "RECORDING" /* RECORDING */) { + throw (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 = "PAUSED" /* PAUSED */; + }; + LocalRecorder.prototype.resume = function () { + if (this.state !== "PAUSED" /* PAUSED */) { + throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.pause()\' before')); + } + this.mediaRecorder.resume(); + this.state = "RECORDING" /* RECORDING */; + }; + LocalRecorder.prototype.preview = function (parentElement) { + if (this.state !== "FINISHED" /* 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 (typeof parentElement === "string") { + this.htmlParentElementId = parentElement; + var parentElementDom = document.getElementById(parentElement); + if (parentElementDom) { + this.videoPreview = parentElementDom.appendChild(this.videoPreview); + } + } + else { + this.htmlParentElementId = parentElement.id; + 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.count = 0; + delete _this.mediaRecorder; + _this.state = "READY" /* READY */; + }; + if (this.state === "RECORDING" /* RECORDING */ || this.state === "PAUSED" /* PAUSED */) { + this.stop().then(function () { return f(); }).catch(function () { return f(); }); + } + else { + f(); + } + }; + LocalRecorder.prototype.download = function () { + if (this.state !== "FINISHED" /* 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 + '.webm'; + a.click(); + window.URL.revokeObjectURL(url); + document.body.removeChild(a); + } + }; + LocalRecorder.prototype.getBlob = function () { + if (this.state !== "FINISHED" /* 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 !== "FINISHED" /* FINISHED */) { + 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') { + // Success response from server (HTTP status standard: 2XX is success) + resolve(http_1.responseText); + } + else { + reject(Error("Upload error: " + 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 !== "FINISHED" /* FINISHED */) { + 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 + ".webm"); + http_2.onreadystatechange = function () { + if (http_2.readyState === 4) { + if (http_2.status.toString().charAt(0) === '2') { + // Success response from server (HTTP status standard: 2XX is success) + resolve(http_2.responseText); + } + else { + reject(Error("Upload error: " + http_2.status)); + } + } + }; + http_2.send(sendable); + } + }); + }; + LocalRecorder.prototype.onStopDefault = function () { + console.log('MediaRecorder stopped (state=' + this.mediaRecorder.state + ")"); + this.blob = new Blob(this.chunks, { type: "video/webm" }); + this.chunks = []; + this.videoPreviewSrc = window.URL.createObjectURL(this.blob); + this.state = "FINISHED" /* FINISHED */; + }; + return LocalRecorder; +}()); +exports.LocalRecorder = LocalRecorder; + +},{}],58:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var OpenViduErrorName; +(function (OpenViduErrorName) { + OpenViduErrorName["BROWSER_NOT_SUPPORTED"] = "BROWSER_NOT_SUPPORTED"; + OpenViduErrorName["CAMERA_ACCESS_DENIED"] = "CAMERA_ACCESS_DENIED"; + OpenViduErrorName["MICROPHONE_ACCESS_DENIED"] = "MICROPHONE_ACCESS_DENIED"; + OpenViduErrorName["SCREEN_CAPTURE_DENIED"] = "SCREEN_CAPTURE_DENIED"; + OpenViduErrorName["NO_VIDEO_DEVICE"] = "NO_VIDEO_DEVICE"; + OpenViduErrorName["NO_INPUT_DEVICE"] = "NO_INPUT_DEVICE"; + OpenViduErrorName["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED"; + OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED"; + OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR"; +})(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {})); +var OpenViduError = /** @class */ (function () { + function OpenViduError(name, message) { + this.name = name; + this.message = message; + } + return OpenViduError; +}()); +exports.OpenViduError = OpenViduError; + +},{}],59:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/* + * (C) Copyright 2017 OpenVidu (http://openvidu.io/) + * + * 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. + * + */ +var SessionInternal_1 = require("./SessionInternal"); +var OpenViduError_1 = require("./OpenViduError"); +var Stream_1 = require("./Stream"); +var RpcBuilder = require("../KurentoUtils/kurento-jsonrpc"); +var OpenViduInternal = /** @class */ (function () { + function OpenViduInternal() { + this.recorder = false; + } + /* NEW METHODS */ + OpenViduInternal.prototype.initSession = function (sessionId) { + console.info("'Session' initialized with 'sessionId' [" + sessionId + "]"); + this.session = new SessionInternal_1.SessionInternal(this, sessionId); + return this.session; + }; + OpenViduInternal.prototype.initPublisherTagged = function (parentId, cameraOptions, newStream, callback) { + var _this = this; + if (newStream) { + if (cameraOptions == null) { + cameraOptions = { + sendAudio: true, + sendVideo: true, + activeAudio: true, + activeVideo: true, + dataChannel: true, + mediaConstraints: { + audio: true, + video: { width: { ideal: 1280 } } + } + }; + } + this.localStream = new Stream_1.Stream(this, true, this.session, cameraOptions); + } + this.localStream.requestCameraAccess(function (error, localStream) { + if (error) { + // Neither localStream or microphone device is allowed/able to capture media + console.error(error); + if (callback) { + callback(error); + } + _this.localStream.ee.emitEvent('access-denied-by-publisher'); + } + else { + _this.localStream.setVideoElement(_this.cameraReady(localStream, parentId)); + if (callback) { + callback(undefined); + } + } + }); + return this.localStream; + }; + OpenViduInternal.prototype.initPublisherScreen = function (parentId, newStream, callback) { + var _this = this; + if (newStream) { + this.localStream = new Stream_1.Stream(this, true, this.session, 'screen-options'); + } + this.localStream.addOnceEventListener('can-request-screen', function () { + _this.localStream.requestCameraAccess(function (error, localStream) { + if (error) { + _this.localStream.ee.emitEvent('access-denied-by-publisher'); + var errorName = "SCREEN_CAPTURE_DENIED" /* SCREEN_CAPTURE_DENIED */; + var errorMessage = 'You must allow access to one window of your desktop'; + var e = new OpenViduError_1.OpenViduError(errorName, errorMessage); + console.error(e); + if (callback) { + callback(e); + } + } + else { + _this.localStream.setVideoElement(_this.cameraReady(localStream, parentId)); + if (_this.localStream.getSendAudio()) { + // If the user wants to send audio with the screen capturing + navigator.mediaDevices.getUserMedia({ audio: true, video: false }) + .then(function (userStream) { + _this.localStream.getMediaStream().addTrack(userStream.getAudioTracks()[0]); + // Mute audio if 'activeAudio' property is false + if (userStream.getAudioTracks()[0] != null) { + userStream.getAudioTracks()[0].enabled = _this.localStream.outboundOptions.activeAudio; + } + _this.localStream.isScreenRequestedReady = true; + _this.localStream.ee.emitEvent('screen-ready'); + if (callback) { + callback(undefined); + } + }) + .catch(function (error) { + _this.localStream.ee.emitEvent('access-denied-by-publisher'); + console.error("Error accessing the microphone", error); + if (callback) { + var errorName = "MICROPHONE_ACCESS_DENIED" /* MICROPHONE_ACCESS_DENIED */; + var errorMessage = error.toString(); + callback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + } + }); + } + else { + _this.localStream.isScreenRequestedReady = true; + _this.localStream.ee.emitEvent('screen-ready'); + if (callback) { + callback(undefined); + } + } + } + }); + }); + return this.localStream; + }; + OpenViduInternal.prototype.cameraReady = function (localStream, parentId) { + this.localStream = localStream; + var videoElement = this.localStream.playOnlyVideo(parentId, null); + this.localStream.emitStreamReadyEvent(); + return videoElement; + }; + OpenViduInternal.prototype.getLocalStream = function () { + return this.localStream; + }; + /* NEW METHODS */ + OpenViduInternal.prototype.getWsUri = function () { + return this.wsUri; + }; + OpenViduInternal.prototype.setWsUri = function (wsUri) { + this.wsUri = wsUri; + }; + OpenViduInternal.prototype.getSecret = function () { + return this.secret; + }; + OpenViduInternal.prototype.setSecret = function (secret) { + this.secret = secret; + }; + OpenViduInternal.prototype.getRecorder = function () { + return this.recorder; + }; + OpenViduInternal.prototype.setRecorder = function (recorder) { + this.recorder = recorder; + }; + OpenViduInternal.prototype.getOpenViduServerURL = function () { + return 'https://' + this.wsUri.split("wss://")[1].split("/room")[0]; + }; + OpenViduInternal.prototype.getRoom = function () { + return this.session; + }; + OpenViduInternal.prototype.connect = function (callback) { + this.callback = callback; + this.initJsonRpcClient(this.wsUri); + }; + OpenViduInternal.prototype.initJsonRpcClient = function (wsUri) { + var config = { + heartbeat: 3000, + sendCloseMessage: false, + ws: { + uri: wsUri, + useSockJS: false, + onconnected: this.connectCallback.bind(this), + ondisconnect: this.disconnectCallback.bind(this), + onreconnecting: this.reconnectingCallback.bind(this), + onreconnected: this.reconnectedCallback.bind(this) + }, + rpc: { + requestTimeout: 15000, + //notifications + participantJoined: this.onParticipantJoined.bind(this), + participantPublished: this.onParticipantPublished.bind(this), + participantUnpublished: this.onParticipantUnpublished.bind(this), + participantLeft: this.onParticipantLeft.bind(this), + participantEvicted: this.onParticipantEvicted.bind(this), + sendMessage: this.onNewMessage.bind(this), + iceCandidate: this.iceCandidateEvent.bind(this), + mediaError: this.onMediaError.bind(this), + } + }; + this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config); + }; + OpenViduInternal.prototype.connectCallback = function (error) { + if (error) { + this.callback(error); + } + else { + this.callback(null); + } + }; + OpenViduInternal.prototype.isRoomAvailable = function () { + if (this.session !== undefined && this.session instanceof SessionInternal_1.SessionInternal) { + return true; + } + else { + console.warn('Session instance not found'); + return false; + } + }; + OpenViduInternal.prototype.disconnectCallback = function () { + console.warn('Websocket connection lost'); + if (this.isRoomAvailable()) { + this.session.onLostConnection(); + } + else { + alert('Connection error. Please reload page.'); + } + }; + OpenViduInternal.prototype.reconnectingCallback = function () { + console.warn('Websocket connection lost (reconnecting)'); + if (this.isRoomAvailable()) { + this.session.onLostConnection(); + } + else { + alert('Connection error. Please reload page.'); + } + }; + OpenViduInternal.prototype.reconnectedCallback = function () { + console.warn('Websocket reconnected'); + }; + OpenViduInternal.prototype.onParticipantJoined = function (params) { + if (this.isRoomAvailable()) { + this.session.onParticipantJoined(params); + } + }; + OpenViduInternal.prototype.onParticipantPublished = function (params) { + if (this.isRoomAvailable()) { + this.session.onParticipantPublished(params); + } + }; + OpenViduInternal.prototype.onParticipantUnpublished = function (params) { + if (this.isRoomAvailable()) { + this.session.onParticipantUnpublished(params); + } + }; + OpenViduInternal.prototype.onParticipantLeft = function (params) { + if (this.isRoomAvailable()) { + this.session.onParticipantLeft(params); + } + }; + OpenViduInternal.prototype.onParticipantEvicted = function (params) { + if (this.isRoomAvailable()) { + this.session.onParticipantEvicted(params); + } + }; + OpenViduInternal.prototype.onNewMessage = function (params) { + if (this.isRoomAvailable()) { + this.session.onNewMessage(params); + } + }; + OpenViduInternal.prototype.iceCandidateEvent = function (params) { + if (this.isRoomAvailable()) { + this.session.recvIceCandidate(params); + } + }; + OpenViduInternal.prototype.onRoomClosed = function (params) { + if (this.isRoomAvailable()) { + this.session.onRoomClosed(params); + } + }; + OpenViduInternal.prototype.onMediaError = function (params) { + if (this.isRoomAvailable()) { + this.session.onMediaError(params); + } + }; + OpenViduInternal.prototype.setRpcParams = function (params) { + this.rpcParams = params; + }; + OpenViduInternal.prototype.sendRequest = function (method, params, callback) { + if (params && params instanceof Function) { + callback = params; + params = undefined; + } + params = params || {}; + if (this.rpcParams && this.rpcParams !== null && this.rpcParams !== undefined) { + for (var index in this.rpcParams) { + if (this.rpcParams.hasOwnProperty(index)) { + params[index] = this.rpcParams[index]; + console.debug('RPC param added to request {' + index + ': ' + this.rpcParams[index] + '}'); + } + } + } + console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}'); + this.jsonRpcClient.send(method, params, callback); + }; + OpenViduInternal.prototype.close = function (forced) { + if (this.isRoomAvailable()) { + this.session.leave(forced, this.jsonRpcClient); + } + }; + ; + OpenViduInternal.prototype.disconnectParticipant = function (stream) { + if (this.isRoomAvailable()) { + this.session.disconnect(stream); + } + }; + //CHAT + OpenViduInternal.prototype.sendMessage = function (message) { + this.sendRequest('sendMessage', { + message: message + }, function (error, response) { + if (error) { + console.error(error); + } + }); + }; + ; + OpenViduInternal.prototype.generateMediaConstraints = function (cameraOptions) { + var mediaConstraints = { + audio: cameraOptions.audio, + video: {} + }; + if (!cameraOptions.video) { + mediaConstraints.video = false; + } + else { + var w = void 0, h = void 0; + switch (cameraOptions.quality) { + case 'LOW': + w = 320; + h = 240; + break; + case 'MEDIUM': + w = 640; + h = 480; + break; + case 'HIGH': + w = 1280; + h = 720; + break; + default: + w = 640; + h = 480; + } + mediaConstraints.video['width'] = { exact: w }; + mediaConstraints.video['height'] = { exact: h }; + //mediaConstraints.video['frameRate'] = { ideal: Number((document.getElementById('frameRate')).value) }; + } + return mediaConstraints; + }; + return OpenViduInternal; +}()); +exports.OpenViduInternal = OpenViduInternal; + +},{"../KurentoUtils/kurento-jsonrpc":45,"./OpenViduError":58,"./SessionInternal":60,"./Stream":61}],60:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Connection_1 = require("./Connection"); +var EventEmitter = require("wolfy87-eventemitter"); +var SECRET_PARAM = '?secret='; +var RECORDER_PARAM = '&recorder='; +var SessionInternal = /** @class */ (function () { + function SessionInternal(openVidu, sessionId) { + this.openVidu = openVidu; + this.ee = new EventEmitter(); + this.remoteStreams = {}; + this.participants = {}; + this.publishersSpeaking = []; + this.connected = false; + this.sessionId = this.getUrlWithoutSecret(sessionId); + this.localParticipant = new Connection_1.Connection(this.openVidu, true, this); + if (!this.openVidu.getWsUri() && !!sessionId) { + this.processOpenViduUrl(sessionId); + } + } + SessionInternal.prototype.processOpenViduUrl = function (url) { + var secret = this.getSecretFromUrl(url); + var recorder = this.getRecorderFromUrl(url); + if (!(secret == null)) { + this.openVidu.setSecret(secret); + } + if (!(recorder == null)) { + this.openVidu.setRecorder(recorder); + } + this.openVidu.setWsUri(this.getFinalUrl(url)); + }; + SessionInternal.prototype.getSecretFromUrl = function (url) { + var secret = ''; + if (url.indexOf(SECRET_PARAM) !== -1) { + var endOfSecret = url.lastIndexOf(RECORDER_PARAM); + if (endOfSecret !== -1) { + secret = url.substring(url.lastIndexOf(SECRET_PARAM) + SECRET_PARAM.length, endOfSecret); + } + else { + secret = url.substring(url.lastIndexOf(SECRET_PARAM) + SECRET_PARAM.length, url.length); + } + } + return secret; + }; + SessionInternal.prototype.getRecorderFromUrl = function (url) { + var recorder = ''; + if (url.indexOf(RECORDER_PARAM) !== -1) { + recorder = url.substring(url.lastIndexOf(RECORDER_PARAM) + RECORDER_PARAM.length, url.length); + } + return new Boolean(recorder).valueOf(); + ; + }; + SessionInternal.prototype.getUrlWithoutSecret = function (url) { + if (!url) { + console.error('sessionId is not defined'); + } + if (url.indexOf(SECRET_PARAM) !== -1) { + url = url.substring(0, url.lastIndexOf(SECRET_PARAM)); + } + return url; + }; + SessionInternal.prototype.getFinalUrl = function (url) { + url = this.getUrlWithoutSecret(url).substring(0, url.lastIndexOf('/')) + '/room'; + if (url.indexOf(".ngrok.io") !== -1) { + // OpenVidu server URL referes to a ngrok IP: secure wss protocol and delete port of URL + url = url.replace("ws://", "wss://"); + var regex = /\.ngrok\.io:\d+/; + url = url.replace(regex, ".ngrok.io"); + } + else if ((url.indexOf("localhost") !== -1) || (url.indexOf("127.0.0.1") != -1)) { + // OpenVidu server URL referes to localhost IP + } + return url; + }; + /* NEW METHODS */ + SessionInternal.prototype.connect = function (token, callback) { + var _this = this; + this.openVidu.connect(function (error) { + if (error) { + callback('ERROR CONNECTING TO OPENVIDU'); + } + else { + if (!token) { + token = _this.randomToken(); + } + var joinParams = { + token: token, + session: _this.sessionId, + metadata: _this.options.metadata, + secret: _this.openVidu.getSecret(), + recorder: _this.openVidu.getRecorder(), + dataChannels: false + }; + if (_this.localParticipant) { + if (Object.keys(_this.localParticipant.getStreams()).some(function (streamId) { + return _this.remoteStreams[streamId].isDataChannelEnabled(); + })) { + joinParams.dataChannels = true; + } + } + _this.openVidu.sendRequest('joinRoom', joinParams, function (error, response) { + if (error) { + callback(error); + } + else { + _this.connected = true; + var exParticipants = response.value; + // IMPORTANT: Update connectionId with value send by server + _this.localParticipant.connectionId = response.id; + _this.participants[response.id] = _this.localParticipant; + var roomEvent = { + participants: new Array(), + streams: new Array() + }; + var length_1 = exParticipants.length; + for (var i = 0; i < length_1; i++) { + var connection = new Connection_1.Connection(_this.openVidu, false, _this, exParticipants[i]); + connection.creationTime = new Date().getTime(); + _this.participants[connection.connectionId] = connection; + roomEvent.participants.push(connection); + var streams = connection.getStreams(); + for (var key in streams) { + roomEvent.streams.push(streams[key]); + if (_this.subscribeToStreams) { + streams[key].subscribe(); + } + } + } + // Update local Connection object properties with values returned by server + _this.localParticipant.data = response.metadata; + _this.localParticipant.creationTime = new Date().getTime(); + // Updates the value of property 'connection' in Session object + _this.ee.emitEvent('update-connection-object', [{ connection: _this.localParticipant }]); + // Own connection created event + _this.ee.emitEvent('connectionCreated', [{ connection: _this.localParticipant }]); + // One connection created event for each existing connection in the session + for (var _i = 0, _a = roomEvent.participants; _i < _a.length; _i++) { + var part = _a[_i]; + _this.ee.emitEvent('connectionCreated', [{ connection: part }]); + } + //if (this.subscribeToStreams) { + for (var _b = 0, _c = roomEvent.streams; _b < _c.length; _b++) { + var stream = _c[_b]; + _this.ee.emitEvent('streamCreated', [{ stream: stream }]); + // Store the remote stream + _this.remoteStreams[stream.streamId] = stream; + } + callback(undefined); + } + }); + } + }); + }; + /* NEW METHODS */ + SessionInternal.prototype.configure = function (options) { + this.options = options; + this.id = options.sessionId; + this.subscribeToStreams = options.subscribeToStreams == null ? true : options.subscribeToStreams; + this.updateSpeakerInterval = options.updateSpeakerInterval || 1500; + this.thresholdSpeaker = options.thresholdSpeaker || -50; + this.activateUpdateMainSpeaker(); + if (!this.openVidu.getWsUri()) { + this.processOpenViduUrl(options.sessionId); + } + }; + SessionInternal.prototype.getId = function () { + return this.id; + }; + SessionInternal.prototype.getSessionId = function () { + return this.sessionId; + }; + SessionInternal.prototype.activateUpdateMainSpeaker = function () { + /*setInterval(() => { + if (this.publishersSpeaking.length > 0) { + this.ee.emitEvent('publisherStartSpeaking', [{ + participantId: this.publishersSpeaking[this.publishersSpeaking.length - 1] + }]); + } + }, this.updateSpeakerInterval);*/ + }; + SessionInternal.prototype.getLocalParticipant = function () { + return this.localParticipant; + }; + SessionInternal.prototype.addEventListener = function (eventName, listener) { + this.ee.on(eventName, listener); + }; + SessionInternal.prototype.addOnceEventListener = function (eventName, listener) { + this.ee.once(eventName, listener); + }; + SessionInternal.prototype.removeListener = function (eventName, listener) { + this.ee.off(eventName, listener); + }; + SessionInternal.prototype.removeEvent = function (eventName) { + this.ee.removeEvent(eventName); + }; + SessionInternal.prototype.emitEvent = function (eventName, eventsArray) { + this.ee.emitEvent(eventName, eventsArray); + }; + SessionInternal.prototype.subscribe = function (stream) { + stream.subscribe(); + }; + SessionInternal.prototype.unsubscribe = function (stream) { + console.info("Unsubscribing from " + stream.connection.connectionId); + this.openVidu.sendRequest('unsubscribeFromVideo', { + sender: stream.connection.connectionId + }, function (error, response) { + if (error) { + console.error("Error unsubscribing from Subscriber", error); + } + else { + console.info("Unsubscribed correctly from " + stream.connection.connectionId); + } + stream.dispose(); + }); + }; + SessionInternal.prototype.onParticipantPublished = function (response) { + // Get the existing Connection created on 'onParticipantJoined' for + // existing participants or create a new one for new participants + var connection = this.participants[response.id]; + if (connection != null) { + // Update existing Connection + response.metadata = connection.data; + connection.setOptions(response); + connection.initRemoteStreams(response); + } + else { + // Create new Connection + connection = new Connection_1.Connection(this.openVidu, false, this, response); + } + var pid = connection.connectionId; + if (!(pid in this.participants)) { + console.debug("Remote Connection not found in connections list by its id [" + pid + "]"); + } + else { + console.debug("Remote Connection found in connections list by its id [" + pid + "]"); + } + this.participants[pid] = connection; + var streams = connection.getStreams(); + for (var key in streams) { + var stream = streams[key]; + if (!this.remoteStreams[stream.streamId]) { + // Avoid race condition between stream.subscribe() in "onParticipantPublished" and in "joinRoom" rpc callback + // This condition is false if openvidu-server sends "participantPublished" event to a subscriber participant that has + // already subscribed to certain stream in the callback of "joinRoom" method + if (this.subscribeToStreams) { + stream.subscribe(); + } + this.ee.emitEvent('streamCreated', [{ stream: stream }]); + // Store the remote stream + this.remoteStreams[stream.streamId] = stream; + } + } + }; + SessionInternal.prototype.onParticipantUnpublished = function (msg) { + var _this = this; + var connection = this.participants[msg.name]; + if (connection !== undefined) { + var streams = connection.getStreams(); + for (var key in streams) { + this.ee.emitEvent('streamDestroyed', [{ + stream: streams[key], + preventDefault: function () { _this.ee.removeEvent('stream-destroyed-default'); } + }]); + this.ee.emitEvent('stream-destroyed-default', [{ + stream: streams[key] + }]); + // Deleting the remote stream + var streamId = streams[key].streamId; + var stream = this.remoteStreams[streamId]; + stream.dispose(); + delete this.remoteStreams[stream.streamId]; + connection.removeStream(stream.streamId); + } + } + else { + console.warn("Participant " + msg.name + + " unknown. Participants: " + + JSON.stringify(this.participants)); + } + }; + SessionInternal.prototype.onParticipantJoined = function (response) { + var connection = new Connection_1.Connection(this.openVidu, false, this, response); + connection.creationTime = new Date().getTime(); + var pid = connection.connectionId; + if (!(pid in this.participants)) { + this.participants[pid] = connection; + } + else { + //use existing so that we don't lose streams info + console.warn("Connection already exists in connections list with " + + "the same connectionId, old:", this.participants[pid], ", joined now:", connection); + connection = this.participants[pid]; + } + this.ee.emitEvent('participant-joined', [{ + connection: connection + }]); + this.ee.emitEvent('connectionCreated', [{ + connection: connection + }]); + }; + SessionInternal.prototype.onParticipantLeft = function (msg) { + var _this = this; + var connection = this.participants[msg.name]; + if (connection !== undefined) { + this.ee.emitEvent('participant-left', [{ + connection: connection + }]); + var streams = connection.getStreams(); + for (var key in streams) { + this.ee.emitEvent('streamDestroyed', [{ + stream: streams[key], + preventDefault: function () { _this.ee.removeEvent('stream-destroyed-default'); } + }]); + this.ee.emitEvent('stream-destroyed-default', [{ + stream: streams[key] + }]); + // Deleting the remote stream + var streamId = streams[key].streamId; + delete this.remoteStreams[streamId]; + } + connection.dispose(); + delete this.participants[msg.name]; + this.ee.emitEvent('connectionDestroyed', [{ + connection: connection + }]); + } + else { + console.warn("Participant " + msg.name + + " unknown. Participants: " + + JSON.stringify(this.participants)); + } + }; + ; + SessionInternal.prototype.onParticipantEvicted = function (msg) { + this.ee.emitEvent('participant-evicted', [{ + localParticipant: this.localParticipant + }]); + }; + ; + SessionInternal.prototype.onNewMessage = function (msg) { + console.info("New signal: " + JSON.stringify(msg)); + this.ee.emitEvent('signal', [{ + data: msg.data, + from: this.participants[msg.from], + type: msg.type + }]); + this.ee.emitEvent('signal:' + msg.type, [{ + data: msg.data, + from: this.participants[msg.from], + type: msg.type + }]); + }; + SessionInternal.prototype.recvIceCandidate = function (msg) { + var candidate = { + candidate: msg.candidate, + sdpMid: msg.sdpMid, + sdpMLineIndex: msg.sdpMLineIndex + }; + var connection = this.participants[msg.endpointName]; + if (!connection) { + console.error("Participant not found for endpoint " + + msg.endpointName + ". Ice candidate will be ignored.", candidate); + return; + } + var streams = connection.getStreams(); + var _loop_1 = function (key) { + var stream = streams[key]; + stream.getWebRtcPeer().addIceCandidate(candidate, function (error) { + if (error) { + console.error("Error adding candidate for " + key + + " stream of endpoint " + msg.endpointName + + ": " + error); + } + }); + }; + for (var key in streams) { + _loop_1(key); + } + }; + SessionInternal.prototype.onRoomClosed = function (msg) { + console.info("Session closed: " + JSON.stringify(msg)); + var room = msg.room; + if (room !== undefined) { + this.ee.emitEvent('room-closed', [{ + room: room + }]); + } + else { + console.warn("Session undefined on session closed", msg); + } + }; + SessionInternal.prototype.onLostConnection = function () { + if (!this.connected) { + console.warn('Not connected to session: if you are not debugging, this is probably a certificate error'); + if (window.confirm('If you are not debugging, this is probably a certificate error at \"' + this.openVidu.getOpenViduServerURL() + '\"\n\nClick OK to navigate and accept it')) { + location.assign(this.openVidu.getOpenViduServerURL() + '/accept-certificate'); + } + ; + return; + } + console.warn('Lost connection in Session ' + this.id); + var room = this.id; + if (room !== undefined) { + this.ee.emitEvent('lost-connection', [{ room: room }]); + } + else { + console.warn('Session undefined when lost connection'); + } + }; + SessionInternal.prototype.onMediaError = function (params) { + console.error("Media error: " + JSON.stringify(params)); + var error = params.error; + if (error) { + this.ee.emitEvent('error-media', [{ + error: error + }]); + } + else { + console.warn("Received undefined media error. Params:", params); + } + }; + /* + * forced means the user was evicted, no need to send the 'leaveRoom' request + */ + SessionInternal.prototype.leave = function (forced, jsonRpcClient) { + forced = !!forced; + console.info("Leaving Session (forced=" + forced + ")"); + if (this.connected && !forced) { + this.openVidu.sendRequest('leaveRoom', function (error, response) { + if (error) { + console.error(error); + } + jsonRpcClient.close(); + }); + } + else { + jsonRpcClient.close(); + } + this.connected = false; + if (this.participants) { + for (var pid in this.participants) { + this.participants[pid].dispose(); + delete this.participants[pid]; + } + } + }; + SessionInternal.prototype.disconnect = function (stream) { + var connection = stream.getParticipant(); + if (!connection) { + console.error("Stream to disconnect has no participant", stream); + return; + } + delete this.participants[connection.connectionId]; + connection.dispose(); + if (connection === this.localParticipant) { + console.info("Unpublishing my media (I'm " + connection.connectionId + ")"); + delete this.localParticipant; + this.openVidu.sendRequest('unpublishVideo', function (error, response) { + if (error) { + console.error(error); + } + else { + console.info("Media unpublished correctly"); + } + }); + } + else { + this.unsubscribe(stream); + } + }; + SessionInternal.prototype.unpublish = function (publisher) { + var _this = this; + var stream = publisher.stream; + if (!stream.connection) { + console.error("The associated Connection object of this Publisher is null", stream); + return; + } + else if (stream.connection !== this.localParticipant) { + console.error("The associated Connection object of this Publisher is not your local Connection." + + "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method", stream); + return; + } + else { + stream.dispose(); + console.info("Unpublishing local media (" + stream.connection.connectionId + ")"); + this.openVidu.sendRequest('unpublishVideo', function (error, response) { + if (error) { + console.error(error); + } + else { + console.info("Media unpublished correctly"); + } + }); + stream.isReadyToPublish = false; + stream.isScreenRequestedReady = false; + delete stream.connection.getStreams()[stream.streamId]; + publisher.ee.emitEvent('streamDestroyed', [{ + stream: publisher.stream, + preventDefault: function () { _this.ee.removeEvent('stream-destroyed-default'); } + }]); + publisher.ee.emitEvent('stream-destroyed-default', [{ + stream: publisher.stream + }]); + } + }; + SessionInternal.prototype.getRemoteStreams = function () { + return this.remoteStreams; + }; + SessionInternal.prototype.addParticipantSpeaking = function (participantId) { + this.publishersSpeaking.push(participantId); + this.ee.emitEvent('publisherStartSpeaking', [{ + participantId: participantId + }]); + }; + SessionInternal.prototype.removeParticipantSpeaking = function (participantId) { + var pos = -1; + for (var i = 0; i < this.publishersSpeaking.length; i++) { + if (this.publishersSpeaking[i] == participantId) { + pos = i; + break; + } + } + if (pos != -1) { + this.publishersSpeaking.splice(pos, 1); + this.ee.emitEvent('publisherStopSpeaking', [{ + participantId: participantId + }]); + } + }; + SessionInternal.prototype.stringClientMetadata = function (metadata) { + if (!(typeof metadata === 'string')) { + return JSON.stringify(metadata); + } + else { + return metadata; + } + }; + SessionInternal.prototype.randomToken = function () { + return Math.random().toString(36).slice(2) + Math.random().toString(36).slice(2); + }; + return SessionInternal; +}()); +exports.SessionInternal = SessionInternal; + +},{"./Connection":56,"wolfy87-eventemitter":38}],61:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var OpenViduError_1 = require("./OpenViduError"); +var WebRtcStats_1 = require("./WebRtcStats"); +var EventEmitter = require("wolfy87-eventemitter"); +var kurentoUtils = require("../KurentoUtils/kurento-utils-js"); +var adapter = require("webrtc-adapter"); +if (window) { + window["adapter"] = adapter; +} +function jq(id) { + return id.replace(/(@|:|\.|\[|\]|,)/g, "\\$1"); +} +function show(id) { + document.getElementById(jq(id)).style.display = 'block'; +} +function hide(id) { + document.getElementById(jq(id)).style.display = 'none'; +} +var Stream = /** @class */ (function () { + function Stream(openVidu, local, room, options) { + var _this = this; + this.openVidu = openVidu; + this.local = local; + this.room = room; + this.ee = new EventEmitter(); + this.showMyRemote = false; + this.localMirrored = false; + this.chanId = 0; + this.dataChannelOpened = false; + this.isReadyToPublish = false; + this.isPublisherPublished = false; + this.isVideoELementCreated = false; + this.accessIsAllowed = false; + this.accessIsDenied = false; + this.isScreenRequestedReady = false; + this.isScreenRequested = false; + if (options !== 'screen-options') { + // Outbound stream (not screen share) or Inbound stream + if ('id' in options) { + this.inboundOptions = options; + } + else { + this.outboundOptions = options; + } + this.streamId = (options.id != null) ? options.id : ((options.sendVideo) ? "CAMERA" : "MICRO"); + this.typeOfVideo = (options.typeOfVideo != null) ? options.typeOfVideo : ''; + if ('recvAudio' in options) { + // Set Connection for an Inbound stream (for Outbound streams will be set on Session.Publish(Publisher)) + this.connection = options.connection; + } + } + else { + // Outbound stream for screen share + this.isScreenRequested = true; + this.typeOfVideo = 'SCREEN'; + } + this.addEventListener('mediastream-updated', function () { + if (_this.video) + _this.video.srcObject = _this.mediaStream; + console.debug("Video srcObject [" + _this.mediaStream + "] added to stream [" + _this.streamId + "]"); + }); + } + Stream.prototype.emitStreamReadyEvent = function () { + this.ee.emitEvent('stream-ready'); + }; + Stream.prototype.removeVideo = function (parentElement) { + if (this.video) { + if (typeof parentElement === "string") { + document.getElementById(parentElement).removeChild(this.video); + this.ee.emitEvent('video-removed'); + } + else if (parentElement instanceof Element) { + parentElement.removeChild(this.video); + this.ee.emitEvent('video-removed'); + } + else if (!parentElement) { + if (document.getElementById(this.parentId)) { + document.getElementById(this.parentId).removeChild(this.video); + this.ee.emitEvent('video-removed'); + } + } + delete this.video; + } + }; + Stream.prototype.getVideoElement = function () { + return this.video; + }; + Stream.prototype.setVideoElement = function (video) { + if (!!video) + this.video = video; + }; + Stream.prototype.getParentId = function () { + return this.parentId; + }; + Stream.prototype.getRecvVideo = function () { + return this.inboundOptions.recvVideo; + }; + Stream.prototype.getRecvAudio = function () { + return this.inboundOptions.recvAudio; + }; + Stream.prototype.getSendVideo = function () { + return this.outboundOptions.sendVideo; + }; + Stream.prototype.getSendAudio = function () { + return this.outboundOptions.sendAudio; + }; + Stream.prototype.subscribeToMyRemote = function () { + this.showMyRemote = true; + }; + Stream.prototype.displayMyRemote = function () { + return this.showMyRemote; + }; + Stream.prototype.mirrorLocalStream = function (wr) { + this.showMyRemote = true; + this.localMirrored = true; + if (wr) { + this.mediaStream = wr; + this.ee.emitEvent('mediastream-updated'); + } + }; + Stream.prototype.isLocalMirrored = function () { + return this.localMirrored; + }; + Stream.prototype.getChannelName = function () { + return this.streamId + '_' + this.chanId++; + }; + Stream.prototype.isDataChannelEnabled = function () { + return this.outboundOptions.dataChannel; + }; + Stream.prototype.isDataChannelOpened = function () { + return this.dataChannelOpened; + }; + Stream.prototype.onDataChannelOpen = function (event) { + console.debug('Data channel is opened'); + this.dataChannelOpened = true; + }; + Stream.prototype.onDataChannelClosed = function (event) { + console.debug('Data channel is closed'); + this.dataChannelOpened = false; + }; + Stream.prototype.sendData = function (data) { + if (this.wp === undefined) { + throw new Error('WebRTC peer has not been created yet'); + } + if (!this.dataChannelOpened) { + throw new Error('Data channel is not opened'); + } + console.info("Sending through data channel: " + data); + this.wp.send(data); + }; + Stream.prototype.getMediaStream = function () { + return this.mediaStream; + }; + Stream.prototype.getWebRtcPeer = function () { + return this.wp; + }; + Stream.prototype.getRTCPeerConnection = function () { + return this.wp.peerConnection; + }; + Stream.prototype.addEventListener = function (eventName, listener) { + this.ee.addListener(eventName, listener); + }; + Stream.prototype.addOnceEventListener = function (eventName, listener) { + this.ee.addOnceListener(eventName, listener); + }; + Stream.prototype.removeListener = function (eventName) { + this.ee.removeAllListeners(eventName); + }; + Stream.prototype.showSpinner = function (spinnerParentId) { + var progress = document.createElement('div'); + progress.id = 'progress-' + this.streamId; + progress.style.background = "center transparent url('img/spinner.gif') no-repeat"; + var spinnerParent = document.getElementById(spinnerParentId); + if (spinnerParent) { + spinnerParent.appendChild(progress); + } + }; + Stream.prototype.hideSpinner = function (spinnerId) { + spinnerId = (spinnerId === undefined) ? this.streamId : spinnerId; + hide('progress-' + spinnerId); + }; + Stream.prototype.playOnlyVideo = function (parentElement, thumbnailId) { + var _this = this; + if (!!parentElement) { + this.video = document.createElement('video'); + this.video.id = (this.local ? 'local-' : 'remote-') + 'video-' + this.streamId; + this.video.autoplay = true; + this.video.controls = false; + this.ee.emitEvent('mediastream-updated'); + if (this.local && !this.displayMyRemote()) { + this.video.muted = true; + this.video.oncanplay = function () { + console.info("Local 'Stream' with id [" + _this.streamId + "] video is now playing"); + _this.ee.emitEvent('video-is-playing', [{ + element: _this.video + }]); + }; + } + else { + this.video.title = this.streamId; + } + if (typeof parentElement === "string") { + this.parentId = parentElement; + var parentElementDom = document.getElementById(parentElement); + if (parentElementDom) { + this.video = parentElementDom.appendChild(this.video); + this.ee.emitEvent('video-element-created-by-stream', [{ + element: this.video + }]); + this.isVideoELementCreated = true; + } + } + else { + this.parentId = parentElement.id; + this.video = parentElement.appendChild(this.video); + } + this.isReadyToPublish = true; + return this.video; + } + return null; + }; + Stream.prototype.playThumbnail = function (thumbnailId) { + var container = document.createElement('div'); + container.className = "participant"; + container.id = this.streamId; + var thumbnail = document.getElementById(thumbnailId); + if (thumbnail) { + thumbnail.appendChild(container); + } + var name = document.createElement('div'); + container.appendChild(name); + var userName = this.streamId.replace('_webcam', ''); + if (userName.length >= 16) { + userName = userName.substring(0, 16) + "..."; + } + name.appendChild(document.createTextNode(userName)); + name.id = "name-" + this.streamId; + name.className = "name"; + name.title = this.streamId; + this.showSpinner(thumbnailId); + return this.playOnlyVideo(container, thumbnailId); + }; + Stream.prototype.getParticipant = function () { + return this.connection; + }; + Stream.prototype.requestCameraAccess = function (callback) { + var _this = this; + var constraints = this.outboundOptions.mediaConstraints; + /*let constraints2 = { + audio: true, + video: { + width: { + ideal: 1280 + }, + frameRate: { + ideal: 15 + } + } + };*/ + this.userMediaHasVideo(function (hasVideo) { + if (!hasVideo) { + if (_this.outboundOptions.sendVideo) { + callback(new OpenViduError_1.OpenViduError("NO_VIDEO_DEVICE" /* NO_VIDEO_DEVICE */, 'You have requested camera access but there is no video input device available. Trying to connect with an audio input device only'), _this); + } + if (!_this.outboundOptions.sendAudio) { + callback(new OpenViduError_1.OpenViduError("NO_INPUT_DEVICE" /* NO_INPUT_DEVICE */, 'You must init Publisher object with audio or video streams enabled'), undefined); + } + else { + constraints.video = false; + _this.outboundOptions.sendVideo = false; + _this.requestCameraAccesAux(constraints, callback); + } + } + else { + _this.requestCameraAccesAux(constraints, callback); + } + }); + }; + Stream.prototype.requestCameraAccesAux = function (constraints, callback) { + var _this = this; + console.log(constraints); + navigator.mediaDevices.getUserMedia(constraints) + .then(function (userStream) { + _this.cameraAccessSuccess(userStream, callback); + }) + .catch(function (error) { + _this.accessIsDenied = true; + _this.accessIsAllowed = false; + var errorName; + var errorMessage = error.toString(); + ; + if (!_this.isScreenRequested) { + errorName = _this.outboundOptions.sendVideo ? "CAMERA_ACCESS_DENIED" /* CAMERA_ACCESS_DENIED */ : "MICROPHONE_ACCESS_DENIED" /* MICROPHONE_ACCESS_DENIED */; + } + else { + errorName = "SCREEN_CAPTURE_DENIED" /* SCREEN_CAPTURE_DENIED */; // This code is only reachable for Firefox + } + callback(new OpenViduError_1.OpenViduError(errorName, errorMessage), undefined); + }); + }; + Stream.prototype.cameraAccessSuccess = function (userStream, callback) { + this.accessIsAllowed = true; + this.accessIsDenied = false; + this.ee.emitEvent('access-allowed-by-publisher'); + if (userStream.getAudioTracks()[0] != null) { + userStream.getAudioTracks()[0].enabled = this.outboundOptions.activeAudio; + } + if (userStream.getVideoTracks()[0] != null) { + userStream.getVideoTracks()[0].enabled = this.outboundOptions.activeVideo; + } + this.mediaStream = userStream; + this.ee.emitEvent('mediastream-updated'); + callback(undefined, this); + }; + Stream.prototype.userMediaHasVideo = function (callback) { + // If the user is going to publish its screen there's a video source + if (this.isScreenRequested) { + callback(true); + return; + } + else { + // List all input devices and serach for a video kind + navigator.mediaDevices.enumerateDevices().then(function (mediaDevices) { + var videoInput = mediaDevices.filter(function (deviceInfo) { + return deviceInfo.kind === 'videoinput'; + })[0]; + callback(videoInput != null); + }); + } + }; + Stream.prototype.publishVideoCallback = function (error, sdpOfferParam, wp) { + var _this = this; + if (error) { + return console.error("(publish) SDP offer error: " + + JSON.stringify(error)); + } + console.debug("Sending SDP offer to publish as " + + this.streamId, sdpOfferParam); + this.openVidu.sendRequest("publishVideo", { + sdpOffer: sdpOfferParam, + doLoopback: this.displayMyRemote() || false, + audioActive: this.outboundOptions.sendAudio, + videoActive: this.outboundOptions.sendVideo, + typeOfVideo: ((this.outboundOptions.sendVideo) ? ((this.isScreenRequested) ? 'SCREEN' : 'CAMERA') : '') + }, function (error, response) { + if (error) { + console.error("Error on publishVideo: " + JSON.stringify(error)); + } + else { + _this.processSdpAnswer(response.sdpAnswer); + console.info("'Publisher' succesfully published to session"); + } + }); + }; + Stream.prototype.startVideoCallback = function (error, sdpOfferParam, wp) { + var _this = this; + if (error) { + return console.error("(subscribe) SDP offer error: " + + JSON.stringify(error)); + } + console.debug("Sending SDP offer to subscribe to " + + this.streamId, sdpOfferParam); + this.openVidu.sendRequest("receiveVideoFrom", { + sender: this.streamId, + sdpOffer: sdpOfferParam + }, function (error, response) { + if (error) { + console.error("Error on recvVideoFrom: " + JSON.stringify(error)); + } + else { + _this.processSdpAnswer(response.sdpAnswer); + } + }); + }; + Stream.prototype.initWebRtcPeer = function (sdpOfferCallback) { + var _this = this; + if (this.local) { + var userMediaConstraints = { + audio: this.outboundOptions.sendAudio, + video: this.outboundOptions.sendVideo + }; + var options = { + videoStream: this.mediaStream, + mediaConstraints: userMediaConstraints, + onicecandidate: this.connection.sendIceCandidate.bind(this.connection), + }; + if (this.outboundOptions.dataChannel) { + options.dataChannelConfig = { + id: this.getChannelName(), + onopen: this.onDataChannelOpen, + onclose: this.onDataChannelClosed + }; + options.dataChannels = true; + } + if (this.displayMyRemote()) { + this.wp = kurentoUtils.WebRtcPeer.WebRtcPeerSendrecv(options, function (error) { + if (error) { + return console.error(error); + } + _this.wp.generateOffer(sdpOfferCallback.bind(_this)); + }); + } + else { + this.wp = kurentoUtils.WebRtcPeer.WebRtcPeerSendonly(options, function (error) { + if (error) { + return console.error(error); + } + _this.wp.generateOffer(sdpOfferCallback.bind(_this)); + }); + } + this.isPublisherPublished = true; + this.ee.emitEvent('stream-created-by-publisher'); + } + else { + var offerConstraints = { + audio: this.inboundOptions.recvAudio, + video: this.inboundOptions.recvVideo + }; + console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer", offerConstraints); + var options = { + onicecandidate: this.connection.sendIceCandidate.bind(this.connection), + mediaConstraints: offerConstraints + }; + this.wp = kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly(options, function (error) { + if (error) { + return console.error(error); + } + _this.wp.generateOffer(sdpOfferCallback.bind(_this)); + }); + } + console.debug("Waiting for SDP offer to be generated (" + + (this.local ? "local" : "remote") + " 'Stream': " + this.streamId + ")"); + }; + Stream.prototype.publish = function () { + var _this = this; + // FIXME: Throw error when stream is not local + if (this.isReadyToPublish) { + this.initWebRtcPeer(this.publishVideoCallback); + } + else { + this.ee.once('stream-ready', function (streamEvent) { + _this.publish(); + }); + } + // FIXME: Now we have coupled connecting to a room and adding a + // stream to this room. But in the new API, there are two steps. + // This is the second step. For now, it do nothing. + }; + Stream.prototype.subscribe = function () { + // FIXME: In the current implementation all participants are subscribed + // automatically to all other participants. We use this method only to + // negotiate SDP + this.initWebRtcPeer(this.startVideoCallback); + }; + Stream.prototype.processSdpAnswer = function (sdpAnswer) { + var _this = this; + var answer = new RTCSessionDescription({ + type: 'answer', + sdp: sdpAnswer, + }); + console.debug(this.streamId + ": set peer connection with recvd SDP answer", sdpAnswer); + var participantId = this.streamId; + var pc = this.wp.peerConnection; + pc.setRemoteDescription(answer, function () { + // Avoids to subscribe to your own stream remotely + // except when showMyRemote is true + if (!_this.local || _this.displayMyRemote()) { + _this.mediaStream = pc.getRemoteStreams()[0]; + console.debug("Peer remote stream", _this.mediaStream); + if (_this.mediaStream != undefined) { + _this.ee.emitEvent('mediastream-updated'); + if (_this.mediaStream.getAudioTracks()[0] != null) { + _this.speechEvent = kurentoUtils.WebRtcPeer.hark(_this.mediaStream, { threshold: _this.room.thresholdSpeaker }); + _this.speechEvent.on('speaking', function () { + //this.room.addParticipantSpeaking(participantId); + _this.room.emitEvent('publisherStartSpeaking', [{ + connection: _this.connection, + streamId: _this.streamId + }]); + }); + _this.speechEvent.on('stopped_speaking', function () { + //this.room.removeParticipantSpeaking(participantId); + _this.room.emitEvent('publisherStopSpeaking', [{ + connection: _this.connection, + streamId: _this.streamId + }]); + }); + } + } + if (!!_this.video) { + // let thumbnailId = this.video.thumb; + _this.video.oncanplay = function () { + if (_this.local && _this.displayMyRemote()) { + console.info("Your own remote 'Stream' with id [" + _this.streamId + "] video is now playing"); + _this.ee.emitEvent('remote-video-is-playing', [{ + element: _this.video + }]); + } + else if (!_this.local && !_this.displayMyRemote()) { + console.info("Remote 'Stream' with id [" + _this.streamId + "] video is now playing"); + _this.ee.emitEvent('video-is-playing', [{ + element: _this.video + }]); + } + //show(thumbnailId); + //this.hideSpinner(this.streamId); + }; + } + _this.room.emitEvent('stream-subscribed', [{ + stream: _this + }]); + } + _this.initWebRtcStats(); + }, function (error) { + console.error(_this.streamId + ": Error setting SDP to the peer connection: " + + JSON.stringify(error)); + }); + }; + Stream.prototype.unpublish = function () { + if (this.wp) { + this.wp.dispose(); + } + else { + if (this.mediaStream) { + this.mediaStream.getAudioTracks().forEach(function (track) { + track.stop && track.stop(); + }); + this.mediaStream.getVideoTracks().forEach(function (track) { + track.stop && track.stop(); + }); + } + } + if (this.speechEvent) { + this.speechEvent.stop(); + } + console.info(this.streamId + ": Stream '" + this.streamId + "' unpublished"); + }; + Stream.prototype.dispose = function () { + function disposeElement(element) { + if (element && element.parentNode) { + element.parentNode.removeChild(element); + } + } + disposeElement("progress-" + this.streamId); + if (this.wp) { + this.wp.dispose(); + } + else { + if (this.mediaStream) { + this.mediaStream.getAudioTracks().forEach(function (track) { + track.stop && track.stop(); + }); + this.mediaStream.getVideoTracks().forEach(function (track) { + track.stop && track.stop(); + }); + } + } + if (this.speechEvent) { + this.speechEvent.stop(); + } + this.stopWebRtcStats(); + console.info((this.local ? "Local " : "Remote ") + "'Stream' with id [" + this.streamId + "]' has been succesfully disposed"); + }; + Stream.prototype.configureScreenOptions = function (options) { + this.outboundOptions = options; + this.streamId = "SCREEN"; + }; + Stream.prototype.initWebRtcStats = function () { + this.webRtcStats = new WebRtcStats_1.WebRtcStats(this); + this.webRtcStats.initWebRtcStats(); + }; + Stream.prototype.stopWebRtcStats = function () { + if (this.webRtcStats != null && this.webRtcStats.isEnabled()) { + this.webRtcStats.stopWebRtcStats(); + } + }; + return Stream; +}()); +exports.Stream = Stream; + +},{"../KurentoUtils/kurento-utils-js":50,"./OpenViduError":58,"./WebRtcStats":62,"webrtc-adapter":26,"wolfy87-eventemitter":38}],62:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var DetectRTC = require("../KurentoUtils/DetectRTC"); +var WebRtcStats = /** @class */ (function () { + function WebRtcStats(stream) { + this.stream = stream; + this.webRtcStatsEnabled = false; + this.statsInterval = 1; + this.stats = { + "inbound": { + "audio": { + "bytesReceived": 0, + "packetsReceived": 0, + "packetsLost": 0 + }, + "video": { + "bytesReceived": 0, + "packetsReceived": 0, + "packetsLost": 0, + "framesDecoded": 0, + "nackCount": 0 + } + }, + "outbound": { + "audio": { + "bytesSent": 0, + "packetsSent": 0, + }, + "video": { + "bytesSent": 0, + "packetsSent": 0, + "framesEncoded": 0, + "nackCount": 0 + } + } + }; + } + WebRtcStats.prototype.isEnabled = function () { + return this.webRtcStatsEnabled; + }; + WebRtcStats.prototype.initWebRtcStats = function () { + var _this = this; + var elastestInstrumentation = localStorage.getItem('elastest-instrumentation'); + if (elastestInstrumentation) { + // ElasTest instrumentation object found in local storage + console.warn("WebRtc stats enabled for stream " + this.stream.streamId + " of connection " + this.stream.connection.connectionId); + this.webRtcStatsEnabled = true; + var instrumentation_1 = JSON.parse(elastestInstrumentation); + this.statsInterval = instrumentation_1.webrtc.interval; // Interval in seconds + console.warn("localStorage item: " + JSON.stringify(instrumentation_1)); + this.webRtcStatsIntervalId = setInterval(function () { + _this.sendStatsToHttpEndpoint(instrumentation_1); + }, this.statsInterval * 1000); + return; + } + console.debug("WebRtc stats not enabled"); + }; + WebRtcStats.prototype.stopWebRtcStats = function () { + if (this.webRtcStatsEnabled) { + clearInterval(this.webRtcStatsIntervalId); + console.warn("WebRtc stats stopped for disposed stream " + this.stream.streamId + " of connection " + this.stream.connection.connectionId); + } + }; + WebRtcStats.prototype.sendStatsToHttpEndpoint = function (instrumentation) { + var _this = this; + var sendPost = function (json) { + var http = new XMLHttpRequest(); + var url = instrumentation.webrtc.httpEndpoint; + http.open("POST", url, true); + http.setRequestHeader("Content-type", "application/json"); + http.onreadystatechange = function () { + if (http.readyState == 4 && http.status == 200) { + console.log("WebRtc stats succesfully sent to " + url + " for stream " + _this.stream.streamId + " of connection " + _this.stream.connection.connectionId); + } + }; + http.send(json); + }; + var f = function (stats) { + if (DetectRTC.browser.name === 'Firefox') { + stats.forEach(function (stat) { + var json = {}; + if ((stat.type === 'inbound-rtp') && + ( + // Avoid firefox empty outbound-rtp statistics + stat.nackCount != null && + stat.isRemote === false && + stat.id.startsWith('inbound') && + stat.remoteId.startsWith('inbound'))) { + var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; + var jitter = stat.jitter * 1000; + var metrics = { + "bytesReceived": (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, + "jitter": jitter, + "packetsReceived": (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, + "packetsLost": (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval + }; + var units = { + "bytesReceived": "bytes", + "jitter": "ms", + "packetsReceived": "packets", + "packetsLost": "packets" + }; + if (stat.mediaType === 'video') { + metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; + metrics['nackCount'] = (stat.nackCount - _this.stats.inbound.video.nackCount) / _this.statsInterval; + units['framesDecoded'] = "frames"; + units['nackCount'] = "packets"; + _this.stats.inbound.video.framesDecoded = stat.framesDecoded; + _this.stats.inbound.video.nackCount = stat.nackCount; + } + _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; + _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; + _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; + json = { + "@timestamp": new Date(stat.timestamp).toISOString(), + "exec": instrumentation.exec, + "component": instrumentation.component, + "stream": "webRtc", + "type": metricId, + "stream_type": "composed_metrics", + "units": units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + else if ((stat.type === 'outbound-rtp') && + ( + // Avoid firefox empty inbound-rtp statistics + stat.isRemote === false && + stat.id.toLowerCase().includes('outbound'))) { + var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; + var metrics = { + "bytesSent": (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, + "packetsSent": (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval + }; + var units = { + "bytesSent": "bytes", + "packetsSent": "packets" + }; + if (stat.mediaType === 'video') { + metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; + units['framesEncoded'] = "frames"; + _this.stats.outbound.video.framesEncoded = stat.framesEncoded; + } + _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; + _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; + json = { + "@timestamp": new Date(stat.timestamp).toISOString(), + "exec": instrumentation.exec, + "component": instrumentation.component, + "stream": "webRtc", + "type": metricId, + "stream_type": "composed_metrics", + "units": units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + }); + } + else if (DetectRTC.browser.name === 'Chrome') { + for (var _i = 0, _a = Object.keys(stats); _i < _a.length; _i++) { + var key = _a[_i]; + var stat = stats[key]; + if (stat.type === 'ssrc') { + var json = {}; + if ('bytesReceived' in stat && ((stat.mediaType === 'audio' && 'audioOutputLevel' in stat) || + (stat.mediaType === 'video' && 'qpSum' in stat))) { + // inbound-rtp + var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; + var metrics = { + "bytesReceived": (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, + "jitter": stat.googJitterBufferMs, + "packetsReceived": (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, + "packetsLost": (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval + }; + var units = { + "bytesReceived": "bytes", + "jitter": "ms", + "packetsReceived": "packets", + "packetsLost": "packets" + }; + if (stat.mediaType === 'video') { + metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; + metrics['nackCount'] = (stat.googNacksSent - _this.stats.inbound.video.nackCount) / _this.statsInterval; + units['framesDecoded'] = "frames"; + units['nackCount'] = "packets"; + _this.stats.inbound.video.framesDecoded = stat.framesDecoded; + _this.stats.inbound.video.nackCount = stat.googNacksSent; + } + _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; + _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; + _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; + json = { + "@timestamp": new Date(stat.timestamp).toISOString(), + "exec": instrumentation.exec, + "component": instrumentation.component, + "stream": "webRtc", + "type": metricId, + "stream_type": "composed_metrics", + "units": units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + else if ('bytesSent' in stat) { + // outbound-rtp + var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; + var metrics = { + "bytesSent": (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, + "packetsSent": (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval + }; + var units = { + "bytesSent": "bytes", + "packetsSent": "packets" + }; + if (stat.mediaType === 'video') { + metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; + units['framesEncoded'] = "frames"; + _this.stats.outbound.video.framesEncoded = stat.framesEncoded; + } + _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; + _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; + json = { + "@timestamp": new Date(stat.timestamp).toISOString(), + "exec": instrumentation.exec, + "component": instrumentation.component, + "stream": "webRtc", + "type": metricId, + "stream_type": "composed_metrics", + "units": units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + } + } + } + }; + this.getStatsAgnostic(this.stream.getRTCPeerConnection(), null, f, function (error) { console.log(error); }); + }; + WebRtcStats.prototype.standardizeReport = function (response) { + if (DetectRTC.browser.name === 'Firefox') { + return response; + } + var standardReport = {}; + response.result().forEach(function (report) { + var standardStats = { + id: report.id, + timestamp: report.timestamp, + type: report.type + }; + report.names().forEach(function (name) { + standardStats[name] = report.stat(name); + }); + standardReport[standardStats.id] = standardStats; + }); + return standardReport; + }; + WebRtcStats.prototype.getStatsAgnostic = function (pc, selector, successCb, failureCb) { + var _this = this; + if (DetectRTC.browser.name === 'Firefox') { + // getStats takes args in different order in Chrome and Firefox + return pc.getStats(selector, function (response) { + var report = _this.standardizeReport(response); + successCb(report); + }, failureCb); + } + else if (DetectRTC.browser.name === 'Chrome') { + // In Chrome, the first two arguments are reversed + return pc.getStats(function (response) { + var report = _this.standardizeReport(response); + successCb(report); + }, selector, failureCb); + } + }; + return WebRtcStats; +}()); +exports.WebRtcStats = WebRtcStats; + +},{"../KurentoUtils/DetectRTC":39}],63:[function(require,module,exports){ +// Last time updated at Feb 16, 2017, 08:32:23 +// Latest file can be found here: https://cdn.webrtc-experiment.com/getScreenId.js +// Muaz Khan - www.MuazKhan.com +// MIT License - www.WebRTC-Experiment.com/licence +// Documentation - https://github.com/muaz-khan/getScreenId. +// ______________ +// getScreenId.js +/* +getScreenId(function (error, sourceId, screen_constraints) { + // error == null || 'permission-denied' || 'not-installed' || 'installed-disabled' || 'not-chrome' + // sourceId == null || 'string' || 'firefox' + + if(sourceId == 'firefox') { + navigator.mozGetUserMedia(screen_constraints, onSuccess, onFailure); + } + else navigator.webkitGetUserMedia(screen_constraints, onSuccess, onFailure); +}); +*/ +window.getScreenId = function (callback) { + // for Firefox: + // sourceId == 'firefox' + // screen_constraints = {...} + if (!!navigator.mozGetUserMedia) { + callback(null, 'firefox', { + video: { + mozMediaSource: 'window', + mediaSource: 'window' + } + }); + 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)); + } + if (event.data.chromeExtensionStatus) { + callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus)); + } + // this event listener is no more needed + window.removeEventListener('message', onIFrameCallback); + } + setTimeout(postGetSourceIdMessage, 100); +}; +function getScreenConstraints(error, sourceId) { + 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 (sourceId) { + screen_constraints.video.mandatory.chromeMediaSourceId = sourceId; + } + return screen_constraints; +} +function postGetSourceIdMessage() { + if (!iframe) { + loadIFrame(postGetSourceIdMessage); + return; + } + if (!iframe.isLoaded) { + setTimeout(postGetSourceIdMessage, 100); + return; + } + iframe.contentWindow.postMessage({ + captureSourceId: true + }, '*'); +} +var iframe; +// this function is used in RTCMultiConnection v3 +window.getScreenConstraints = function (callback) { + loadIFrame(function () { + getScreenId(function (error, sourceId, screen_constraints) { + 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://www.webrtc-experiment.com/getSourceId/'; // https://wwww.yourdomain.com/getScreenId.html + iframe.style.display = 'none'; + (document.body || document.documentElement).appendChild(iframe); +} +window.getChromeExtensionStatus = function (callback) { + // for Firefox: + 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); + } + // this event listener is no more needed + 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 = getScreenId; +exports.getChromeExtensionStatus = getChromeExtensionStatus; + +},{}]},{},[51]) +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL21lcmdlL21lcmdlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL25vcm1hbGljZS9pbmRleC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9wcm9jZXNzL2Jyb3dzZXIuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvcnRjcGVlcmNvbm5lY3Rpb24tc2hpbS9ydGNwZWVyY29ubmVjdGlvbi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNmb3JtL2xpYi9ncmFtbWFyLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL3NkcC10cmFuc2Zvcm0vbGliL2luZGV4LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL3NkcC10cmFuc2Zvcm0vbGliL3BhcnNlci5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNmb3JtL2xpYi93cml0ZXIuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvc2RwLXRyYW5zbGF0b3IvbGliL2FycmF5LWVxdWFscy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNsYXRvci9saWIvaW5kZXguanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvc2RwLXRyYW5zbGF0b3IvbGliL2ludGVyb3AuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvc2RwLXRyYW5zbGF0b3IvbGliL3RyYW5zZm9ybS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9zZHAvc2RwLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL3VhLXBhcnNlci1qcy9zcmMvdWEtcGFyc2VyLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL3V1aWQvaW5kZXguanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvdXVpZC9saWIvYnl0ZXNUb1V1aWQuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvdXVpZC9saWIvcm5nLWJyb3dzZXIuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvdXVpZC92MS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy91dWlkL3Y0LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL3dlYnJ0Yy1hZGFwdGVyL3NyYy9qcy9hZGFwdGVyX2NvcmUuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvd2VicnRjLWFkYXB0ZXIvc3JjL2pzL2FkYXB0ZXJfZmFjdG9yeS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy93ZWJydGMtYWRhcHRlci9zcmMvanMvY2hyb21lL2Nocm9tZV9zaGltLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL3dlYnJ0Yy1hZGFwdGVyL3NyYy9qcy9jaHJvbWUvZ2V0dXNlcm1lZGlhLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL3dlYnJ0Yy1hZGFwdGVyL3NyYy9qcy9jb21tb25fc2hpbS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy93ZWJydGMtYWRhcHRlci9zcmMvanMvZWRnZS9lZGdlX3NoaW0uanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvd2VicnRjLWFkYXB0ZXIvc3JjL2pzL2VkZ2UvZ2V0dXNlcm1lZGlhLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL3dlYnJ0Yy1hZGFwdGVyL3NyYy9qcy9maXJlZm94L2ZpcmVmb3hfc2hpbS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy93ZWJydGMtYWRhcHRlci9zcmMvanMvZmlyZWZveC9nZXR1c2VybWVkaWEuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvd2VicnRjLWFkYXB0ZXIvc3JjL2pzL3NhZmFyaS9zYWZhcmlfc2hpbS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy93ZWJydGMtYWRhcHRlci9zcmMvanMvdXRpbHMuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvd2lsZGVtaXR0ZXIvd2lsZGVtaXR0ZXIuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvd29sZnk4Ny1ldmVudGVtaXR0ZXIvRXZlbnRFbWl0dGVyLmpzIiwiLi4vS3VyZW50b1V0aWxzL0RldGVjdFJUQy5qcyIsIi4uL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvTWFwcGVyLmpzIiwiLi4vS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2luZGV4LmpzIiwiLi4vS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2pzb25ycGNjbGllbnQuanMiLCIuLi9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvdHJhbnNwb3J0cy9pbmRleC5qcyIsIi4uL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy90cmFuc3BvcnRzL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24uanMiLCIuLi9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2luZGV4LmpzIiwiLi4vS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL0pzb25SUEMuanMiLCIuLi9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvWG1sUlBDLmpzIiwiLi4vS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL2luZGV4LmpzIiwiLi4vS3VyZW50b1V0aWxzL2t1cmVudG8tdXRpbHMtanMvV2ViUnRjUGVlci5qcyIsIi4uL0t1cmVudG9VdGlscy9rdXJlbnRvLXV0aWxzLWpzL2luZGV4LmpzIiwiTWFpbi50cyIsIk9wZW5WaWR1LnRzIiwiUHVibGlzaGVyLnRzIiwiU2Vzc2lvbi50cyIsIlN1YnNjcmliZXIudHMiLCIuLi9PcGVuVmlkdUludGVybmFsL0Nvbm5lY3Rpb24udHMiLCIuLi9PcGVuVmlkdUludGVybmFsL0xvY2FsUmVjb3JkZXIudHMiLCIuLi9PcGVuVmlkdUludGVybmFsL09wZW5WaWR1RXJyb3IudHMiLCIuLi9PcGVuVmlkdUludGVybmFsL09wZW5WaWR1SW50ZXJuYWwudHMiLCIuLi9PcGVuVmlkdUludGVybmFsL1Nlc3Npb25JbnRlcm5hbC50cyIsIi4uL09wZW5WaWR1SW50ZXJuYWwvU3RyZWFtLnRzIiwiLi4vT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNTdGF0cy50cyIsIi4uL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQkE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4dURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbjNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BxQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoakNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ2pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQzdCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDYkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3p1QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaFBBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbFJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6TkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM1NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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RUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksWUFBWSxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMxQyxNQUFNLENBQUMsSUFBSSxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUE7SUFDbEQsQ0FBQztJQUVELGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUE7QUFDckUsQ0FBQztBQUNELFFBQVEsQ0FBQyxrQkFBa0IsRUFBRSxVQUFVLENBQUMsQ0FBQTtBQUV4Qyw0QkFBNEIsT0FBTyxFQUFFLFFBQVE7SUFDM0MsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksWUFBWSxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMxQyxNQUFNLENBQUMsSUFBSSxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUE7SUFDbEQsQ0FBQztJQUVELGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUE7QUFDckUsQ0FBQztBQUNELFFBQVEsQ0FBQyxrQkFBa0IsRUFBRSxVQUFVLENBQUMsQ0FBQTtBQUV4Qyw0QkFBNEIsT0FBTyxFQUFFLFFBQVE7SUFDM0MsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksWUFBWSxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMxQyxNQUFNLENBQUMsSUFBSSxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUE7SUFDbEQsQ0FBQztJQUVELGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUE7QUFDckUsQ0FBQztBQUNELFFBQVEsQ0FBQyxrQkFBa0IsRUFBRSxVQUFVLENBQUMsQ0FBQTtBQUV4QyxtQkFBbUIsTUFBTSxFQUFFLE9BQU87SUFDaEMs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LG1CQUFtQixDQUFDLFNBQVMsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO0lBQzVELENBQUM7SUFFRCxVQUFVLENBQUMsbUNBQW1DLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDekQsQ0FBQyxDQUFDO0FBRUY7SUFDSSxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDVixVQUFVLENBQUMsbUNBQW1DLENBQUMsQ0FBQztRQUNoRCxNQUFNLENBQUM7SUFDWCxDQUFDO0lBRUQsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUNuQixVQUFVLENBQUMsbUNBQW1DLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDckQsTUFBTSxDQUFDO0lBQ1gsQ0FBQztJQUVELE1BQU0sQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDO1FBQzdCLHdCQUF3QixFQUFFLElBQUk7S0FDakMsRUFBRSxHQUFHLENBQUMsQ0FBQztBQUNaLENBQUM7QUFFRCxPQUFPLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztBQUNsQyxPQUFPLENBQUMsd0JBQXdCLEdBQUcsd0JBQXdCLENBQUMiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpe2Z1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfXJldHVybiBlfSkoKSIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG5mdW5jdGlvbiBFdmVudEVtaXR0ZXIoKSB7XG4gIHRoaXMuX2V2ZW50cyA9IHRoaXMuX2V2ZW50cyB8fCB7fTtcbiAgdGhpcy5fbWF4TGlzdGVuZXJzID0gdGhpcy5fbWF4TGlzdGVuZXJzIHx8IHVuZGVmaW5lZDtcbn1cbm1vZHVsZS5leHBvcnRzID0gRXZlbnRFbWl0dGVyO1xuXG4vLyBCYWNrd2FyZHMtY29tcGF0IHdpdGggbm9kZSAwLjEwLnhcbkV2ZW50RW1pdHRlci5FdmVudEVtaXR0ZXIgPSBFdmVudEVtaXR0ZXI7XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuX2V2ZW50cyA9IHVuZGVmaW5lZDtcbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuX21heExpc3RlbmVycyA9IHVuZGVmaW5lZDtcblxuLy8gQnkgZGVmYXVsdCBFdmVudEVtaXR0ZXJzIHdpbGwgcHJpbnQgYSB3YXJuaW5nIGlmIG1vcmUgdGhhbiAxMCBsaXN0ZW5lcnMgYXJlXG4vLyBhZGRlZCB0byBpdC4gVGhpcyBpcyBhIHVzZWZ1bCBkZWZhdWx0IHdoaWNoIGhlbHBzIGZpbmRpbmcgbWVtb3J5IGxlYWtzLlxuRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnMgPSAxMDtcblxuLy8gT2J2aW91c2x5IG5vdCBhbGwgRW1pdHRlcnMgc2hvdWxkIGJlIGxpbWl0ZWQgdG8gMTAuIFRoaXMgZnVuY3Rpb24gYWxsb3dzXG4vLyB0aGF0IHRvIGJlIGluY3JlYXNlZC4gU2V0IHRvIHplcm8gZm9yIHVubGltaXRlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuc2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24obikge1xuICBpZiAoIWlzTnVtYmVyKG4pIHx8IG4gPCAwIHx8IGlzTmFOKG4pKVxuICAgIHRocm93IFR5cGVFcnJvcignbiBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gIHRoaXMuX21heExpc3RlbmVycyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5lbWl0ID0gZnVuY3Rpb24odHlwZSkge1xuICB2YXIgZXIsIGhhbmRsZXIsIGxlbiwgYXJncywgaSwgbGlzdGVuZXJzO1xuXG4gIGlmICghdGhpcy5fZXZlbnRzKVxuICAgIHRoaXMuX2V2ZW50cyA9IHt9O1xuXG4gIC8vIElmIHRoZXJlIGlzIG5vICdlcnJvcicgZXZlbnQgbGlzdGVuZXIgdGhlbiB0aHJvdy5cbiAgaWYgKHR5cGUgPT09ICdlcnJvcicpIHtcbiAgICBpZiAoIXRoaXMuX2V2ZW50cy5lcnJvciB8fFxuICAgICAgICAoaXNPYmplY3QodGhpcy5fZXZlbnRzLmVycm9yKSAmJiAhdGhpcy5fZXZlbnRzLmVycm9yLmxlbmd0aCkpIHtcbiAgICAgIGVyID0gYXJndW1lbnRzWzFdO1xuICAgICAgaWYgKGVyIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBBdCBsZWFzdCBnaXZlIHNvbWUga2luZCBvZiBjb250ZXh0IHRvIHRoZSB1c2VyXG4gICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoJ1VuY2F1Z2h0LCB1bnNwZWNpZmllZCBcImVycm9yXCIgZXZlbnQuICgnICsgZXIgKyAnKScpO1xuICAgICAgICBlcnIuY29udGV4dCA9IGVyO1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaGFuZGxlciA9IHRoaXMuX2V2ZW50c1t0eXBlXTtcblxuICBpZiAoaXNVbmRlZmluZWQoaGFuZGxlcikpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIGlmIChpc0Z1bmN0aW9uKGhhbmRsZXIpKSB7XG4gICAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICAvLyBmYXN0IGNhc2VzXG4gICAgICBjYXNlIDE6XG4gICAgICAgIGhhbmRsZXIuY2FsbCh0aGlzKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDI6XG4gICAgICAgIGhhbmRsZXIuY2FsbCh0aGlzLCBhcmd1bWVudHNbMV0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMzpcbiAgICAgICAgaGFuZGxlci5jYWxsKHRoaXMsIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICAvLyBzbG93ZXJcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICBoYW5kbGVyLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChpc09iamVjdChoYW5kbGVyKSkge1xuICAgIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgIGxpc3RlbmVycyA9IGhhbmRsZXIuc2xpY2UoKTtcbiAgICBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoO1xuICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKylcbiAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBhcmdzKTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBtO1xuXG4gIGlmICghaXNGdW5jdGlvbihsaXN0ZW5lcikpXG4gICAgdGhyb3cgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcblxuICBpZiAoIXRoaXMuX2V2ZW50cylcbiAgICB0aGlzLl9ldmVudHMgPSB7fTtcblxuICAvLyBUbyBhdm9pZCByZWN1cnNpb24gaW4gdGhlIGNhc2UgdGhhdCB0eXBlID09PSBcIm5ld0xpc3RlbmVyXCIhIEJlZm9yZVxuICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gIGlmICh0aGlzLl9ldmVudHMubmV3TGlzdGVuZXIpXG4gICAgdGhpcy5lbWl0KCduZXdMaXN0ZW5lcicsIHR5cGUsXG4gICAgICAgICAgICAgIGlzRnVuY3Rpb24obGlzdGVuZXIubGlzdGVuZXIpID9cbiAgICAgICAgICAgICAgbGlzdGVuZXIubGlzdGVuZXIgOiBsaXN0ZW5lcik7XG5cbiAgaWYgKCF0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgdGhpcy5fZXZlbnRzW3R5cGVdID0gbGlzdGVuZXI7XG4gIGVsc2UgaWYgKGlzT2JqZWN0KHRoaXMuX2V2ZW50c1t0eXBlXSkpXG4gICAgLy8gSWYgd2UndmUgYWxyZWFkeSBnb3QgYW4gYXJyYXksIGp1c3QgYXBwZW5kLlxuICAgIHRoaXMuX2V2ZW50c1t0eXBlXS5wdXNoKGxpc3RlbmVyKTtcbiAgZWxzZVxuICAgIC8vIEFkZGluZyB0aGUgc2Vjb25kIGVsZW1lbnQsIG5lZWQgdG8gY2hhbmdlIHRvIGFycmF5LlxuICAgIHRoaXMuX2V2ZW50c1t0eXBlXSA9IFt0aGlzLl9ldmVudHNbdHlwZV0sIGxpc3RlbmVyXTtcblxuICAvLyBDaGVjayBmb3IgbGlzdGVuZXIgbGVha1xuICBpZiAoaXNPYmplY3QodGhpcy5fZXZlbnRzW3R5cGVdKSAmJiAhdGhpcy5fZXZlbnRzW3R5cGVdLndhcm5lZCkge1xuICAgIGlmICghaXNVbmRlZmluZWQodGhpcy5fbWF4TGlzdGVuZXJzKSkge1xuICAgICAgbSA9IHRoaXMuX21heExpc3RlbmVycztcbiAgICB9IGVsc2Uge1xuICAgICAgbSA9IEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzO1xuICAgIH1cblxuICAgIGlmIChtICYmIG0gPiAwICYmIHRoaXMuX2V2ZW50c1t0eXBlXS5sZW5ndGggPiBtKSB7XG4gICAgICB0aGlzLl9ldmVudHNbdHlwZV0ud2FybmVkID0gdHJ1ZTtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJyhub2RlKSB3YXJuaW5nOiBwb3NzaWJsZSBFdmVudEVtaXR0ZXIgbWVtb3J5ICcgK1xuICAgICAgICAgICAgICAgICAgICAnbGVhayBkZXRlY3RlZC4gJWQgbGlzdGVuZXJzIGFkZGVkLiAnICtcbiAgICAgICAgICAgICAgICAgICAgJ1VzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvIGluY3JlYXNlIGxpbWl0LicsXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2V2ZW50c1t0eXBlXS5sZW5ndGgpO1xuICAgICAgaWYgKHR5cGVvZiBjb25zb2xlLnRyYWNlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIC8vIG5vdCBzdXBwb3J0ZWQgaW4gSUUgMTBcbiAgICAgICAgY29uc29sZS50cmFjZSgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5vbiA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGUuYWRkTGlzdGVuZXI7XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub25jZSA9IGZ1bmN0aW9uKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGlmICghaXNGdW5jdGlvbihsaXN0ZW5lcikpXG4gICAgdGhyb3cgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcblxuICB2YXIgZmlyZWQgPSBmYWxzZTtcblxuICBmdW5jdGlvbiBnKCkge1xuICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIodHlwZSwgZyk7XG5cbiAgICBpZiAoIWZpcmVkKSB7XG4gICAgICBmaXJlZCA9IHRydWU7XG4gICAgICBsaXN0ZW5lci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgfVxuXG4gIGcubGlzdGVuZXIgPSBsaXN0ZW5lcjtcbiAgdGhpcy5vbih0eXBlLCBnKTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cbi8vIGVtaXRzIGEgJ3JlbW92ZUxpc3RlbmVyJyBldmVudCBpZmYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnJlbW92ZUxpc3RlbmVyID0gZnVuY3Rpb24odHlwZSwgbGlzdGVuZXIpIHtcbiAgdmFyIGxpc3QsIHBvc2l0aW9uLCBsZW5ndGgsIGk7XG5cbiAgaWYgKCFpc0Z1bmN0aW9uKGxpc3RlbmVyKSlcbiAgICB0aHJvdyBUeXBlRXJyb3IoJ2xpc3RlbmVyIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuXG4gIGlmICghdGhpcy5fZXZlbnRzIHx8ICF0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgcmV0dXJuIHRoaXM7XG5cbiAgbGlzdCA9IHRoaXMuX2V2ZW50c1t0eXBlXTtcbiAgbGVuZ3RoID0gbGlzdC5sZW5ndGg7XG4gIHBvc2l0aW9uID0gLTE7XG5cbiAgaWYgKGxpc3QgPT09IGxpc3RlbmVyIHx8XG4gICAgICAoaXNGdW5jdGlvbihsaXN0Lmxpc3RlbmVyKSAmJiBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikpIHtcbiAgICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuICAgIGlmICh0aGlzLl9ldmVudHMucmVtb3ZlTGlzdGVuZXIpXG4gICAgICB0aGlzLmVtaXQoJ3JlbW92ZUxpc3RlbmVyJywgdHlwZSwgbGlzdGVuZXIpO1xuXG4gIH0gZWxzZSBpZiAoaXNPYmplY3QobGlzdCkpIHtcbiAgICBmb3IgKGkgPSBsZW5ndGg7IGktLSA+IDA7KSB7XG4gICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHxcbiAgICAgICAgICAobGlzdFtpXS5saXN0ZW5lciAmJiBsaXN0W2ldLmxpc3RlbmVyID09PSBsaXN0ZW5lcikpIHtcbiAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAocG9zaXRpb24gPCAwKVxuICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpIHtcbiAgICAgIGxpc3QubGVuZ3RoID0gMDtcbiAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHNbdHlwZV07XG4gICAgfSBlbHNlIHtcbiAgICAgIGxpc3Quc3BsaWNlKHBvc2l0aW9uLCAxKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgdGhpcy5lbWl0KCdyZW1vdmVMaXN0ZW5lcicsIHR5cGUsIGxpc3RlbmVyKTtcbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBmdW5jdGlvbih0eXBlKSB7XG4gIHZhciBrZXksIGxpc3RlbmVycztcblxuICBpZiAoIXRoaXMuX2V2ZW50cylcbiAgICByZXR1cm4gdGhpcztcblxuICAvLyBub3QgbGlzdGVuaW5nIGZvciByZW1vdmVMaXN0ZW5lciwgbm8gbmVlZCB0byBlbWl0XG4gIGlmICghdGhpcy5fZXZlbnRzLnJlbW92ZUxpc3RlbmVyKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApXG4gICAgICB0aGlzLl9ldmVudHMgPSB7fTtcbiAgICBlbHNlIGlmICh0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLy8gZW1pdCByZW1vdmVMaXN0ZW5lciBmb3IgYWxsIGxpc3RlbmVycyBvbiBhbGwgZXZlbnRzXG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgZm9yIChrZXkgaW4gdGhpcy5fZXZlbnRzKSB7XG4gICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKGtleSk7XG4gICAgfVxuICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgIHRoaXMuX2V2ZW50cyA9IHt9O1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgbGlzdGVuZXJzID0gdGhpcy5fZXZlbnRzW3R5cGVdO1xuXG4gIGlmIChpc0Z1bmN0aW9uKGxpc3RlbmVycykpIHtcbiAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVycyk7XG4gIH0gZWxzZSBpZiAobGlzdGVuZXJzKSB7XG4gICAgLy8gTElGTyBvcmRlclxuICAgIHdoaWxlIChsaXN0ZW5lcnMubGVuZ3RoKVxuICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnNbbGlzdGVuZXJzLmxlbmd0aCAtIDFdKTtcbiAgfVxuICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuXG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5saXN0ZW5lcnMgPSBmdW5jdGlvbih0eXBlKSB7XG4gIHZhciByZXQ7XG4gIGlmICghdGhpcy5fZXZlbnRzIHx8ICF0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgcmV0ID0gW107XG4gIGVsc2UgaWYgKGlzRnVuY3Rpb24odGhpcy5fZXZlbnRzW3R5cGVdKSlcbiAgICByZXQgPSBbdGhpcy5fZXZlbnRzW3R5cGVdXTtcbiAgZWxzZVxuICAgIHJldCA9IHRoaXMuX2V2ZW50c1t0eXBlXS5zbGljZSgpO1xuICByZXR1cm4gcmV0O1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5saXN0ZW5lckNvdW50ID0gZnVuY3Rpb24odHlwZSkge1xuICBpZiAodGhpcy5fZXZlbnRzKSB7XG4gICAgdmFyIGV2bGlzdGVuZXIgPSB0aGlzLl9ldmVudHNbdHlwZV07XG5cbiAgICBpZiAoaXNGdW5jdGlvbihldmxpc3RlbmVyKSlcbiAgICAgIHJldHVybiAxO1xuICAgIGVsc2UgaWYgKGV2bGlzdGVuZXIpXG4gICAgICByZXR1cm4gZXZsaXN0ZW5lci5sZW5ndGg7XG4gIH1cbiAgcmV0dXJuIDA7XG59O1xuXG5FdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKGVtaXR0ZXIsIHR5cGUpIHtcbiAgcmV0dXJuIGVtaXR0ZXIubGlzdGVuZXJDb3VudCh0eXBlKTtcbn07XG5cbmZ1bmN0aW9uIGlzRnVuY3Rpb24oYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnZnVuY3Rpb24nO1xufVxuXG5mdW5jdGlvbiBpc051bWJlcihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc09iamVjdChhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdvYmplY3QnICYmIGFyZyAhPT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNVbmRlZmluZWQoYXJnKSB7XG4gIHJldHVybiBhcmcgPT09IHZvaWQgMDtcbn1cbiIsIi8qIGpzaGludCBub2RlOiB0cnVlICovXG4ndXNlIHN0cmljdCc7XG5cbnZhciBub3JtYWxpY2UgPSByZXF1aXJlKCdub3JtYWxpY2UnKTtcblxuLyoqXG4gICMgZnJlZWljZVxuXG4gIFRoZSBgZnJlZWljZWAgbW9kdWxlIGlzIGEgc2ltcGxlIHdheSBvZiBnZXR0aW5nIHJhbmRvbSBTVFVOIG9yIFRVUk4gc2VydmVyXG4gIGZvciB5b3VyIFdlYlJUQyBhcHBsaWNhdGlvbi4gIFRoZSBsaXN0IG9mIHNlcnZlcnMgKGp1c3QgU1RVTiBhdCB0aGlzIHN0YWdlKVxuICB3ZXJlIHNvdXJjZWQgZnJvbSB0aGlzIFtnaXN0XShodHRwczovL2dpc3QuZ2l0aHViLmNvbS96eml1bmkvMzc0MTkzMykuXG5cbiAgIyMgRXhhbXBsZSBVc2VcblxuICBUaGUgZm9sbG93aW5nIGRlbW9uc3RyYXRlcyBob3cgeW91IGNhbiB1c2UgYGZyZWVpY2VgIHdpdGhcbiAgW3J0Yy1xdWlja2Nvbm5lY3RdKGh0dHBzOi8vZ2l0aHViLmNvbS9ydGMtaW8vcnRjLXF1aWNrY29ubmVjdCk6XG5cbiAgPDw8IGV4YW1wbGVzL3F1aWNrY29ubmVjdC5qc1xuXG4gIEFzIHRoZSBgZnJlZWljZWAgbW9kdWxlIGdlbmVyYXRlcyBpY2Ugc2VydmVycyBpbiBhIGxpc3QgY29tcGxpYW50IHdpdGggdGhlXG4gIFdlYlJUQyBzcGVjIHlvdSB3aWxsIGJlIGFibGUgdG8gdXNlIGl0IHdpdGggcmF3IGBSVENQZWVyQ29ubmVjdGlvbmBcbiAgY29uc3RydWN0b3JzIGFuZCBvdGhlciBXZWJSVEMgbGlicmFyaWVzLlxuXG4gICMjIEhleSwgZG9uJ3QgdXNlIG15IFNUVU4vVFVSTiBzZXJ2ZXIhXG5cbiAgSWYgZm9yIHNvbWUgcmVhc29uIHlvdXIgZnJlZSBTVFVOIG9yIFRVUk4gc2VydmVyIGVuZHMgdXAgaW4gdGhlXG4gIGxpc3Qgb2Ygc2VydmVycyAoW3N0dW5dKGh0dHBzOi8vZ2l0aHViLmNvbS9EYW1vbk9laGxtYW4vZnJlZWljZS9ibG9iL21hc3Rlci9zdHVuLmpzb24pIG9yXG4gIFt0dXJuXShodHRwczovL2dpdGh1Yi5jb20vRGFtb25PZWhsbWFuL2ZyZWVpY2UvYmxvYi9tYXN0ZXIvdHVybi5qc29uKSlcbiAgdGhhdCBpcyB1c2VkIGluIHRoaXMgbW9kdWxlLCB5b3UgY2FuIGZlZWxcbiAgZnJlZSB0byBvcGVuIGFuIGlzc3VlIG9uIHRoaXMgcmVwb3NpdG9yeSBhbmQgdGhvc2Ugc2VydmVycyB3aWxsIGJlIHJlbW92ZWRcbiAgd2l0aGluIDI0IGhvdXJzIChvciBzb29uZXIpLiAgVGhpcyBpcyB0aGUgcXVpY2tlc3QgYW5kIHByb2JhYmx5IHRoZSBtb3N0XG4gIHBvbGl0ZSB3YXkgdG8gaGF2ZSBzb21ldGhpbmcgcmVtb3ZlZCAoYW5kIHByb3ZpZGVzIHVzIHNvbWUgdmlzaWJpbGl0eVxuICBpZiBzb21lb25lIG9wZW5zIGEgcHVsbCByZXF1ZXN0IHJlcXVlc3RpbmcgdGhhdCBhIHNlcnZlciBpcyBhZGRlZCkuXG5cbiAgIyMgUGxlYXNlIGFkZCBteSBzZXJ2ZXIhXG5cbiAgSWYgeW91IGhhdmUgYSBzZXJ2ZXIgdGhhdCB5b3Ugd2lzaCB0byBhZGQgdG8gdGhlIGxpc3QsIHRoYXQncyBhd2Vzb21lISBJJ21cbiAgc3VyZSBJIHNwZWFrIG9uIGJlaGFsZiBvZiBhIHdob2xlIHBpbGUgb2YgV2ViUlRDIGRldmVsb3BlcnMgd2hvIHNheSB0aGFua3MuXG4gIFRvIGdldCBpdCBpbnRvIHRoZSBsaXN0LCBmZWVsIGZyZWUgdG8gZWl0aGVyIG9wZW4gYSBwdWxsIHJlcXVlc3Qgb3IgaWYgeW91XG4gIGZpbmQgdGhhdCBwcm9jZXNzIGEgYml0IGRhdW50aW5nIHRoZW4ganVzdCBjcmVhdGUgYW4gaXNzdWUgcmVxdWVzdGluZ1xuICB0aGUgYWRkaXRpb24gb2YgdGhlIHNlcnZlciAobWFrZSBzdXJlIHlvdSBwcm92aWRlIGFsbCB0aGUgZGV0YWlscywgYW5kIGlmXG4gIHlvdSBoYXZlIGEgVGVybXMgb2YgU2VydmljZSB0aGVuIGluY2x1ZGluZyB0aGF0IGluIHRoZSBQUi9pc3N1ZSB3b3VsZCBiZVxuICBhd2Vzb21lKS5cblxuICAjIyBJIGtub3cgb2YgYSBmcmVlIHNlcnZlciwgY2FuIEkgYWRkIGl0P1xuXG4gIFN1cmUsIGlmIHlvdSBkbyB5b3VyIGhvbWV3b3JrIGFuZCBtYWtlIHN1cmUgaXQgaXMgb2sgdG8gdXNlIChJJ20gY3VycmVudGx5XG4gIGluIHRoZSBwcm9jZXNzIG9mIHJldmlld2luZyB0aGUgdGVybXMgb2YgdGhvc2UgU1RVTiBzZXJ2ZXJzIGluY2x1ZGVkIGZyb21cbiAgdGhlIG9yaWdpbmFsIGxpc3QpLiAgSWYgaXQncyBvayB0byBnbywgdGhlbiBwbGVhc2Ugc2VlIHRoZSBwcmV2aW91cyBlbnRyeVxuICBmb3IgaG93IHRvIGFkZCBpdC5cblxuICAjIyBDdXJyZW50IExpc3Qgb2YgU2VydmVyc1xuXG4gICogY3VycmVudCBhcyBhdCB0aGUgdGltZSBvZiBsYXN0IGBSRUFETUUubWRgIGZpbGUgZ2VuZXJhdGlvblxuXG4gICMjIyBTVFVOXG5cbiAgPDw8IHN0dW4uanNvblxuXG4gICMjIyBUVVJOXG5cbiAgPDw8IHR1cm4uanNvblxuXG4qKi9cblxudmFyIGZyZWVpY2UgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKG9wdHMpIHtcbiAgLy8gaWYgYSBsaXN0IG9mIHNlcnZlcnMgaGFzIGJlZW4gcHJvdmlkZWQsIHRoZW4gdXNlIGl0IGluc3RlYWQgb2YgZGVmYXVsdHNcbiAgdmFyIHNlcnZlcnMgPSB7XG4gICAgc3R1bjogKG9wdHMgfHwge30pLnN0dW4gfHwgcmVxdWlyZSgnLi9zdHVuLmpzb24nKSxcbiAgICB0dXJuOiAob3B0cyB8fCB7fSkudHVybiB8fCByZXF1aXJlKCcuL3R1cm4uanNvbicpXG4gIH07XG5cbiAgdmFyIHN0dW5Db3VudCA9IChvcHRzIHx8IHt9KS5zdHVuQ291bnQgfHwgMjtcbiAgdmFyIHR1cm5Db3VudCA9IChvcHRzIHx8IHt9KS50dXJuQ291bnQgfHwgMDtcbiAgdmFyIHNlbGVjdGVkO1xuXG4gIGZ1bmN0aW9uIGdldFNlcnZlcnModHlwZSwgY291bnQpIHtcbiAgICB2YXIgb3V0ID0gW107XG4gICAgdmFyIGlucHV0ID0gW10uY29uY2F0KHNlcnZlcnNbdHlwZV0pO1xuICAgIHZhciBpZHg7XG5cbiAgICB3aGlsZSAoaW5wdXQubGVuZ3RoICYmIG91dC5sZW5ndGggPCBjb3VudCkge1xuICAgICAgaWR4ID0gKE1hdGgucmFuZG9tKCkgKiBpbnB1dC5sZW5ndGgpIHwgMDtcbiAgICAgIG91dCA9IG91dC5jb25jYXQoaW5wdXQuc3BsaWNlKGlkeCwgMSkpO1xuICAgIH1cblxuICAgIHJldHVybiBvdXQubWFwKGZ1bmN0aW9uKHVybCkge1xuICAgICAgICAvL0lmIGl0J3MgYSBub3QgYSBzdHJpbmcsIGRvbid0IHRyeSB0byBcIm5vcm1hbGljZVwiIGl0IG90aGVyd2lzZSB1c2luZyB0eXBlOnVybCB3aWxsIHNjcmV3IGl0IHVwXG4gICAgICAgIGlmICgodHlwZW9mIHVybCAhPT0gJ3N0cmluZycpICYmICghICh1cmwgaW5zdGFuY2VvZiBTdHJpbmcpKSkge1xuICAgICAgICAgICAgcmV0dXJuIHVybDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBub3JtYWxpY2UodHlwZSArICc6JyArIHVybCk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8vIGFkZCBzdHVuIHNlcnZlcnNcbiAgc2VsZWN0ZWQgPSBbXS5jb25jYXQoZ2V0U2VydmVycygnc3R1bicsIHN0dW5Db3VudCkpO1xuXG4gIGlmICh0dXJuQ291bnQpIHtcbiAgICBzZWxlY3RlZCA9IHNlbGVjdGVkLmNvbmNhdChnZXRTZXJ2ZXJzKCd0dXJuJywgdHVybkNvdW50KSk7XG4gIH1cblxuICByZXR1cm4gc2VsZWN0ZWQ7XG59O1xuIiwibW9kdWxlLmV4cG9ydHM9W1xuICBcInN0dW4ubC5nb29nbGUuY29tOjE5MzAyXCIsXG4gIFwic3R1bjEubC5nb29nbGUuY29tOjE5MzAyXCIsXG4gIFwic3R1bjIubC5nb29nbGUuY29tOjE5MzAyXCIsXG4gIFwic3R1bjMubC5nb29nbGUuY29tOjE5MzAyXCIsXG4gIFwic3R1bjQubC5nb29nbGUuY29tOjE5MzAyXCIsXG4gIFwic3R1bi5la2lnYS5uZXRcIixcbiAgXCJzdHVuLmlkZWFzaXAuY29tXCIsXG4gIFwic3R1bi5zY2hsdW5kLmRlXCIsXG4gIFwic3R1bi5zdHVucHJvdG9jb2wub3JnOjM0NzhcIixcbiAgXCJzdHVuLnZvaXBhcm91bmQuY29tXCIsXG4gIFwic3R1bi52b2lwYnVzdGVyLmNvbVwiLFxuICBcInN0dW4udm9pcHN0dW50LmNvbVwiLFxuICBcInN0dW4udm94Z3JhdGlhLm9yZ1wiLFxuICBcInN0dW4uc2VydmljZXMubW96aWxsYS5jb21cIlxuXVxuIiwibW9kdWxlLmV4cG9ydHM9W11cbiIsInZhciBXaWxkRW1pdHRlciA9IHJlcXVpcmUoJ3dpbGRlbWl0dGVyJyk7XG5cbmZ1bmN0aW9uIGdldE1heFZvbHVtZSAoYW5hbHlzZXIsIGZmdEJpbnMpIHtcbiAgdmFyIG1heFZvbHVtZSA9IC1JbmZpbml0eTtcbiAgYW5hbHlzZXIuZ2V0RmxvYXRGcmVxdWVuY3lEYXRhKGZmdEJpbnMpO1xuXG4gIGZvcih2YXIgaT00LCBpaT1mZnRCaW5zLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICBpZiAoZmZ0Qmluc1tpXSA+IG1heFZvbHVtZSAmJiBmZnRCaW5zW2ldIDwgMCkge1xuICAgICAgbWF4Vm9sdW1lID0gZmZ0Qmluc1tpXTtcbiAgICB9XG4gIH07XG5cbiAgcmV0dXJuIG1heFZvbHVtZTtcbn1cblxuXG52YXIgYXVkaW9Db250ZXh0VHlwZTtcbmlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICBhdWRpb0NvbnRleHRUeXBlID0gd2luZG93LkF1ZGlvQ29udGV4dCB8fCB3aW5kb3cud2Via2l0QXVkaW9Db250ZXh0O1xufVxuLy8gdXNlIGEgc2luZ2xlIGF1ZGlvIGNvbnRleHQgZHVlIHRvIGhhcmR3YXJlIGxpbWl0c1xudmFyIGF1ZGlvQ29udGV4dCA9IG51bGw7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHN0cmVhbSwgb3B0aW9ucykge1xuICB2YXIgaGFya2VyID0gbmV3IFdpbGRFbWl0dGVyKCk7XG5cblxuICAvLyBtYWtlIGl0IG5vdCBicmVhayBpbiBub24tc3VwcG9ydGVkIGJyb3dzZXJzXG4gIGlmICghYXVkaW9Db250ZXh0VHlwZSkgcmV0dXJuIGhhcmtlcjtcblxuICAvL0NvbmZpZ1xuICB2YXIgb3B0aW9ucyA9IG9wdGlvbnMgfHwge30sXG4gICAgICBzbW9vdGhpbmcgPSAob3B0aW9ucy5zbW9vdGhpbmcgfHwgMC4xKSxcbiAgICAgIGludGVydmFsID0gKG9wdGlvbnMuaW50ZXJ2YWwgfHwgNTApLFxuICAgICAgdGhyZXNob2xkID0gb3B0aW9ucy50aHJlc2hvbGQsXG4gICAgICBwbGF5ID0gb3B0aW9ucy5wbGF5LFxuICAgICAgaGlzdG9yeSA9IG9wdGlvbnMuaGlzdG9yeSB8fCAxMCxcbiAgICAgIHJ1bm5pbmcgPSB0cnVlO1xuXG4gIC8vU2V0dXAgQXVkaW8gQ29udGV4dFxuICBpZiAoIWF1ZGlvQ29udGV4dCkge1xuICAgIGF1ZGlvQ29udGV4dCA9IG5ldyBhdWRpb0NvbnRleHRUeXBlKCk7XG4gIH1cbiAgdmFyIHNvdXJjZU5vZGUsIGZmdEJpbnMsIGFuYWx5c2VyO1xuXG4gIGFuYWx5c2VyID0gYXVkaW9Db250ZXh0LmNyZWF0ZUFuYWx5c2VyKCk7XG4gIGFuYWx5c2VyLmZmdFNpemUgPSA1MTI7XG4gIGFuYWx5c2VyLnNtb290aGluZ1RpbWVDb25zdGFudCA9IHNtb290aGluZztcbiAgZmZ0QmlucyA9IG5ldyBGbG9hdDMyQXJyYXkoYW5hbHlzZXIuZnJlcXVlbmN5QmluQ291bnQpO1xuXG4gIGlmIChzdHJlYW0uanF1ZXJ5KSBzdHJlYW0gPSBzdHJlYW1bMF07XG4gIGlmIChzdHJlYW0gaW5zdGFuY2VvZiBIVE1MQXVkaW9FbGVtZW50IHx8IHN0cmVhbSBpbnN0YW5jZW9mIEhUTUxWaWRlb0VsZW1lbnQpIHtcbiAgICAvL0F1ZGlvIFRhZ1xuICAgIHNvdXJjZU5vZGUgPSBhdWRpb0NvbnRleHQuY3JlYXRlTWVkaWFFbGVtZW50U291cmNlKHN0cmVhbSk7XG4gICAgaWYgKHR5cGVvZiBwbGF5ID09PSAndW5kZWZpbmVkJykgcGxheSA9IHRydWU7XG4gICAgdGhyZXNob2xkID0gdGhyZXNob2xkIHx8IC01MDtcbiAgfSBlbHNlIHtcbiAgICAvL1dlYlJUQyBTdHJlYW1cbiAgICBzb3VyY2VOb2RlID0gYXVkaW9Db250ZXh0LmNyZWF0ZU1lZGlhU3RyZWFtU291cmNlKHN0cmVhbSk7XG4gICAgdGhyZXNob2xkID0gdGhyZXNob2xkIHx8IC01MDtcbiAgfVxuXG4gIHNvdXJjZU5vZGUuY29ubmVjdChhbmFseXNlcik7XG4gIGlmIChwbGF5KSBhbmFseXNlci5jb25uZWN0KGF1ZGlvQ29udGV4dC5kZXN0aW5hdGlvbik7XG5cbiAgaGFya2VyLnNwZWFraW5nID0gZmFsc2U7XG5cbiAgaGFya2VyLnNldFRocmVzaG9sZCA9IGZ1bmN0aW9uKHQpIHtcbiAgICB0aHJlc2hvbGQgPSB0O1xuICB9O1xuXG4gIGhhcmtlci5zZXRJbnRlcnZhbCA9IGZ1bmN0aW9uKGkpIHtcbiAgICBpbnRlcnZhbCA9IGk7XG4gIH07XG5cbiAgaGFya2VyLnN0b3AgPSBmdW5jdGlvbigpIHtcbiAgICBydW5uaW5nID0gZmFsc2U7XG4gICAgaGFya2VyLmVtaXQoJ3ZvbHVtZV9jaGFuZ2UnLCAtMTAwLCB0aHJlc2hvbGQpO1xuICAgIGlmIChoYXJrZXIuc3BlYWtpbmcpIHtcbiAgICAgIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuICAgICAgaGFya2VyLmVtaXQoJ3N0b3BwZWRfc3BlYWtpbmcnKTtcbiAgICB9XG4gICAgYW5hbHlzZXIuZGlzY29ubmVjdCgpO1xuICAgIHNvdXJjZU5vZGUuZGlzY29ubmVjdCgpO1xuICB9O1xuICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5ID0gW107XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgaGlzdG9yeTsgaSsrKSB7XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnB1c2goMCk7XG4gIH1cblxuICAvLyBQb2xsIHRoZSBhbmFseXNlciBub2RlIHRvIGRldGVybWluZSBpZiBzcGVha2luZ1xuICAvLyBhbmQgZW1pdCBldmVudHMgaWYgY2hhbmdlZFxuICB2YXIgbG9vcGVyID0gZnVuY3Rpb24oKSB7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcblxuICAgICAgLy9jaGVjayBpZiBzdG9wIGhhcyBiZWVuIGNhbGxlZFxuICAgICAgaWYoIXJ1bm5pbmcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB2YXIgY3VycmVudFZvbHVtZSA9IGdldE1heFZvbHVtZShhbmFseXNlciwgZmZ0Qmlucyk7XG5cbiAgICAgIGhhcmtlci5lbWl0KCd2b2x1bWVfY2hhbmdlJywgY3VycmVudFZvbHVtZSwgdGhyZXNob2xkKTtcblxuICAgICAgdmFyIGhpc3RvcnkgPSAwO1xuICAgICAgaWYgKGN1cnJlbnRWb2x1bWUgPiB0aHJlc2hvbGQgJiYgIWhhcmtlci5zcGVha2luZykge1xuICAgICAgICAvLyB0cmlnZ2VyIHF1aWNrbHksIHNob3J0IGhpc3RvcnlcbiAgICAgICAgZm9yICh2YXIgaSA9IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoIC0gMzsgaSA8IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBoaXN0b3J5ICs9IGhhcmtlci5zcGVha2luZ0hpc3RvcnlbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpc3RvcnkgPj0gMikge1xuICAgICAgICAgIGhhcmtlci5zcGVha2luZyA9IHRydWU7XG4gICAgICAgICAgaGFya2VyLmVtaXQoJ3NwZWFraW5nJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoY3VycmVudFZvbHVtZSA8IHRocmVzaG9sZCAmJiBoYXJrZXIuc3BlYWtpbmcpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaGlzdG9yeSArPSBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5W2ldO1xuICAgICAgICB9XG4gICAgICAgIGlmIChoaXN0b3J5ID09IDApIHtcbiAgICAgICAgICBoYXJrZXIuc3BlYWtpbmcgPSBmYWxzZTtcbiAgICAgICAgICBoYXJrZXIuZW1pdCgnc3RvcHBlZF9zcGVha2luZycpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnNoaWZ0KCk7XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnB1c2goMCArIChjdXJyZW50Vm9sdW1lID4gdGhyZXNob2xkKSk7XG5cbiAgICAgIGxvb3BlcigpO1xuICAgIH0sIGludGVydmFsKTtcbiAgfTtcbiAgbG9vcGVyKCk7XG5cblxuICByZXR1cm4gaGFya2VyO1xufVxuIiwiaWYgKHR5cGVvZiBPYmplY3QuY3JlYXRlID09PSAnZnVuY3Rpb24nKSB7XG4gIC8vIGltcGxlbWVudGF0aW9uIGZyb20gc3RhbmRhcmQgbm9kZS5qcyAndXRpbCcgbW9kdWxlXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICBjdG9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDdG9yLnByb3RvdHlwZSwge1xuICAgICAgY29uc3RydWN0b3I6IHtcbiAgICAgICAgdmFsdWU6IGN0b3IsXG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICB9XG4gICAgfSk7XG4gIH07XG59IGVsc2Uge1xuICAvLyBvbGQgc2Nob29sIHNoaW0gZm9yIG9sZCBicm93c2Vyc1xuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGluaGVyaXRzKGN0b3IsIHN1cGVyQ3Rvcikge1xuICAgIGN0b3Iuc3VwZXJfID0gc3VwZXJDdG9yXG4gICAgdmFyIFRlbXBDdG9yID0gZnVuY3Rpb24gKCkge31cbiAgICBUZW1wQ3Rvci5wcm90b3R5cGUgPSBzdXBlckN0b3IucHJvdG90eXBlXG4gICAgY3Rvci5wcm90b3R5cGUgPSBuZXcgVGVtcEN0b3IoKVxuICAgIGN0b3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gY3RvclxuICB9XG59XG4iLCIvKiFcclxuICogQG5hbWUgSmF2YVNjcmlwdC9Ob2RlSlMgTWVyZ2UgdjEuMi4wXHJcbiAqIEBhdXRob3IgeWVpa29zXHJcbiAqIEByZXBvc2l0b3J5IGh0dHBzOi8vZ2l0aHViLmNvbS95ZWlrb3MvanMubWVyZ2VcclxuXHJcbiAqIENvcHlyaWdodCAyMDE0IHllaWtvcyAtIE1JVCBsaWNlbnNlXHJcbiAqIGh0dHBzOi8vcmF3LmdpdGh1Yi5jb20veWVpa29zL2pzLm1lcmdlL21hc3Rlci9MSUNFTlNFXHJcbiAqL1xyXG5cclxuOyhmdW5jdGlvbihpc05vZGUpIHtcclxuXHJcblx0LyoqXHJcblx0ICogTWVyZ2Ugb25lIG9yIG1vcmUgb2JqZWN0cyBcclxuXHQgKiBAcGFyYW0gYm9vbD8gY2xvbmVcclxuXHQgKiBAcGFyYW0gbWl4ZWQsLi4uIGFyZ3VtZW50c1xyXG5cdCAqIEByZXR1cm4gb2JqZWN0XHJcblx0ICovXHJcblxyXG5cdHZhciBQdWJsaWMgPSBmdW5jdGlvbihjbG9uZSkge1xyXG5cclxuXHRcdHJldHVybiBtZXJnZShjbG9uZSA9PT0gdHJ1ZSwgZmFsc2UsIGFyZ3VtZW50cyk7XHJcblxyXG5cdH0sIHB1YmxpY05hbWUgPSAnbWVyZ2UnO1xyXG5cclxuXHQvKipcclxuXHQgKiBNZXJnZSB0d28gb3IgbW9yZSBvYmplY3RzIHJlY3Vyc2l2ZWx5IFxyXG5cdCAqIEBwYXJhbSBib29sPyBjbG9uZVxyXG5cdCAqIEBwYXJhbSBtaXhlZCwuLi4gYXJndW1lbnRzXHJcblx0ICogQHJldHVybiBvYmplY3RcclxuXHQgKi9cclxuXHJcblx0UHVibGljLnJlY3Vyc2l2ZSA9IGZ1bmN0aW9uKGNsb25lKSB7XHJcblxyXG5cdFx0cmV0dXJuIG1lcmdlKGNsb25lID09PSB0cnVlLCB0cnVlLCBhcmd1bWVudHMpO1xyXG5cclxuXHR9O1xyXG5cclxuXHQvKipcclxuXHQgKiBDbG9uZSB0aGUgaW5wdXQgcmVtb3ZpbmcgYW55IHJlZmVyZW5jZVxyXG5cdCAqIEBwYXJhbSBtaXhlZCBpbnB1dFxyXG5cdCAqIEByZXR1cm4gbWl4ZWRcclxuXHQgKi9cclxuXHJcblx0UHVibGljLmNsb25lID0gZnVuY3Rpb24oaW5wdXQpIHtcclxuXHJcblx0XHR2YXIgb3V0cHV0ID0gaW5wdXQsXHJcblx0XHRcdHR5cGUgPSB0eXBlT2YoaW5wdXQpLFxyXG5cdFx0XHRpbmRleCwgc2l6ZTtcclxuXHJcblx0XHRpZiAodHlwZSA9PT0gJ2FycmF5Jykge1xyXG5cclxuXHRcdFx0b3V0cHV0ID0gW107XHJcblx0XHRcdHNpemUgPSBpbnB1dC5sZW5ndGg7XHJcblxyXG5cdFx0XHRmb3IgKGluZGV4PTA7aW5kZXg8c2l6ZTsrK2luZGV4KVxyXG5cclxuXHRcdFx0XHRvdXRwdXRbaW5kZXhdID0gUHVibGljLmNsb25lKGlucHV0W2luZGV4XSk7XHJcblxyXG5cdFx0fSBlbHNlIGlmICh0eXBlID09PSAnb2JqZWN0Jykge1xyXG5cclxuXHRcdFx0b3V0cHV0ID0ge307XHJcblxyXG5cdFx0XHRmb3IgKGluZGV4IGluIGlucHV0KVxyXG5cclxuXHRcdFx0XHRvdXRwdXRbaW5kZXhdID0gUHVibGljLmNsb25lKGlucHV0W2luZGV4XSk7XHJcblxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBvdXRwdXQ7XHJcblxyXG5cdH07XHJcblxyXG5cdC8qKlxyXG5cdCAqIE1lcmdlIHR3byBvYmplY3RzIHJlY3Vyc2l2ZWx5XHJcblx0ICogQHBhcmFtIG1peGVkIGlucHV0XHJcblx0ICogQHBhcmFtIG1peGVkIGV4dGVuZFxyXG5cdCAqIEByZXR1cm4gbWl4ZWRcclxuXHQgKi9cclxuXHJcblx0ZnVuY3Rpb24gbWVyZ2VfcmVjdXJzaXZlKGJhc2UsIGV4dGVuZCkge1xyXG5cclxuXHRcdGlmICh0eXBlT2YoYmFzZSkgIT09ICdvYmplY3QnKVxyXG5cclxuXHRcdFx0cmV0dXJuIGV4dGVuZDtcclxuXHJcblx0XHRmb3IgKHZhciBrZXkgaW4gZXh0ZW5kKSB7XHJcblxyXG5cdFx0XHRpZiAodHlwZU9mKGJhc2Vba2V5XSkgPT09ICdvYmplY3QnICYmIHR5cGVPZihleHRlbmRba2V5XSkgPT09ICdvYmplY3QnKSB7XHJcblxyXG5cdFx0XHRcdGJhc2Vba2V5XSA9IG1lcmdlX3JlY3Vyc2l2ZShiYXNlW2tleV0sIGV4dGVuZFtrZXldKTtcclxuXHJcblx0XHRcdH0gZWxzZSB7XHJcblxyXG5cdFx0XHRcdGJhc2Vba2V5XSA9IGV4dGVuZFtrZXldO1xyXG5cclxuXHRcdFx0fVxyXG5cclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gYmFzZTtcclxuXHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBNZXJnZSB0d28gb3IgbW9yZSBvYmplY3RzXHJcblx0ICogQHBhcmFtIGJvb2wgY2xvbmVcclxuXHQgKiBAcGFyYW0gYm9vbCByZWN1cnNpdmVcclxuXHQgKiBAcGFyYW0gYXJyYXkgYXJndlxyXG5cdCAqIEByZXR1cm4gb2JqZWN0XHJcblx0ICovXHJcblxyXG5cdGZ1bmN0aW9uIG1lcmdlKGNsb25lLCByZWN1cnNpdmUsIGFyZ3YpIHtcclxuXHJcblx0XHR2YXIgcmVzdWx0ID0gYXJndlswXSxcclxuXHRcdFx0c2l6ZSA9IGFyZ3YubGVuZ3RoO1xyXG5cclxuXHRcdGlmIChjbG9uZSB8fCB0eXBlT2YocmVzdWx0KSAhPT0gJ29iamVjdCcpXHJcblxyXG5cdFx0XHRyZXN1bHQgPSB7fTtcclxuXHJcblx0XHRmb3IgKHZhciBpbmRleD0wO2luZGV4PHNpemU7KytpbmRleCkge1xyXG5cclxuXHRcdFx0dmFyIGl0ZW0gPSBhcmd2W2luZGV4XSxcclxuXHJcblx0XHRcdFx0dHlwZSA9IHR5cGVPZihpdGVtKTtcclxuXHJcblx0XHRcdGlmICh0eXBlICE9PSAnb2JqZWN0JykgY29udGludWU7XHJcblxyXG5cdFx0XHRmb3IgKHZhciBrZXkgaW4gaXRlbSkge1xyXG5cclxuXHRcdFx0XHR2YXIgc2l0ZW0gPSBjbG9uZSA/IFB1YmxpYy5jbG9uZShpdGVtW2tleV0pIDogaXRlbVtrZXldO1xyXG5cclxuXHRcdFx0XHRpZiAocmVjdXJzaXZlKSB7XHJcblxyXG5cdFx0XHRcdFx0cmVzdWx0W2tleV0gPSBtZXJnZV9yZWN1cnNpdmUocmVzdWx0W2tleV0sIHNpdGVtKTtcclxuXHJcblx0XHRcdFx0fSBlbHNlIHtcclxuXHJcblx0XHRcdFx0XHRyZXN1bHRba2V5XSA9IHNpdGVtO1xyXG5cclxuXHRcdFx0XHR9XHJcblxyXG5cdFx0XHR9XHJcblxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiByZXN1bHQ7XHJcblxyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogR2V0IHR5cGUgb2YgdmFyaWFibGVcclxuXHQgKiBAcGFyYW0gbWl4ZWQgaW5wdXRcclxuXHQgKiBAcmV0dXJuIHN0cmluZ1xyXG5cdCAqXHJcblx0ICogQHNlZSBodHRwOi8vanNwZXJmLmNvbS90eXBlb2Z2YXJcclxuXHQgKi9cclxuXHJcblx0ZnVuY3Rpb24gdHlwZU9mKGlucHV0KSB7XHJcblxyXG5cdFx0cmV0dXJuICh7fSkudG9TdHJpbmcuY2FsbChpbnB1dCkuc2xpY2UoOCwgLTEpLnRvTG93ZXJDYXNlKCk7XHJcblxyXG5cdH1cclxuXHJcblx0aWYgKGlzTm9kZSkge1xyXG5cclxuXHRcdG1vZHVsZS5leHBvcnRzID0gUHVibGljO1xyXG5cclxuXHR9IGVsc2Uge1xyXG5cclxuXHRcdHdpbmRvd1twdWJsaWNOYW1lXSA9IFB1YmxpYztcclxuXHJcblx0fVxyXG5cclxufSkodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgbW9kdWxlICYmIHR5cGVvZiBtb2R1bGUuZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMpOyIsIi8qKlxuICAjIG5vcm1hbGljZVxuXG4gIE5vcm1hbGl6ZSBhbiBpY2Ugc2VydmVyIGNvbmZpZ3VyYXRpb24gb2JqZWN0IChvciBwbGFpbiBvbGQgc3RyaW5nKSBpbnRvIGEgZm9ybWF0XG4gIHRoYXQgaXMgdXNhYmxlIGluIGFsbCBicm93c2VycyBzdXBwb3J0aW5nIFdlYlJUQy4gIFByaW1hcmlseSB0aGlzIG1vZHVsZSBpcyBkZXNpZ25lZFxuICB0byBoZWxwIHdpdGggdGhlIHRyYW5zaXRpb24gb2YgdGhlIGB1cmxgIGF0dHJpYnV0ZSBvZiB0aGUgY29uZmlndXJhdGlvbiBvYmplY3QgdG9cbiAgdGhlIGB1cmxzYCBhdHRyaWJ1dGUuXG5cbiAgIyMgRXhhbXBsZSBVc2FnZVxuXG4gIDw8PCBleGFtcGxlcy9zaW1wbGUuanNcblxuKiovXG5cbnZhciBwcm90b2NvbHMgPSBbXG4gICdzdHVuOicsXG4gICd0dXJuOidcbl07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaW5wdXQpIHtcbiAgdmFyIHVybCA9IChpbnB1dCB8fCB7fSkudXJsIHx8IGlucHV0O1xuICB2YXIgcHJvdG9jb2w7XG4gIHZhciBwYXJ0cztcbiAgdmFyIG91dHB1dCA9IHt9O1xuXG4gIC8vIGlmIHdlIGRvbid0IGhhdmUgYSBzdHJpbmcgdXJsLCB0aGVuIGFsbG93IHRoZSBpbnB1dCB0byBwYXNzdGhyb3VnaFxuICBpZiAodHlwZW9mIHVybCAhPSAnc3RyaW5nJyAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICByZXR1cm4gaW5wdXQ7XG4gIH1cblxuICAvLyB0cmltIHRoZSB1cmwgc3RyaW5nLCBhbmQgY29udmVydCB0byBhbiBhcnJheVxuICB1cmwgPSB1cmwudHJpbSgpO1xuXG4gIC8vIGlmIHRoZSBwcm90b2NvbCBpcyBub3Qga25vd24sIHRoZW4gcGFzc3Rocm91Z2hcbiAgcHJvdG9jb2wgPSBwcm90b2NvbHNbcHJvdG9jb2xzLmluZGV4T2YodXJsLnNsaWNlKDAsIDUpKV07XG4gIGlmICghIHByb3RvY29sKSB7XG4gICAgcmV0dXJuIGlucHV0O1xuICB9XG5cbiAgLy8gbm93IGxldCdzIGF0dGFjayB0aGUgcmVtYWluaW5nIHVybCBwYXJ0c1xuICB1cmwgPSB1cmwuc2xpY2UoNSk7XG4gIHBhcnRzID0gdXJsLnNwbGl0KCdAJyk7XG5cbiAgb3V0cHV0LnVzZXJuYW1lID0gaW5wdXQudXNlcm5hbWU7XG4gIG91dHB1dC5jcmVkZW50aWFsID0gaW5wdXQuY3JlZGVudGlhbDtcbiAgLy8gaWYgd2UgaGF2ZSBhbiBhdXRoZW50aWNhdGlvbiBwYXJ0LCB0aGVuIHNldCB0aGUgY3JlZGVudGlhbHNcbiAgaWYgKHBhcnRzLmxlbmd0aCA+IDEpIHtcbiAgICB1cmwgPSBwYXJ0c1sxXTtcbiAgICBwYXJ0cyA9IHBhcnRzWzBdLnNwbGl0KCc6Jyk7XG5cbiAgICAvLyBhZGQgdGhlIG91dHB1dCBjcmVkZW50aWFsIGFuZCB1c2VybmFtZVxuICAgIG91dHB1dC51c2VybmFtZSA9IHBhcnRzWzBdO1xuICAgIG91dHB1dC5jcmVkZW50aWFsID0gKGlucHV0IHx8IHt9KS5jcmVkZW50aWFsIHx8IHBhcnRzWzFdIHx8ICcnO1xuICB9XG5cbiAgb3V0cHV0LnVybCA9IHByb3RvY29sICsgdXJsO1xuICBvdXRwdXQudXJscyA9IFsgb3V0cHV0LnVybCBdO1xuXG4gIHJldHVybiBvdXRwdXQ7XG59O1xuIiwiLy8gc2hpbSBmb3IgdXNpbmcgcHJvY2VzcyBpbiBicm93c2VyXG52YXIgcHJvY2VzcyA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbi8vIGNhY2hlZCBmcm9tIHdoYXRldmVyIGdsb2JhbCBpcyBwcmVzZW50IHNvIHRoYXQgdGVzdCBydW5uZXJzIHRoYXQgc3R1YiBpdFxuLy8gZG9uJ3QgYnJlYWsgdGhpbmdzLiAgQnV0IHdlIG5lZWQgdG8gd3JhcCBpdCBpbiBhIHRyeSBjYXRjaCBpbiBjYXNlIGl0IGlzXG4vLyB3cmFwcGVkIGluIHN0cmljdCBtb2RlIGNvZGUgd2hpY2ggZG9lc24ndCBkZWZpbmUgYW55IGdsb2JhbHMuICBJdCdzIGluc2lkZSBhXG4vLyBmdW5jdGlvbiBiZWNhdXNlIHRyeS9jYXRjaGVzIGRlb3B0aW1pemUgaW4gY2VydGFpbiBlbmdpbmVzLlxuXG52YXIgY2FjaGVkU2V0VGltZW91dDtcbnZhciBjYWNoZWRDbGVhclRpbWVvdXQ7XG5cbmZ1bmN0aW9uIGRlZmF1bHRTZXRUaW1vdXQoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzZXRUaW1lb3V0IGhhcyBub3QgYmVlbiBkZWZpbmVkJyk7XG59XG5mdW5jdGlvbiBkZWZhdWx0Q2xlYXJUaW1lb3V0ICgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NsZWFyVGltZW91dCBoYXMgbm90IGJlZW4gZGVmaW5lZCcpO1xufVxuKGZ1bmN0aW9uICgpIHtcbiAgICB0cnkge1xuICAgICAgICBpZiAodHlwZW9mIHNldFRpbWVvdXQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGNhY2hlZFNldFRpbWVvdXQgPSBzZXRUaW1lb3V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IGRlZmF1bHRTZXRUaW1vdXQ7XG4gICAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNhY2hlZFNldFRpbWVvdXQgPSBkZWZhdWx0U2V0VGltb3V0O1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICBpZiAodHlwZW9mIGNsZWFyVGltZW91dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gY2xlYXJUaW1lb3V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gZGVmYXVsdENsZWFyVGltZW91dDtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gZGVmYXVsdENsZWFyVGltZW91dDtcbiAgICB9XG59ICgpKVxuZnVuY3Rpb24gcnVuVGltZW91dChmdW4pIHtcbiAgICBpZiAoY2FjaGVkU2V0VGltZW91dCA9PT0gc2V0VGltZW91dCkge1xuICAgICAgICAvL25vcm1hbCBlbnZpcm9tZW50cyBpbiBzYW5lIHNpdHVhdGlvbnNcbiAgICAgICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9XG4gICAgLy8gaWYgc2V0VGltZW91dCB3YXNuJ3QgYXZhaWxhYmxlIGJ1dCB3YXMgbGF0dGVyIGRlZmluZWRcbiAgICBpZiAoKGNhY2hlZFNldFRpbWVvdXQgPT09IGRlZmF1bHRTZXRUaW1vdXQgfHwgIWNhY2hlZFNldFRpbWVvdXQpICYmIHNldFRpbWVvdXQpIHtcbiAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IHNldFRpbWVvdXQ7XG4gICAgICAgIHJldHVybiBzZXRUaW1lb3V0KGZ1biwgMCk7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIC8vIHdoZW4gd2hlbiBzb21lYm9keSBoYXMgc2NyZXdlZCB3aXRoIHNldFRpbWVvdXQgYnV0IG5vIEkuRS4gbWFkZG5lc3NcbiAgICAgICAgcmV0dXJuIGNhY2hlZFNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9IGNhdGNoKGUpe1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gV2hlbiB3ZSBhcmUgaW4gSS5FLiBidXQgdGhlIHNjcmlwdCBoYXMgYmVlbiBldmFsZWQgc28gSS5FLiBkb2Vzbid0IHRydXN0IHRoZSBnbG9iYWwgb2JqZWN0IHdoZW4gY2FsbGVkIG5vcm1hbGx5XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dC5jYWxsKG51bGwsIGZ1biwgMCk7XG4gICAgICAgIH0gY2F0Y2goZSl7XG4gICAgICAgICAgICAvLyBzYW1lIGFzIGFib3ZlIGJ1dCB3aGVuIGl0J3MgYSB2ZXJzaW9uIG9mIEkuRS4gdGhhdCBtdXN0IGhhdmUgdGhlIGdsb2JhbCBvYmplY3QgZm9yICd0aGlzJywgaG9wZnVsbHkgb3VyIGNvbnRleHQgY29ycmVjdCBvdGhlcndpc2UgaXQgd2lsbCB0aHJvdyBhIGdsb2JhbCBlcnJvclxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZFNldFRpbWVvdXQuY2FsbCh0aGlzLCBmdW4sIDApO1xuICAgICAgICB9XG4gICAgfVxuXG5cbn1cbmZ1bmN0aW9uIHJ1bkNsZWFyVGltZW91dChtYXJrZXIpIHtcbiAgICBpZiAoY2FjaGVkQ2xlYXJUaW1lb3V0ID09PSBjbGVhclRpbWVvdXQpIHtcbiAgICAgICAgLy9ub3JtYWwgZW52aXJvbWVudHMgaW4gc2FuZSBzaXR1YXRpb25zXG4gICAgICAgIHJldHVybiBjbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9XG4gICAgLy8gaWYgY2xlYXJUaW1lb3V0IHdhc24ndCBhdmFpbGFibGUgYnV0IHdhcyBsYXR0ZXIgZGVmaW5lZFxuICAgIGlmICgoY2FjaGVkQ2xlYXJUaW1lb3V0ID09PSBkZWZhdWx0Q2xlYXJUaW1lb3V0IHx8ICFjYWNoZWRDbGVhclRpbWVvdXQpICYmIGNsZWFyVGltZW91dCkge1xuICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBjbGVhclRpbWVvdXQ7XG4gICAgICAgIHJldHVybiBjbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgLy8gd2hlbiB3aGVuIHNvbWVib2R5IGhhcyBzY3Jld2VkIHdpdGggc2V0VGltZW91dCBidXQgbm8gSS5FLiBtYWRkbmVzc1xuICAgICAgICByZXR1cm4gY2FjaGVkQ2xlYXJUaW1lb3V0KG1hcmtlcik7XG4gICAgfSBjYXRjaCAoZSl7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBpbiBJLkUuIGJ1dCB0aGUgc2NyaXB0IGhhcyBiZWVuIGV2YWxlZCBzbyBJLkUuIGRvZXNuJ3QgIHRydXN0IHRoZSBnbG9iYWwgb2JqZWN0IHdoZW4gY2FsbGVkIG5vcm1hbGx5XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkQ2xlYXJUaW1lb3V0LmNhbGwobnVsbCwgbWFya2VyKTtcbiAgICAgICAgfSBjYXRjaCAoZSl7XG4gICAgICAgICAgICAvLyBzYW1lIGFzIGFib3ZlIGJ1dCB3aGVuIGl0J3MgYSB2ZXJzaW9uIG9mIEkuRS4gdGhhdCBtdXN0IGhhdmUgdGhlIGdsb2JhbCBvYmplY3QgZm9yICd0aGlzJywgaG9wZnVsbHkgb3VyIGNvbnRleHQgY29ycmVjdCBvdGhlcndpc2UgaXQgd2lsbCB0aHJvdyBhIGdsb2JhbCBlcnJvci5cbiAgICAgICAgICAgIC8vIFNvbWUgdmVyc2lvbnMgb2YgSS5FLiBoYXZlIGRpZmZlcmVudCBydWxlcyBmb3IgY2xlYXJUaW1lb3V0IHZzIHNldFRpbWVvdXRcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQuY2FsbCh0aGlzLCBtYXJrZXIpO1xuICAgICAgICB9XG4gICAgfVxuXG5cblxufVxudmFyIHF1ZXVlID0gW107XG52YXIgZHJhaW5pbmcgPSBmYWxzZTtcbnZhciBjdXJyZW50UXVldWU7XG52YXIgcXVldWVJbmRleCA9IC0xO1xuXG5mdW5jdGlvbiBjbGVhblVwTmV4dFRpY2soKSB7XG4gICAgaWYgKCFkcmFpbmluZyB8fCAhY3VycmVudFF1ZXVlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbiAgICBpZiAoY3VycmVudFF1ZXVlLmxlbmd0aCkge1xuICAgICAgICBxdWV1ZSA9IGN1cnJlbnRRdWV1ZS5jb25jYXQocXVldWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHF1ZXVlSW5kZXggPSAtMTtcbiAgICB9XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCkge1xuICAgICAgICBkcmFpblF1ZXVlKCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkcmFpblF1ZXVlKCkge1xuICAgIGlmIChkcmFpbmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciB0aW1lb3V0ID0gcnVuVGltZW91dChjbGVhblVwTmV4dFRpY2spO1xuICAgIGRyYWluaW5nID0gdHJ1ZTtcblxuICAgIHZhciBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgd2hpbGUobGVuKSB7XG4gICAgICAgIGN1cnJlbnRRdWV1ZSA9IHF1ZXVlO1xuICAgICAgICBxdWV1ZSA9IFtdO1xuICAgICAgICB3aGlsZSAoKytxdWV1ZUluZGV4IDwgbGVuKSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudFF1ZXVlKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudFF1ZXVlW3F1ZXVlSW5kZXhdLnJ1bigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHF1ZXVlSW5kZXggPSAtMTtcbiAgICAgICAgbGVuID0gcXVldWUubGVuZ3RoO1xuICAgIH1cbiAgICBjdXJyZW50UXVldWUgPSBudWxsO1xuICAgIGRyYWluaW5nID0gZmFsc2U7XG4gICAgcnVuQ2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xufVxuXG5wcm9jZXNzLm5leHRUaWNrID0gZnVuY3Rpb24gKGZ1bikge1xuICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGggLSAxKTtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgICB9XG4gICAgfVxuICAgIHF1ZXVlLnB1c2gobmV3IEl0ZW0oZnVuLCBhcmdzKSk7XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCA9PT0gMSAmJiAhZHJhaW5pbmcpIHtcbiAgICAgICAgcnVuVGltZW91dChkcmFpblF1ZXVlKTtcbiAgICB9XG59O1xuXG4vLyB2OCBsaWtlcyBwcmVkaWN0aWJsZSBvYmplY3RzXG5mdW5jdGlvbiBJdGVtKGZ1biwgYXJyYXkpIHtcbiAgICB0aGlzLmZ1biA9IGZ1bjtcbiAgICB0aGlzLmFycmF5ID0gYXJyYXk7XG59XG5JdGVtLnByb3RvdHlwZS5ydW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5mdW4uYXBwbHkobnVsbCwgdGhpcy5hcnJheSk7XG59O1xucHJvY2Vzcy50aXRsZSA9ICdicm93c2VyJztcbnByb2Nlc3MuYnJvd3NlciA9IHRydWU7XG5wcm9jZXNzLmVudiA9IHt9O1xucHJvY2Vzcy5hcmd2ID0gW107XG5wcm9jZXNzLnZlcnNpb24gPSAnJzsgLy8gZW1wdHkgc3RyaW5nIHRvIGF2b2lkIHJlZ2V4cCBpc3N1ZXNcbnByb2Nlc3MudmVyc2lvbnMgPSB7fTtcblxuZnVuY3Rpb24gbm9vcCgpIHt9XG5cbnByb2Nlc3Mub24gPSBub29wO1xucHJvY2Vzcy5hZGRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLm9uY2UgPSBub29wO1xucHJvY2Vzcy5vZmYgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUFsbExpc3RlbmVycyA9IG5vb3A7XG5wcm9jZXNzLmVtaXQgPSBub29wO1xucHJvY2Vzcy5wcmVwZW5kTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5wcmVwZW5kT25jZUxpc3RlbmVyID0gbm9vcDtcblxucHJvY2Vzcy5saXN0ZW5lcnMgPSBmdW5jdGlvbiAobmFtZSkgeyByZXR1cm4gW10gfVxuXG5wcm9jZXNzLmJpbmRpbmcgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5iaW5kaW5nIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5cbnByb2Nlc3MuY3dkID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gJy8nIH07XG5wcm9jZXNzLmNoZGlyID0gZnVuY3Rpb24gKGRpcikge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5jaGRpciBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xucHJvY2Vzcy51bWFzayA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gMDsgfTtcbiIsIi8qXG4gKiAgQ29weXJpZ2h0IChjKSAyMDE3IFRoZSBXZWJSVEMgcHJvamVjdCBhdXRob3JzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqICBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhIEJTRC1zdHlsZSBsaWNlbnNlXG4gKiAgdGhhdCBjYW4gYmUgZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBvZiB0aGUgc291cmNlXG4gKiAgdHJlZS5cbiAqL1xuIC8qIGVzbGludC1lbnYgbm9kZSAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgU0RQVXRpbHMgPSByZXF1aXJlKCdzZHAnKTtcblxuZnVuY3Rpb24gd3JpdGVNZWRpYVNlY3Rpb24odHJhbnNjZWl2ZXIsIGNhcHMsIHR5cGUsIHN0cmVhbSwgZHRsc1JvbGUpIHtcbiAgdmFyIHNkcCA9IFNEUFV0aWxzLndyaXRlUnRwRGVzY3JpcHRpb24odHJhbnNjZWl2ZXIua2luZCwgY2Fwcyk7XG5cbiAgLy8gTWFwIElDRSBwYXJhbWV0ZXJzICh1ZnJhZywgcHdkKSB0byBTRFAuXG4gIHNkcCArPSBTRFBVdGlscy53cml0ZUljZVBhcmFtZXRlcnMoXG4gICAgICB0cmFuc2NlaXZlci5pY2VHYXRoZXJlci5nZXRMb2NhbFBhcmFtZXRlcnMoKSk7XG5cbiAgLy8gTWFwIERUTFMgcGFyYW1ldGVycyB0byBTRFAuXG4gIHNkcCArPSBTRFBVdGlscy53cml0ZUR0bHNQYXJhbWV0ZXJzKFxuICAgICAgdHJhbnNjZWl2ZXIuZHRsc1RyYW5zcG9ydC5nZXRMb2NhbFBhcmFtZXRlcnMoKSxcbiAgICAgIHR5cGUgPT09ICdvZmZlcicgPyAnYWN0cGFzcycgOiBkdGxzUm9sZSB8fCAnYWN0aXZlJyk7XG5cbiAgc2RwICs9ICdhPW1pZDonICsgdHJhbnNjZWl2ZXIubWlkICsgJ1xcclxcbic7XG5cbiAgaWYgKHRyYW5zY2VpdmVyLnJ0cFNlbmRlciAmJiB0cmFuc2NlaXZlci5ydHBSZWNlaXZlcikge1xuICAgIHNkcCArPSAnYT1zZW5kcmVjdlxcclxcbic7XG4gIH0gZWxzZSBpZiAodHJhbnNjZWl2ZXIucnRwU2VuZGVyKSB7XG4gICAgc2RwICs9ICdhPXNlbmRvbmx5XFxyXFxuJztcbiAgfSBlbHNlIGlmICh0cmFuc2NlaXZlci5ydHBSZWNlaXZlcikge1xuICAgIHNkcCArPSAnYT1yZWN2b25seVxcclxcbic7XG4gIH0gZWxzZSB7XG4gICAgc2RwICs9ICdhPWluYWN0aXZlXFxyXFxuJztcbiAgfVxuXG4gIGlmICh0cmFuc2NlaXZlci5ydHBTZW5kZXIpIHtcbiAgICB2YXIgdHJhY2tJZCA9IHRyYW5zY2VpdmVyLnJ0cFNlbmRlci5faW5pdGlhbFRyYWNrSWQgfHxcbiAgICAgICAgdHJhbnNjZWl2ZXIucnRwU2VuZGVyLnRyYWNrLmlkO1xuICAgIHRyYW5zY2VpdmVyLnJ0cFNlbmRlci5faW5pdGlhbFRyYWNrSWQgPSB0cmFja0lkO1xuICAgIC8vIHNwZWMuXG4gICAgdmFyIG1zaWQgPSAnbXNpZDonICsgKHN0cmVhbSA/IHN0cmVhbS5pZCA6ICctJykgKyAnICcgK1xuICAgICAgICB0cmFja0lkICsgJ1xcclxcbic7XG4gICAgc2RwICs9ICdhPScgKyBtc2lkO1xuICAgIC8vIGZvciBDaHJvbWUuIExlZ2FjeSBzaG91bGQgbm8gbG9uZ2VyIGJlIHJlcXVpcmVkLlxuICAgIHNkcCArPSAnYT1zc3JjOicgKyB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzWzBdLnNzcmMgK1xuICAgICAgICAnICcgKyBtc2lkO1xuXG4gICAgLy8gUlRYXG4gICAgaWYgKHRyYW5zY2VpdmVyLnNlbmRFbmNvZGluZ1BhcmFtZXRlcnNbMF0ucnR4KSB7XG4gICAgICBzZHAgKz0gJ2E9c3NyYzonICsgdHJhbnNjZWl2ZXIuc2VuZEVuY29kaW5nUGFyYW1ldGVyc1swXS5ydHguc3NyYyArXG4gICAgICAgICAgJyAnICsgbXNpZDtcbiAgICAgIHNkcCArPSAnYT1zc3JjLWdyb3VwOkZJRCAnICtcbiAgICAgICAgICB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzWzBdLnNzcmMgKyAnICcgK1xuICAgICAgICAgIHRyYW5zY2VpdmVyLnNlbmRFbmNvZGluZ1BhcmFtZXRlcnNbMF0ucnR4LnNzcmMgK1xuICAgICAgICAgICdcXHJcXG4nO1xuICAgIH1cbiAgfVxuICAvLyBGSVhNRTogdGhpcyBzaG91bGQgYmUgd3JpdHRlbiBieSB3cml0ZVJ0cERlc2NyaXB0aW9uLlxuICBzZHAgKz0gJ2E9c3NyYzonICsgdHJhbnNjZWl2ZXIuc2VuZEVuY29kaW5nUGFyYW1ldGVyc1swXS5zc3JjICtcbiAgICAgICcgY25hbWU6JyArIFNEUFV0aWxzLmxvY2FsQ05hbWUgKyAnXFxyXFxuJztcbiAgaWYgKHRyYW5zY2VpdmVyLnJ0cFNlbmRlciAmJiB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzWzBdLnJ0eCkge1xuICAgIHNkcCArPSAnYT1zc3JjOicgKyB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzWzBdLnJ0eC5zc3JjICtcbiAgICAgICAgJyBjbmFtZTonICsgU0RQVXRpbHMubG9jYWxDTmFtZSArICdcXHJcXG4nO1xuICB9XG4gIHJldHVybiBzZHA7XG59XG5cbi8vIEVkZ2UgZG9lcyBub3QgbGlrZVxuLy8gMSkgc3R1bjogZmlsdGVyZWQgYWZ0ZXIgMTQzOTMgdW5sZXNzID90cmFuc3BvcnQ9dWRwIGlzIHByZXNlbnRcbi8vIDIpIHR1cm46IHRoYXQgZG9lcyBub3QgaGF2ZSBhbGwgb2YgdHVybjpob3N0OnBvcnQ/dHJhbnNwb3J0PXVkcFxuLy8gMykgdHVybjogd2l0aCBpcHY2IGFkZHJlc3Nlc1xuLy8gNCkgdHVybjogb2NjdXJyaW5nIG11bGlwbGUgdGltZXNcbmZ1bmN0aW9uIGZpbHRlckljZVNlcnZlcnMoaWNlU2VydmVycywgZWRnZVZlcnNpb24pIHtcbiAgdmFyIGhhc1R1cm4gPSBmYWxzZTtcbiAgaWNlU2VydmVycyA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoaWNlU2VydmVycykpO1xuICByZXR1cm4gaWNlU2VydmVycy5maWx0ZXIoZnVuY3Rpb24oc2VydmVyKSB7XG4gICAgaWYgKHNlcnZlciAmJiAoc2VydmVyLnVybHMgfHwgc2VydmVyLnVybCkpIHtcbiAgICAgIHZhciB1cmxzID0gc2VydmVyLnVybHMgfHwgc2VydmVyLnVybDtcbiAgICAgIGlmIChzZXJ2ZXIudXJsICYmICFzZXJ2ZXIudXJscykge1xuICAgICAgICBjb25zb2xlLndhcm4oJ1JUQ0ljZVNlcnZlci51cmwgaXMgZGVwcmVjYXRlZCEgVXNlIHVybHMgaW5zdGVhZC4nKTtcbiAgICAgIH1cbiAgICAgIHZhciBpc1N0cmluZyA9IHR5cGVvZiB1cmxzID09PSAnc3RyaW5nJztcbiAgICAgIGlmIChpc1N0cmluZykge1xuICAgICAgICB1cmxzID0gW3VybHNdO1xuICAgICAgfVxuICAgICAgdXJscyA9IHVybHMuZmlsdGVyKGZ1bmN0aW9uKHVybCkge1xuICAgICAgICB2YXIgdmFsaWRUdXJuID0gdXJsLmluZGV4T2YoJ3R1cm46JykgPT09IDAgJiZcbiAgICAgICAgICAgIHVybC5pbmRleE9mKCd0cmFuc3BvcnQ9dWRwJykgIT09IC0xICYmXG4gICAgICAgICAgICB1cmwuaW5kZXhPZigndHVybjpbJykgPT09IC0xICYmXG4gICAgICAgICAgICAhaGFzVHVybjtcblxuICAgICAgICBpZiAodmFsaWRUdXJuKSB7XG4gICAgICAgICAgaGFzVHVybiA9IHRydWU7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVybC5pbmRleE9mKCdzdHVuOicpID09PSAwICYmIGVkZ2VWZXJzaW9uID49IDE0MzkzICYmXG4gICAgICAgICAgICB1cmwuaW5kZXhPZignP3RyYW5zcG9ydD11ZHAnKSA9PT0gLTE7XG4gICAgICB9KTtcblxuICAgICAgZGVsZXRlIHNlcnZlci51cmw7XG4gICAgICBzZXJ2ZXIudXJscyA9IGlzU3RyaW5nID8gdXJsc1swXSA6IHVybHM7XG4gICAgICByZXR1cm4gISF1cmxzLmxlbmd0aDtcbiAgICB9XG4gIH0pO1xufVxuXG4vLyBEZXRlcm1pbmVzIHRoZSBpbnRlcnNlY3Rpb24gb2YgbG9jYWwgYW5kIHJlbW90ZSBjYXBhYmlsaXRpZXMuXG5mdW5jdGlvbiBnZXRDb21tb25DYXBhYmlsaXRpZXMobG9jYWxDYXBhYmlsaXRpZXMsIHJlbW90ZUNhcGFiaWxpdGllcykge1xuICB2YXIgY29tbW9uQ2FwYWJpbGl0aWVzID0ge1xuICAgIGNvZGVjczogW10sXG4gICAgaGVhZGVyRXh0ZW5zaW9uczogW10sXG4gICAgZmVjTWVjaGFuaXNtczogW11cbiAgfTtcblxuICB2YXIgZmluZENvZGVjQnlQYXlsb2FkVHlwZSA9IGZ1bmN0aW9uKHB0LCBjb2RlY3MpIHtcbiAgICBwdCA9IHBhcnNlSW50KHB0LCAxMCk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb2RlY3MubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChjb2RlY3NbaV0ucGF5bG9hZFR5cGUgPT09IHB0IHx8XG4gICAgICAgICAgY29kZWNzW2ldLnByZWZlcnJlZFBheWxvYWRUeXBlID09PSBwdCkge1xuICAgICAgICByZXR1cm4gY29kZWNzW2ldO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICB2YXIgcnR4Q2FwYWJpbGl0eU1hdGNoZXMgPSBmdW5jdGlvbihsUnR4LCByUnR4LCBsQ29kZWNzLCByQ29kZWNzKSB7XG4gICAgdmFyIGxDb2RlYyA9IGZpbmRDb2RlY0J5UGF5bG9hZFR5cGUobFJ0eC5wYXJhbWV0ZXJzLmFwdCwgbENvZGVjcyk7XG4gICAgdmFyIHJDb2RlYyA9IGZpbmRDb2RlY0J5UGF5bG9hZFR5cGUoclJ0eC5wYXJhbWV0ZXJzLmFwdCwgckNvZGVjcyk7XG4gICAgcmV0dXJuIGxDb2RlYyAmJiByQ29kZWMgJiZcbiAgICAgICAgbENvZGVjLm5hbWUudG9Mb3dlckNhc2UoKSA9PT0gckNvZGVjLm5hbWUudG9Mb3dlckNhc2UoKTtcbiAgfTtcblxuICBsb2NhbENhcGFiaWxpdGllcy5jb2RlY3MuZm9yRWFjaChmdW5jdGlvbihsQ29kZWMpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlbW90ZUNhcGFiaWxpdGllcy5jb2RlY3MubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciByQ29kZWMgPSByZW1vdGVDYXBhYmlsaXRpZXMuY29kZWNzW2ldO1xuICAgICAgaWYgKGxDb2RlYy5uYW1lLnRvTG93ZXJDYXNlKCkgPT09IHJDb2RlYy5uYW1lLnRvTG93ZXJDYXNlKCkgJiZcbiAgICAgICAgICBsQ29kZWMuY2xvY2tSYXRlID09PSByQ29kZWMuY2xvY2tSYXRlKSB7XG4gICAgICAgIGlmIChsQ29kZWMubmFtZS50b0xvd2VyQ2FzZSgpID09PSAncnR4JyAmJlxuICAgICAgICAgICAgbENvZGVjLnBhcmFtZXRlcnMgJiYgckNvZGVjLnBhcmFtZXRlcnMuYXB0KSB7XG4gICAgICAgICAgLy8gZm9yIFJUWCB3ZSBuZWVkIHRvIGZpbmQgdGhlIGxvY2FsIHJ0eCB0aGF0IGhhcyBhIGFwdFxuICAgICAgICAgIC8vIHdoaWNoIHBvaW50cyB0byB0aGUgc2FtZSBsb2NhbCBjb2RlYyBhcyB0aGUgcmVtb3RlIG9uZS5cbiAgICAgICAgICBpZiAoIXJ0eENhcGFiaWxpdHlNYXRjaGVzKGxDb2RlYywgckNvZGVjLFxuICAgICAgICAgICAgICBsb2NhbENhcGFiaWxpdGllcy5jb2RlY3MsIHJlbW90ZUNhcGFiaWxpdGllcy5jb2RlY3MpKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgckNvZGVjID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShyQ29kZWMpKTsgLy8gZGVlcGNvcHlcbiAgICAgICAgLy8gbnVtYmVyIG9mIGNoYW5uZWxzIGlzIHRoZSBoaWdoZXN0IGNvbW1vbiBudW1iZXIgb2YgY2hhbm5lbHNcbiAgICAgICAgckNvZGVjLm51bUNoYW5uZWxzID0gTWF0aC5taW4obENvZGVjLm51bUNoYW5uZWxzLFxuICAgICAgICAgICAgckNvZGVjLm51bUNoYW5uZWxzKTtcbiAgICAgICAgLy8gcHVzaCByQ29kZWMgc28gd2UgcmVwbHkgd2l0aCBvZmZlcmVyIHBheWxvYWQgdHlwZVxuICAgICAgICBjb21tb25DYXBhYmlsaXRpZXMuY29kZWNzLnB1c2gockNvZGVjKTtcblxuICAgICAgICAvLyBkZXRlcm1pbmUgY29tbW9uIGZlZWRiYWNrIG1lY2hhbmlzbXNcbiAgICAgICAgckNvZGVjLnJ0Y3BGZWVkYmFjayA9IHJDb2RlYy5ydGNwRmVlZGJhY2suZmlsdGVyKGZ1bmN0aW9uKGZiKSB7XG4gICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBsQ29kZWMucnRjcEZlZWRiYWNrLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBpZiAobENvZGVjLnJ0Y3BGZWVkYmFja1tqXS50eXBlID09PSBmYi50eXBlICYmXG4gICAgICAgICAgICAgICAgbENvZGVjLnJ0Y3BGZWVkYmFja1tqXS5wYXJhbWV0ZXIgPT09IGZiLnBhcmFtZXRlcikge1xuICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9KTtcbiAgICAgICAgLy8gRklYTUU6IGFsc28gbmVlZCB0byBkZXRlcm1pbmUgLnBhcmFtZXRlcnNcbiAgICAgICAgLy8gIHNlZSBodHRwczovL2dpdGh1Yi5jb20vb3BlbnBlZXIvb3J0Yy9pc3N1ZXMvNTY5XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgfSk7XG5cbiAgbG9jYWxDYXBhYmlsaXRpZXMuaGVhZGVyRXh0ZW5zaW9ucy5mb3JFYWNoKGZ1bmN0aW9uKGxIZWFkZXJFeHRlbnNpb24pIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlbW90ZUNhcGFiaWxpdGllcy5oZWFkZXJFeHRlbnNpb25zLmxlbmd0aDtcbiAgICAgICAgIGkrKykge1xuICAgICAgdmFyIHJIZWFkZXJFeHRlbnNpb24gPSByZW1vdGVDYXBhYmlsaXRpZXMuaGVhZGVyRXh0ZW5zaW9uc1tpXTtcbiAgICAgIGlmIChsSGVhZGVyRXh0ZW5zaW9uLnVyaSA9PT0gckhlYWRlckV4dGVuc2lvbi51cmkpIHtcbiAgICAgICAgY29tbW9uQ2FwYWJpbGl0aWVzLmhlYWRlckV4dGVuc2lvbnMucHVzaChySGVhZGVyRXh0ZW5zaW9uKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9KTtcblxuICAvLyBGSVhNRTogZmVjTWVjaGFuaXNtc1xuICByZXR1cm4gY29tbW9uQ2FwYWJpbGl0aWVzO1xufVxuXG4vLyBpcyBhY3Rpb249c2V0TG9jYWxEZXNjcmlwdGlvbiB3aXRoIHR5cGUgYWxsb3dlZCBpbiBzaWduYWxpbmdTdGF0ZVxuZnVuY3Rpb24gaXNBY3Rpb25BbGxvd2VkSW5TaWduYWxpbmdTdGF0ZShhY3Rpb24sIHR5cGUsIHNpZ25hbGluZ1N0YXRlKSB7XG4gIHJldHVybiB7XG4gICAgb2ZmZXI6IHtcbiAgICAgIHNldExvY2FsRGVzY3JpcHRpb246IFsnc3RhYmxlJywgJ2hhdmUtbG9jYWwtb2ZmZXInXSxcbiAgICAgIHNldFJlbW90ZURlc2NyaXB0aW9uOiBbJ3N0YWJsZScsICdoYXZlLXJlbW90ZS1vZmZlciddXG4gICAgfSxcbiAgICBhbnN3ZXI6IHtcbiAgICAgIHNldExvY2FsRGVzY3JpcHRpb246IFsnaGF2ZS1yZW1vdGUtb2ZmZXInLCAnaGF2ZS1sb2NhbC1wcmFuc3dlciddLFxuICAgICAgc2V0UmVtb3RlRGVzY3JpcHRpb246IFsnaGF2ZS1sb2NhbC1vZmZlcicsICdoYXZlLXJlbW90ZS1wcmFuc3dlciddXG4gICAgfVxuICB9W3R5cGVdW2FjdGlvbl0uaW5kZXhPZihzaWduYWxpbmdTdGF0ZSkgIT09IC0xO1xufVxuXG5mdW5jdGlvbiBtYXliZUFkZENhbmRpZGF0ZShpY2VUcmFuc3BvcnQsIGNhbmRpZGF0ZSkge1xuICAvLyBFZGdlJ3MgaW50ZXJuYWwgcmVwcmVzZW50YXRpb24gYWRkcyBzb21lIGZpZWxkcyB0aGVyZWZvcmVcbiAgLy8gbm90IGFsbCBmaWVsZNGVIGFyZSB0YWtlbiBpbnRvIGFjY291bnQuXG4gIHZhciBhbHJlYWR5QWRkZWQgPSBpY2VUcmFuc3BvcnQuZ2V0UmVtb3RlQ2FuZGlkYXRlcygpXG4gICAgICAuZmluZChmdW5jdGlvbihyZW1vdGVDYW5kaWRhdGUpIHtcbiAgICAgICAgcmV0dXJuIGNhbmRpZGF0ZS5mb3VuZGF0aW9uID09PSByZW1vdGVDYW5kaWRhdGUuZm91bmRhdGlvbiAmJlxuICAgICAgICAgICAgY2FuZGlkYXRlLmlwID09PSByZW1vdGVDYW5kaWRhdGUuaXAgJiZcbiAgICAgICAgICAgIGNhbmRpZGF0ZS5wb3J0ID09PSByZW1vdGVDYW5kaWRhdGUucG9ydCAmJlxuICAgICAgICAgICAgY2FuZGlkYXRlLnByaW9yaXR5ID09PSByZW1vdGVDYW5kaWRhdGUucHJpb3JpdHkgJiZcbiAgICAgICAgICAgIGNhbmRpZGF0ZS5wcm90b2NvbCA9PT0gcmVtb3RlQ2FuZGlkYXRlLnByb3RvY29sICYmXG4gICAgICAgICAgICBjYW5kaWRhdGUudHlwZSA9PT0gcmVtb3RlQ2FuZGlkYXRlLnR5cGU7XG4gICAgICB9KTtcbiAgaWYgKCFhbHJlYWR5QWRkZWQpIHtcbiAgICBpY2VUcmFuc3BvcnQuYWRkUmVtb3RlQ2FuZGlkYXRlKGNhbmRpZGF0ZSk7XG4gIH1cbiAgcmV0dXJuICFhbHJlYWR5QWRkZWQ7XG59XG5cblxuZnVuY3Rpb24gbWFrZUVycm9yKG5hbWUsIGRlc2NyaXB0aW9uKSB7XG4gIHZhciBlID0gbmV3IEVycm9yKGRlc2NyaXB0aW9uKTtcbiAgZS5uYW1lID0gbmFtZTtcbiAgLy8gbGVnYWN5IGVycm9yIGNvZGVzIGZyb20gaHR0cHM6Ly9oZXljYW0uZ2l0aHViLmlvL3dlYmlkbC8jaWRsLURPTUV4Y2VwdGlvbi1lcnJvci1uYW1lc1xuICBlLmNvZGUgPSB7XG4gICAgTm90U3VwcG9ydGVkRXJyb3I6IDksXG4gICAgSW52YWxpZFN0YXRlRXJyb3I6IDExLFxuICAgIEludmFsaWRBY2Nlc3NFcnJvcjogMTUsXG4gICAgVHlwZUVycm9yOiB1bmRlZmluZWQsXG4gICAgT3BlcmF0aW9uRXJyb3I6IHVuZGVmaW5lZFxuICB9W25hbWVdO1xuICByZXR1cm4gZTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbih3aW5kb3csIGVkZ2VWZXJzaW9uKSB7XG4gIC8vIGh0dHBzOi8vdzNjLmdpdGh1Yi5pby9tZWRpYWNhcHR1cmUtbWFpbi8jbWVkaWFzdHJlYW1cbiAgLy8gSGVscGVyIGZ1bmN0aW9uIHRvIGFkZCB0aGUgdHJhY2sgdG8gdGhlIHN0cmVhbSBhbmRcbiAgLy8gZGlzcGF0Y2ggdGhlIGV2ZW50IG91cnNlbHZlcy5cbiAgZnVuY3Rpb24gYWRkVHJhY2tUb1N0cmVhbUFuZEZpcmVFdmVudCh0cmFjaywgc3RyZWFtKSB7XG4gICAgc3RyZWFtLmFkZFRyYWNrKHRyYWNrKTtcbiAgICBzdHJlYW0uZGlzcGF0Y2hFdmVudChuZXcgd2luZG93Lk1lZGlhU3RyZWFtVHJhY2tFdmVudCgnYWRkdHJhY2snLFxuICAgICAgICB7dHJhY2s6IHRyYWNrfSkpO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVtb3ZlVHJhY2tGcm9tU3RyZWFtQW5kRmlyZUV2ZW50KHRyYWNrLCBzdHJlYW0pIHtcbiAgICBzdHJlYW0ucmVtb3ZlVHJhY2sodHJhY2spO1xuICAgIHN0cmVhbS5kaXNwYXRjaEV2ZW50KG5ldyB3aW5kb3cuTWVkaWFTdHJlYW1UcmFja0V2ZW50KCdyZW1vdmV0cmFjaycsXG4gICAgICAgIHt0cmFjazogdHJhY2t9KSk7XG4gIH1cblxuICBmdW5jdGlvbiBmaXJlQWRkVHJhY2socGMsIHRyYWNrLCByZWNlaXZlciwgc3RyZWFtcykge1xuICAgIHZhciB0cmFja0V2ZW50ID0gbmV3IEV2ZW50KCd0cmFjaycpO1xuICAgIHRyYWNrRXZlbnQudHJhY2sgPSB0cmFjaztcbiAgICB0cmFja0V2ZW50LnJlY2VpdmVyID0gcmVjZWl2ZXI7XG4gICAgdHJhY2tFdmVudC50cmFuc2NlaXZlciA9IHtyZWNlaXZlcjogcmVjZWl2ZXJ9O1xuICAgIHRyYWNrRXZlbnQuc3RyZWFtcyA9IHN0cmVhbXM7XG4gICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICBwYy5fZGlzcGF0Y2hFdmVudCgndHJhY2snLCB0cmFja0V2ZW50KTtcbiAgICB9KTtcbiAgfVxuXG4gIHZhciBSVENQZWVyQ29ubmVjdGlvbiA9IGZ1bmN0aW9uKGNvbmZpZykge1xuICAgIHZhciBwYyA9IHRoaXM7XG5cbiAgICB2YXIgX2V2ZW50VGFyZ2V0ID0gZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpO1xuICAgIFsnYWRkRXZlbnRMaXN0ZW5lcicsICdyZW1vdmVFdmVudExpc3RlbmVyJywgJ2Rpc3BhdGNoRXZlbnQnXVxuICAgICAgICAuZm9yRWFjaChmdW5jdGlvbihtZXRob2QpIHtcbiAgICAgICAgICBwY1ttZXRob2RdID0gX2V2ZW50VGFyZ2V0W21ldGhvZF0uYmluZChfZXZlbnRUYXJnZXQpO1xuICAgICAgICB9KTtcblxuICAgIHRoaXMuY2FuVHJpY2tsZUljZUNhbmRpZGF0ZXMgPSBudWxsO1xuXG4gICAgdGhpcy5uZWVkTmVnb3RpYXRpb24gPSBmYWxzZTtcblxuICAgIHRoaXMubG9jYWxTdHJlYW1zID0gW107XG4gICAgdGhpcy5yZW1vdGVTdHJlYW1zID0gW107XG5cbiAgICB0aGlzLmxvY2FsRGVzY3JpcHRpb24gPSBudWxsO1xuICAgIHRoaXMucmVtb3RlRGVzY3JpcHRpb24gPSBudWxsO1xuXG4gICAgdGhpcy5zaWduYWxpbmdTdGF0ZSA9ICdzdGFibGUnO1xuICAgIHRoaXMuaWNlQ29ubmVjdGlvblN0YXRlID0gJ25ldyc7XG4gICAgdGhpcy5jb25uZWN0aW9uU3RhdGUgPSAnbmV3JztcbiAgICB0aGlzLmljZUdhdGhlcmluZ1N0YXRlID0gJ25ldyc7XG5cbiAgICBjb25maWcgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGNvbmZpZyB8fCB7fSkpO1xuXG4gICAgdGhpcy51c2luZ0J1bmRsZSA9IGNvbmZpZy5idW5kbGVQb2xpY3kgPT09ICdtYXgtYnVuZGxlJztcbiAgICBpZiAoY29uZmlnLnJ0Y3BNdXhQb2xpY3kgPT09ICduZWdvdGlhdGUnKSB7XG4gICAgICB0aHJvdyhtYWtlRXJyb3IoJ05vdFN1cHBvcnRlZEVycm9yJyxcbiAgICAgICAgICAncnRjcE11eFBvbGljeSBcXCduZWdvdGlhdGVcXCcgaXMgbm90IHN1cHBvcnRlZCcpKTtcbiAgICB9IGVsc2UgaWYgKCFjb25maWcucnRjcE11eFBvbGljeSkge1xuICAgICAgY29uZmlnLnJ0Y3BNdXhQb2xpY3kgPSAncmVxdWlyZSc7XG4gICAgfVxuXG4gICAgc3dpdGNoIChjb25maWcuaWNlVHJhbnNwb3J0UG9saWN5KSB7XG4gICAgICBjYXNlICdhbGwnOlxuICAgICAgY2FzZSAncmVsYXknOlxuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGNvbmZpZy5pY2VUcmFuc3BvcnRQb2xpY3kgPSAnYWxsJztcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgc3dpdGNoIChjb25maWcuYnVuZGxlUG9saWN5KSB7XG4gICAgICBjYXNlICdiYWxhbmNlZCc6XG4gICAgICBjYXNlICdtYXgtY29tcGF0JzpcbiAgICAgIGNhc2UgJ21heC1idW5kbGUnOlxuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGNvbmZpZy5idW5kbGVQb2xpY3kgPSAnYmFsYW5jZWQnO1xuICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICBjb25maWcuaWNlU2VydmVycyA9IGZpbHRlckljZVNlcnZlcnMoY29uZmlnLmljZVNlcnZlcnMgfHwgW10sIGVkZ2VWZXJzaW9uKTtcblxuICAgIHRoaXMuX2ljZUdhdGhlcmVycyA9IFtdO1xuICAgIGlmIChjb25maWcuaWNlQ2FuZGlkYXRlUG9vbFNpemUpIHtcbiAgICAgIGZvciAodmFyIGkgPSBjb25maWcuaWNlQ2FuZGlkYXRlUG9vbFNpemU7IGkgPiAwOyBpLS0pIHtcbiAgICAgICAgdGhpcy5faWNlR2F0aGVyZXJzLnB1c2gobmV3IHdpbmRvdy5SVENJY2VHYXRoZXJlcih7XG4gICAgICAgICAgaWNlU2VydmVyczogY29uZmlnLmljZVNlcnZlcnMsXG4gICAgICAgICAgZ2F0aGVyUG9saWN5OiBjb25maWcuaWNlVHJhbnNwb3J0UG9saWN5XG4gICAgICAgIH0pKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29uZmlnLmljZUNhbmRpZGF0ZVBvb2xTaXplID0gMDtcbiAgICB9XG5cbiAgICB0aGlzLl9jb25maWcgPSBjb25maWc7XG5cbiAgICAvLyBwZXItdHJhY2sgaWNlR2F0aGVycywgaWNlVHJhbnNwb3J0cywgZHRsc1RyYW5zcG9ydHMsIHJ0cFNlbmRlcnMsIC4uLlxuICAgIC8vIGV2ZXJ5dGhpbmcgdGhhdCBpcyBuZWVkZWQgdG8gZGVzY3JpYmUgYSBTRFAgbS1saW5lLlxuICAgIHRoaXMudHJhbnNjZWl2ZXJzID0gW107XG5cbiAgICB0aGlzLl9zZHBTZXNzaW9uSWQgPSBTRFBVdGlscy5nZW5lcmF0ZVNlc3Npb25JZCgpO1xuICAgIHRoaXMuX3NkcFNlc3Npb25WZXJzaW9uID0gMDtcblxuICAgIHRoaXMuX2R0bHNSb2xlID0gdW5kZWZpbmVkOyAvLyByb2xlIGZvciBhPXNldHVwIHRvIHVzZSBpbiBhbnN3ZXJzLlxuXG4gICAgdGhpcy5faXNDbG9zZWQgPSBmYWxzZTtcbiAgfTtcblxuICAvLyBzZXQgdXAgZXZlbnQgaGFuZGxlcnMgb24gcHJvdG90eXBlXG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5vbmljZWNhbmRpZGF0ZSA9IG51bGw7XG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5vbmFkZHN0cmVhbSA9IG51bGw7XG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5vbnRyYWNrID0gbnVsbDtcbiAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLm9ucmVtb3Zlc3RyZWFtID0gbnVsbDtcbiAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLm9uc2lnbmFsaW5nc3RhdGVjaGFuZ2UgPSBudWxsO1xuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUub25pY2Vjb25uZWN0aW9uc3RhdGVjaGFuZ2UgPSBudWxsO1xuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUub25jb25uZWN0aW9uc3RhdGVjaGFuZ2UgPSBudWxsO1xuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUub25pY2VnYXRoZXJpbmdzdGF0ZWNoYW5nZSA9IG51bGw7XG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5vbm5lZ290aWF0aW9ubmVlZGVkID0gbnVsbDtcbiAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLm9uZGF0YWNoYW5uZWwgPSBudWxsO1xuXG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5fZGlzcGF0Y2hFdmVudCA9IGZ1bmN0aW9uKG5hbWUsIGV2ZW50KSB7XG4gICAgaWYgKHRoaXMuX2lzQ2xvc2VkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgaWYgKHR5cGVvZiB0aGlzWydvbicgKyBuYW1lXSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgdGhpc1snb24nICsgbmFtZV0oZXZlbnQpO1xuICAgIH1cbiAgfTtcblxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuX2VtaXRHYXRoZXJpbmdTdGF0ZUNoYW5nZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBldmVudCA9IG5ldyBFdmVudCgnaWNlZ2F0aGVyaW5nc3RhdGVjaGFuZ2UnKTtcbiAgICB0aGlzLl9kaXNwYXRjaEV2ZW50KCdpY2VnYXRoZXJpbmdzdGF0ZWNoYW5nZScsIGV2ZW50KTtcbiAgfTtcblxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuZ2V0Q29uZmlndXJhdGlvbiA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLl9jb25maWc7XG4gIH07XG5cbiAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmdldExvY2FsU3RyZWFtcyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmxvY2FsU3RyZWFtcztcbiAgfTtcblxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuZ2V0UmVtb3RlU3RyZWFtcyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLnJlbW90ZVN0cmVhbXM7XG4gIH07XG5cbiAgLy8gaW50ZXJuYWwgaGVscGVyIHRvIGNyZWF0ZSBhIHRyYW5zY2VpdmVyIG9iamVjdC5cbiAgLy8gKHdoaWNoIGlzIG5vdCB5ZXQgdGhlIHNhbWUgYXMgdGhlIFdlYlJUQyAxLjAgdHJhbnNjZWl2ZXIpXG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5fY3JlYXRlVHJhbnNjZWl2ZXIgPSBmdW5jdGlvbihraW5kLCBkb05vdEFkZCkge1xuICAgIHZhciBoYXNCdW5kbGVUcmFuc3BvcnQgPSB0aGlzLnRyYW5zY2VpdmVycy5sZW5ndGggPiAwO1xuICAgIHZhciB0cmFuc2NlaXZlciA9IHtcbiAgICAgIHRyYWNrOiBudWxsLFxuICAgICAgaWNlR2F0aGVyZXI6IG51bGwsXG4gICAgICBpY2VUcmFuc3BvcnQ6IG51bGwsXG4gICAgICBkdGxzVHJhbnNwb3J0OiBudWxsLFxuICAgICAgbG9jYWxDYXBhYmlsaXRpZXM6IG51bGwsXG4gICAgICByZW1vdGVDYXBhYmlsaXRpZXM6IG51bGwsXG4gICAgICBydHBTZW5kZXI6IG51bGwsXG4gICAgICBydHBSZWNlaXZlcjogbnVsbCxcbiAgICAgIGtpbmQ6IGtpbmQsXG4gICAgICBtaWQ6IG51bGwsXG4gICAgICBzZW5kRW5jb2RpbmdQYXJhbWV0ZXJzOiBudWxsLFxuICAgICAgcmVjdkVuY29kaW5nUGFyYW1ldGVyczogbnVsbCxcbiAgICAgIHN0cmVhbTogbnVsbCxcbiAgICAgIGFzc29jaWF0ZWRSZW1vdGVNZWRpYVN0cmVhbXM6IFtdLFxuICAgICAgd2FudFJlY2VpdmU6IHRydWVcbiAgICB9O1xuICAgIGlmICh0aGlzLnVzaW5nQnVuZGxlICYmIGhhc0J1bmRsZVRyYW5zcG9ydCkge1xuICAgICAgdHJhbnNjZWl2ZXIuaWNlVHJhbnNwb3J0ID0gdGhpcy50cmFuc2NlaXZlcnNbMF0uaWNlVHJhbnNwb3J0O1xuICAgICAgdHJhbnNjZWl2ZXIuZHRsc1RyYW5zcG9ydCA9IHRoaXMudHJhbnNjZWl2ZXJzWzBdLmR0bHNUcmFuc3BvcnQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciB0cmFuc3BvcnRzID0gdGhpcy5fY3JlYXRlSWNlQW5kRHRsc1RyYW5zcG9ydHMoKTtcbiAgICAgIHRyYW5zY2VpdmVyLmljZVRyYW5zcG9ydCA9IHRyYW5zcG9ydHMuaWNlVHJhbnNwb3J0O1xuICAgICAgdHJhbnNjZWl2ZXIuZHRsc1RyYW5zcG9ydCA9IHRyYW5zcG9ydHMuZHRsc1RyYW5zcG9ydDtcbiAgICB9XG4gICAgaWYgKCFkb05vdEFkZCkge1xuICAgICAgdGhpcy50cmFuc2NlaXZlcnMucHVzaCh0cmFuc2NlaXZlcik7XG4gICAgfVxuICAgIHJldHVybiB0cmFuc2NlaXZlcjtcbiAgfTtcblxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuYWRkVHJhY2sgPSBmdW5jdGlvbih0cmFjaywgc3RyZWFtKSB7XG4gICAgaWYgKHRoaXMuX2lzQ2xvc2VkKSB7XG4gICAgICB0aHJvdyBtYWtlRXJyb3IoJ0ludmFsaWRTdGF0ZUVycm9yJyxcbiAgICAgICAgICAnQXR0ZW1wdGVkIHRvIGNhbGwgYWRkVHJhY2sgb24gYSBjbG9zZWQgcGVlcmNvbm5lY3Rpb24uJyk7XG4gICAgfVxuXG4gICAgdmFyIGFscmVhZHlFeGlzdHMgPSB0aGlzLnRyYW5zY2VpdmVycy5maW5kKGZ1bmN0aW9uKHMpIHtcbiAgICAgIHJldHVybiBzLnRyYWNrID09PSB0cmFjaztcbiAgICB9KTtcblxuICAgIGlmIChhbHJlYWR5RXhpc3RzKSB7XG4gICAgICB0aHJvdyBtYWtlRXJyb3IoJ0ludmFsaWRBY2Nlc3NFcnJvcicsICdUcmFjayBhbHJlYWR5IGV4aXN0cy4nKTtcbiAgICB9XG5cbiAgICB2YXIgdHJhbnNjZWl2ZXI7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnRyYW5zY2VpdmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKCF0aGlzLnRyYW5zY2VpdmVyc1tpXS50cmFjayAmJlxuICAgICAgICAgIHRoaXMudHJhbnNjZWl2ZXJzW2ldLmtpbmQgPT09IHRyYWNrLmtpbmQpIHtcbiAgICAgICAgdHJhbnNjZWl2ZXIgPSB0aGlzLnRyYW5zY2VpdmVyc1tpXTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCF0cmFuc2NlaXZlcikge1xuICAgICAgdHJhbnNjZWl2ZXIgPSB0aGlzLl9jcmVhdGVUcmFuc2NlaXZlcih0cmFjay5raW5kKTtcbiAgICB9XG5cbiAgICB0aGlzLl9tYXliZUZpcmVOZWdvdGlhdGlvbk5lZWRlZCgpO1xuXG4gICAgaWYgKHRoaXMubG9jYWxTdHJlYW1zLmluZGV4T2Yoc3RyZWFtKSA9PT0gLTEpIHtcbiAgICAgIHRoaXMubG9jYWxTdHJlYW1zLnB1c2goc3RyZWFtKTtcbiAgICB9XG5cbiAgICB0cmFuc2NlaXZlci50cmFjayA9IHRyYWNrO1xuICAgIHRyYW5zY2VpdmVyLnN0cmVhbSA9IHN0cmVhbTtcbiAgICB0cmFuc2NlaXZlci5ydHBTZW5kZXIgPSBuZXcgd2luZG93LlJUQ1J0cFNlbmRlcih0cmFjayxcbiAgICAgICAgdHJhbnNjZWl2ZXIuZHRsc1RyYW5zcG9ydCk7XG4gICAgcmV0dXJuIHRyYW5zY2VpdmVyLnJ0cFNlbmRlcjtcbiAgfTtcblxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuYWRkU3RyZWFtID0gZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgdmFyIHBjID0gdGhpcztcbiAgICBpZiAoZWRnZVZlcnNpb24gPj0gMTUwMjUpIHtcbiAgICAgIHN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKGZ1bmN0aW9uKHRyYWNrKSB7XG4gICAgICAgIHBjLmFkZFRyYWNrKHRyYWNrLCBzdHJlYW0pO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIENsb25lIGlzIG5lY2Vzc2FyeSBmb3IgbG9jYWwgZGVtb3MgbW9zdGx5LCBhdHRhY2hpbmcgZGlyZWN0bHlcbiAgICAgIC8vIHRvIHR3byBkaWZmZXJlbnQgc2VuZGVycyBkb2VzIG5vdCB3b3JrIChidWlsZCAxMDU0NykuXG4gICAgICAvLyBGaXhlZCBpbiAxNTAyNSAob3IgZWFybGllcilcbiAgICAgIHZhciBjbG9uZWRTdHJlYW0gPSBzdHJlYW0uY2xvbmUoKTtcbiAgICAgIHN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKGZ1bmN0aW9uKHRyYWNrLCBpZHgpIHtcbiAgICAgICAgdmFyIGNsb25lZFRyYWNrID0gY2xvbmVkU3RyZWFtLmdldFRyYWNrcygpW2lkeF07XG4gICAgICAgIHRyYWNrLmFkZEV2ZW50TGlzdGVuZXIoJ2VuYWJsZWQnLCBmdW5jdGlvbihldmVudCkge1xuICAgICAgICAgIGNsb25lZFRyYWNrLmVuYWJsZWQgPSBldmVudC5lbmFibGVkO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgICAgY2xvbmVkU3RyZWFtLmdldFRyYWNrcygpLmZvckVhY2goZnVuY3Rpb24odHJhY2spIHtcbiAgICAgICAgcGMuYWRkVHJhY2sodHJhY2ssIGNsb25lZFN0cmVhbSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH07XG5cbiAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnJlbW92ZVRyYWNrID0gZnVuY3Rpb24oc2VuZGVyKSB7XG4gICAgaWYgKHRoaXMuX2lzQ2xvc2VkKSB7XG4gICAgICB0aHJvdyBtYWtlRXJyb3IoJ0ludmFsaWRTdGF0ZUVycm9yJyxcbiAgICAgICAgICAnQXR0ZW1wdGVkIHRvIGNhbGwgcmVtb3ZlVHJhY2sgb24gYSBjbG9zZWQgcGVlcmNvbm5lY3Rpb24uJyk7XG4gICAgfVxuXG4gICAgaWYgKCEoc2VuZGVyIGluc3RhbmNlb2Ygd2luZG93LlJUQ1J0cFNlbmRlcikpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50IDEgb2YgUlRDUGVlckNvbm5lY3Rpb24ucmVtb3ZlVHJhY2sgJyArXG4gICAgICAgICAgJ2RvZXMgbm90IGltcGxlbWVudCBpbnRlcmZhY2UgUlRDUnRwU2VuZGVyLicpO1xuICAgIH1cblxuICAgIHZhciB0cmFuc2NlaXZlciA9IHRoaXMudHJhbnNjZWl2ZXJzLmZpbmQoZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIHQucnRwU2VuZGVyID09PSBzZW5kZXI7XG4gICAgfSk7XG5cbiAgICBpZiAoIXRyYW5zY2VpdmVyKSB7XG4gICAgICB0aHJvdyBtYWtlRXJyb3IoJ0ludmFsaWRBY2Nlc3NFcnJvcicsXG4gICAgICAgICAgJ1NlbmRlciB3YXMgbm90IGNyZWF0ZWQgYnkgdGhpcyBjb25uZWN0aW9uLicpO1xuICAgIH1cbiAgICB2YXIgc3RyZWFtID0gdHJhbnNjZWl2ZXIuc3RyZWFtO1xuXG4gICAgdHJhbnNjZWl2ZXIucnRwU2VuZGVyLnN0b3AoKTtcbiAgICB0cmFuc2NlaXZlci5ydHBTZW5kZXIgPSBudWxsO1xuICAgIHRyYW5zY2VpdmVyLnRyYWNrID0gbnVsbDtcbiAgICB0cmFuc2NlaXZlci5zdHJlYW0gPSBudWxsO1xuXG4gICAgLy8gcmVtb3ZlIHRoZSBzdHJlYW0gZnJvbSB0aGUgc2V0IG9mIGxvY2FsIHN0cmVhbXNcbiAgICB2YXIgbG9jYWxTdHJlYW1zID0gdGhpcy50cmFuc2NlaXZlcnMubWFwKGZ1bmN0aW9uKHQpIHtcbiAgICAgIHJldHVybiB0LnN0cmVhbTtcbiAgICB9KTtcbiAgICBpZiAobG9jYWxTdHJlYW1zLmluZGV4T2Yoc3RyZWFtKSA9PT0gLTEgJiZcbiAgICAgICAgdGhpcy5sb2NhbFN0cmVhbXMuaW5kZXhPZihzdHJlYW0pID4gLTEpIHtcbiAgICAgIHRoaXMubG9jYWxTdHJlYW1zLnNwbGljZSh0aGlzLmxvY2FsU3RyZWFtcy5pbmRleE9mKHN0cmVhbSksIDEpO1xuICAgIH1cblxuICAgIHRoaXMuX21heWJlRmlyZU5lZ290aWF0aW9uTmVlZGVkKCk7XG4gIH07XG5cbiAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnJlbW92ZVN0cmVhbSA9IGZ1bmN0aW9uKHN0cmVhbSkge1xuICAgIHZhciBwYyA9IHRoaXM7XG4gICAgc3RyZWFtLmdldFRyYWNrcygpLmZvckVhY2goZnVuY3Rpb24odHJhY2spIHtcbiAgICAgIHZhciBzZW5kZXIgPSBwYy5nZXRTZW5kZXJzKCkuZmluZChmdW5jdGlvbihzKSB7XG4gICAgICAgIHJldHVybiBzLnRyYWNrID09PSB0cmFjaztcbiAgICAgIH0pO1xuICAgICAgaWYgKHNlbmRlcikge1xuICAgICAgICBwYy5yZW1vdmVUcmFjayhzZW5kZXIpO1xuICAgICAgfVxuICAgIH0pO1xuICB9O1xuXG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5nZXRTZW5kZXJzID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMudHJhbnNjZWl2ZXJzLmZpbHRlcihmdW5jdGlvbih0cmFuc2NlaXZlcikge1xuICAgICAgcmV0dXJuICEhdHJhbnNjZWl2ZXIucnRwU2VuZGVyO1xuICAgIH0pXG4gICAgLm1hcChmdW5jdGlvbih0cmFuc2NlaXZlcikge1xuICAgICAgcmV0dXJuIHRyYW5zY2VpdmVyLnJ0cFNlbmRlcjtcbiAgICB9KTtcbiAgfTtcblxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuZ2V0UmVjZWl2ZXJzID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMudHJhbnNjZWl2ZXJzLmZpbHRlcihmdW5jdGlvbih0cmFuc2NlaXZlcikge1xuICAgICAgcmV0dXJuICEhdHJhbnNjZWl2ZXIucnRwUmVjZWl2ZXI7XG4gICAgfSlcbiAgICAubWFwKGZ1bmN0aW9uKHRyYW5zY2VpdmVyKSB7XG4gICAgICByZXR1cm4gdHJhbnNjZWl2ZXIucnRwUmVjZWl2ZXI7XG4gICAgfSk7XG4gIH07XG5cblxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuX2NyZWF0ZUljZUdhdGhlcmVyID0gZnVuY3Rpb24oc2RwTUxpbmVJbmRleCxcbiAgICAgIHVzaW5nQnVuZGxlKSB7XG4gICAgdmFyIHBjID0gdGhpcztcbiAgICBpZiAodXNpbmdCdW5kbGUgJiYgc2RwTUxpbmVJbmRleCA+IDApIHtcbiAgICAgIHJldHVybiB0aGlzLnRyYW5zY2VpdmVyc1swXS5pY2VHYXRoZXJlcjtcbiAgICB9IGVsc2UgaWYgKHRoaXMuX2ljZUdhdGhlcmVycy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9pY2VHYXRoZXJlcnMuc2hpZnQoKTtcbiAgICB9XG4gICAgdmFyIGljZUdhdGhlcmVyID0gbmV3IHdpbmRvdy5SVENJY2VHYXRoZXJlcih7XG4gICAgICBpY2VTZXJ2ZXJzOiB0aGlzLl9jb25maWcuaWNlU2VydmVycyxcbiAgICAgIGdhdGhlclBvbGljeTogdGhpcy5fY29uZmlnLmljZVRyYW5zcG9ydFBvbGljeVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShpY2VHYXRoZXJlciwgJ3N0YXRlJyxcbiAgICAgICAge3ZhbHVlOiAnbmV3Jywgd3JpdGFibGU6IHRydWV9XG4gICAgKTtcblxuICAgIHRoaXMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLmJ1ZmZlcmVkQ2FuZGlkYXRlRXZlbnRzID0gW107XG4gICAgdGhpcy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF0uYnVmZmVyQ2FuZGlkYXRlcyA9IGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICB2YXIgZW5kID0gIWV2ZW50LmNhbmRpZGF0ZSB8fCBPYmplY3Qua2V5cyhldmVudC5jYW5kaWRhdGUpLmxlbmd0aCA9PT0gMDtcbiAgICAgIC8vIHBvbHlmaWxsIHNpbmNlIFJUQ0ljZUdhdGhlcmVyLnN0YXRlIGlzIG5vdCBpbXBsZW1lbnRlZCBpblxuICAgICAgLy8gRWRnZSAxMDU0NyB5ZXQuXG4gICAgICBpY2VHYXRoZXJlci5zdGF0ZSA9IGVuZCA/ICdjb21wbGV0ZWQnIDogJ2dhdGhlcmluZyc7XG4gICAgICBpZiAocGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLmJ1ZmZlcmVkQ2FuZGlkYXRlRXZlbnRzICE9PSBudWxsKSB7XG4gICAgICAgIHBjLnRyYW5zY2VpdmVyc1tzZHBNTGluZUluZGV4XS5idWZmZXJlZENhbmRpZGF0ZUV2ZW50cy5wdXNoKGV2ZW50KTtcbiAgICAgIH1cbiAgICB9O1xuICAgIGljZUdhdGhlcmVyLmFkZEV2ZW50TGlzdGVuZXIoJ2xvY2FsY2FuZGlkYXRlJyxcbiAgICAgIHRoaXMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLmJ1ZmZlckNhbmRpZGF0ZXMpO1xuICAgIHJldHVybiBpY2VHYXRoZXJlcjtcbiAgfTtcblxuICAvLyBzdGFydCBnYXRoZXJpbmcgZnJvbSBhbiBSVENJY2VHYXRoZXJlci5cbiAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLl9nYXRoZXIgPSBmdW5jdGlvbihtaWQsIHNkcE1MaW5lSW5kZXgpIHtcbiAgICB2YXIgcGMgPSB0aGlzO1xuICAgIHZhciBpY2VHYXRoZXJlciA9IHRoaXMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLmljZUdhdGhlcmVyO1xuICAgIGlmIChpY2VHYXRoZXJlci5vbmxvY2FsY2FuZGlkYXRlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciBidWZmZXJlZENhbmRpZGF0ZUV2ZW50cyA9XG4gICAgICB0aGlzLnRyYW5zY2VpdmVyc1tzZHBNTGluZUluZGV4XS5idWZmZXJlZENhbmRpZGF0ZUV2ZW50cztcbiAgICB0aGlzLnRyYW5zY2VpdmVyc1tzZHBNTGluZUluZGV4XS5idWZmZXJlZENhbmRpZGF0ZUV2ZW50cyA9IG51bGw7XG4gICAgaWNlR2F0aGVyZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcignbG9jYWxjYW5kaWRhdGUnLFxuICAgICAgdGhpcy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF0uYnVmZmVyQ2FuZGlkYXRlcyk7XG4gICAgaWNlR2F0aGVyZXIub25sb2NhbGNhbmRpZGF0ZSA9IGZ1bmN0aW9uKGV2dCkge1xuICAgICAgaWYgKHBjLnVzaW5nQnVuZGxlICYmIHNkcE1MaW5lSW5kZXggPiAwKSB7XG4gICAgICAgIC8vIGlmIHdlIGtub3cgdGhhdCB3ZSB1c2UgYnVuZGxlIHdlIGNhbiBkcm9wIGNhbmRpZGF0ZXMgd2l0aFxuICAgICAgICAvLyDRlWRwTUxpbmVJbmRleCA+IDAuIElmIHdlIGRvbid0IGRvIHRoaXMgdGhlbiBvdXIgc3RhdGUgZ2V0c1xuICAgICAgICAvLyBjb25mdXNlZCBzaW5jZSB3ZSBkaXNwb3NlIHRoZSBleHRyYSBpY2UgZ2F0aGVyZXIuXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHZhciBldmVudCA9IG5ldyBFdmVudCgnaWNlY2FuZGlkYXRlJyk7XG4gICAgICBldmVudC5jYW5kaWRhdGUgPSB7c2RwTWlkOiBtaWQsIHNkcE1MaW5lSW5kZXg6IHNkcE1MaW5lSW5kZXh9O1xuXG4gICAgICB2YXIgY2FuZCA9IGV2dC5jYW5kaWRhdGU7XG4gICAgICAvLyBFZGdlIGVtaXRzIGFuIGVtcHR5IG9iamVjdCBmb3IgUlRDSWNlQ2FuZGlkYXRlQ29tcGxldGXigKVcbiAgICAgIHZhciBlbmQgPSAhY2FuZCB8fCBPYmplY3Qua2V5cyhjYW5kKS5sZW5ndGggPT09IDA7XG4gICAgICBpZiAoZW5kKSB7XG4gICAgICAgIC8vIHBvbHlmaWxsIHNpbmNlIFJUQ0ljZUdhdGhlcmVyLnN0YXRlIGlzIG5vdCBpbXBsZW1lbnRlZCBpblxuICAgICAgICAvLyBFZGdlIDEwNTQ3IHlldC5cbiAgICAgICAgaWYgKGljZUdhdGhlcmVyLnN0YXRlID09PSAnbmV3JyB8fCBpY2VHYXRoZXJlci5zdGF0ZSA9PT0gJ2dhdGhlcmluZycpIHtcbiAgICAgICAgICBpY2VHYXRoZXJlci5zdGF0ZSA9ICdjb21wbGV0ZWQnO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoaWNlR2F0aGVyZXIuc3RhdGUgPT09ICduZXcnKSB7XG4gICAgICAgICAgaWNlR2F0aGVyZXIuc3RhdGUgPSAnZ2F0aGVyaW5nJztcbiAgICAgICAgfVxuICAgICAgICAvLyBSVENJY2VDYW5kaWRhdGUgZG9lc24ndCBoYXZlIGEgY29tcG9uZW50LCBuZWVkcyB0byBiZSBhZGRlZFxuICAgICAgICBjYW5kLmNvbXBvbmVudCA9IDE7XG4gICAgICAgIHZhciBzZXJpYWxpemVkQ2FuZGlkYXRlID0gU0RQVXRpbHMud3JpdGVDYW5kaWRhdGUoY2FuZCk7XG4gICAgICAgIGV2ZW50LmNhbmRpZGF0ZSA9IE9iamVjdC5hc3NpZ24oZXZlbnQuY2FuZGlkYXRlLFxuICAgICAgICAgICAgU0RQVXRpbHMucGFyc2VDYW5kaWRhdGUoc2VyaWFsaXplZENhbmRpZGF0ZSkpO1xuICAgICAgICBldmVudC5jYW5kaWRhdGUuY2FuZGlkYXRlID0gc2VyaWFsaXplZENhbmRpZGF0ZTtcbiAgICAgIH1cblxuICAgICAgLy8gdXBkYXRlIGxvY2FsIGRlc2NyaXB0aW9uLlxuICAgICAgdmFyIHNlY3Rpb25zID0gU0RQVXRpbHMuZ2V0TWVkaWFTZWN0aW9ucyhwYy5sb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICBpZiAoIWVuZCkge1xuICAgICAgICBzZWN0aW9uc1tldmVudC5jYW5kaWRhdGUuc2RwTUxpbmVJbmRleF0gKz1cbiAgICAgICAgICAgICdhPScgKyBldmVudC5jYW5kaWRhdGUuY2FuZGlkYXRlICsgJ1xcclxcbic7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZWN0aW9uc1tldmVudC5jYW5kaWRhdGUuc2RwTUxpbmVJbmRleF0gKz1cbiAgICAgICAgICAgICdhPWVuZC1vZi1jYW5kaWRhdGVzXFxyXFxuJztcbiAgICAgIH1cbiAgICAgIHBjLmxvY2FsRGVzY3JpcHRpb24uc2RwID1cbiAgICAgICAgICBTRFBVdGlscy5nZXREZXNjcmlwdGlvbihwYy5sb2NhbERlc2NyaXB0aW9uLnNkcCkgK1xuICAgICAgICAgIHNlY3Rpb25zLmpvaW4oJycpO1xuICAgICAgdmFyIGNvbXBsZXRlID0gcGMudHJhbnNjZWl2ZXJzLmV2ZXJ5KGZ1bmN0aW9uKHRyYW5zY2VpdmVyKSB7XG4gICAgICAgIHJldHVybiB0cmFuc2NlaXZlci5pY2VHYXRoZXJlciAmJlxuICAgICAgICAgICAgdHJhbnNjZWl2ZXIuaWNlR2F0aGVyZXIuc3RhdGUgPT09ICdjb21wbGV0ZWQnO1xuICAgICAgfSk7XG5cbiAgICAgIGlmIChwYy5pY2VHYXRoZXJpbmdTdGF0ZSAhPT0gJ2dhdGhlcmluZycpIHtcbiAgICAgICAgcGMuaWNlR2F0aGVyaW5nU3RhdGUgPSAnZ2F0aGVyaW5nJztcbiAgICAgICAgcGMuX2VtaXRHYXRoZXJpbmdTdGF0ZUNoYW5nZSgpO1xuICAgICAgfVxuXG4gICAgICAvLyBFbWl0IGNhbmRpZGF0ZS4gQWxzbyBlbWl0IG51bGwgY2FuZGlkYXRlIHdoZW4gYWxsIGdhdGhlcmVycyBhcmVcbiAgICAgIC8vIGNvbXBsZXRlLlxuICAgICAgaWYgKCFlbmQpIHtcbiAgICAgICAgcGMuX2Rpc3BhdGNoRXZlbnQoJ2ljZWNhbmRpZGF0ZScsIGV2ZW50KTtcbiAgICAgIH1cbiAgICAgIGlmIChjb21wbGV0ZSkge1xuICAgICAgICBwYy5fZGlzcGF0Y2hFdmVudCgnaWNlY2FuZGlkYXRlJywgbmV3IEV2ZW50KCdpY2VjYW5kaWRhdGUnKSk7XG4gICAgICAgIHBjLmljZUdhdGhlcmluZ1N0YXRlID0gJ2NvbXBsZXRlJztcbiAgICAgICAgcGMuX2VtaXRHYXRoZXJpbmdTdGF0ZUNoYW5nZSgpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICAvLyBlbWl0IGFscmVhZHkgZ2F0aGVyZWQgY2FuZGlkYXRlcy5cbiAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgIGJ1ZmZlcmVkQ2FuZGlkYXRlRXZlbnRzLmZvckVhY2goZnVuY3Rpb24oZSkge1xuICAgICAgICBpY2VHYXRoZXJlci5vbmxvY2FsY2FuZGlkYXRlKGUpO1xuICAgICAgfSk7XG4gICAgfSwgMCk7XG4gIH07XG5cbiAgLy8gQ3JlYXRlIElDRSB0cmFuc3BvcnQgYW5kIERUTFMgdHJhbnNwb3J0LlxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuX2NyZWF0ZUljZUFuZER0bHNUcmFuc3BvcnRzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHBjID0gdGhpcztcbiAgICB2YXIgaWNlVHJhbnNwb3J0ID0gbmV3IHdpbmRvdy5SVENJY2VUcmFuc3BvcnQobnVsbCk7XG4gICAgaWNlVHJhbnNwb3J0Lm9uaWNlc3RhdGVjaGFuZ2UgPSBmdW5jdGlvbigpIHtcbiAgICAgIHBjLl91cGRhdGVJY2VDb25uZWN0aW9uU3RhdGUoKTtcbiAgICAgIHBjLl91cGRhdGVDb25uZWN0aW9uU3RhdGUoKTtcbiAgICB9O1xuXG4gICAgdmFyIGR0bHNUcmFuc3BvcnQgPSBuZXcgd2luZG93LlJUQ0R0bHNUcmFuc3BvcnQoaWNlVHJhbnNwb3J0KTtcbiAgICBkdGxzVHJhbnNwb3J0Lm9uZHRsc3N0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG4gICAgICBwYy5fdXBkYXRlQ29ubmVjdGlvblN0YXRlKCk7XG4gICAgfTtcbiAgICBkdGxzVHJhbnNwb3J0Lm9uZXJyb3IgPSBmdW5jdGlvbigpIHtcbiAgICAgIC8vIG9uZXJyb3IgZG9lcyBub3Qgc2V0IHN0YXRlIHRvIGZhaWxlZCBieSBpdHNlbGYuXG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZHRsc1RyYW5zcG9ydCwgJ3N0YXRlJyxcbiAgICAgICAgICB7dmFsdWU6ICdmYWlsZWQnLCB3cml0YWJsZTogdHJ1ZX0pO1xuICAgICAgcGMuX3VwZGF0ZUNvbm5lY3Rpb25TdGF0ZSgpO1xuICAgIH07XG5cbiAgICByZXR1cm4ge1xuICAgICAgaWNlVHJhbnNwb3J0OiBpY2VUcmFuc3BvcnQsXG4gICAgICBkdGxzVHJhbnNwb3J0OiBkdGxzVHJhbnNwb3J0XG4gICAgfTtcbiAgfTtcblxuICAvLyBEZXN0cm95IElDRSBnYXRoZXJlciwgSUNFIHRyYW5zcG9ydCBhbmQgRFRMUyB0cmFuc3BvcnQuXG4gIC8vIFdpdGhvdXQgdHJpZ2dlcmluZyB0aGUgY2FsbGJhY2tzLlxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuX2Rpc3Bvc2VJY2VBbmREdGxzVHJhbnNwb3J0cyA9IGZ1bmN0aW9uKFxuICAgICAgc2RwTUxpbmVJbmRleCkge1xuICAgIHZhciBpY2VHYXRoZXJlciA9IHRoaXMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLmljZUdhdGhlcmVyO1xuICAgIGlmIChpY2VHYXRoZXJlcikge1xuICAgICAgZGVsZXRlIGljZUdhdGhlcmVyLm9ubG9jYWxjYW5kaWRhdGU7XG4gICAgICBkZWxldGUgdGhpcy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF0uaWNlR2F0aGVyZXI7XG4gICAgfVxuICAgIHZhciBpY2VUcmFuc3BvcnQgPSB0aGlzLnRyYW5zY2VpdmVyc1tzZHBNTGluZUluZGV4XS5pY2VUcmFuc3BvcnQ7XG4gICAgaWYgKGljZVRyYW5zcG9ydCkge1xuICAgICAgZGVsZXRlIGljZVRyYW5zcG9ydC5vbmljZXN0YXRlY2hhbmdlO1xuICAgICAgZGVsZXRlIHRoaXMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLmljZVRyYW5zcG9ydDtcbiAgICB9XG4gICAgdmFyIGR0bHNUcmFuc3BvcnQgPSB0aGlzLnRyYW5zY2VpdmVyc1tzZHBNTGluZUluZGV4XS5kdGxzVHJhbnNwb3J0O1xuICAgIGlmIChkdGxzVHJhbnNwb3J0KSB7XG4gICAgICBkZWxldGUgZHRsc1RyYW5zcG9ydC5vbmR0bHNzdGF0ZWNoYW5nZTtcbiAgICAgIGRlbGV0ZSBkdGxzVHJhbnNwb3J0Lm9uZXJyb3I7XG4gICAgICBkZWxldGUgdGhpcy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF0uZHRsc1RyYW5zcG9ydDtcbiAgICB9XG4gIH07XG5cbiAgLy8gU3RhcnQgdGhlIFJUUCBTZW5kZXIgYW5kIFJlY2VpdmVyIGZvciBhIHRyYW5zY2VpdmVyLlxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuX3RyYW5zY2VpdmUgPSBmdW5jdGlvbih0cmFuc2NlaXZlcixcbiAgICAgIHNlbmQsIHJlY3YpIHtcbiAgICB2YXIgcGFyYW1zID0gZ2V0Q29tbW9uQ2FwYWJpbGl0aWVzKHRyYW5zY2VpdmVyLmxvY2FsQ2FwYWJpbGl0aWVzLFxuICAgICAgICB0cmFuc2NlaXZlci5yZW1vdGVDYXBhYmlsaXRpZXMpO1xuICAgIGlmIChzZW5kICYmIHRyYW5zY2VpdmVyLnJ0cFNlbmRlcikge1xuICAgICAgcGFyYW1zLmVuY29kaW5ncyA9IHRyYW5zY2VpdmVyLnNlbmRFbmNvZGluZ1BhcmFtZXRlcnM7XG4gICAgICBwYXJhbXMucnRjcCA9IHtcbiAgICAgICAgY25hbWU6IFNEUFV0aWxzLmxvY2FsQ05hbWUsXG4gICAgICAgIGNvbXBvdW5kOiB0cmFuc2NlaXZlci5ydGNwUGFyYW1ldGVycy5jb21wb3VuZFxuICAgICAgfTtcbiAgICAgIGlmICh0cmFuc2NlaXZlci5yZWN2RW5jb2RpbmdQYXJhbWV0ZXJzLmxlbmd0aCkge1xuICAgICAgICBwYXJhbXMucnRjcC5zc3JjID0gdHJhbnNjZWl2ZXIucmVjdkVuY29kaW5nUGFyYW1ldGVyc1swXS5zc3JjO1xuICAgICAgfVxuICAgICAgdHJhbnNjZWl2ZXIucnRwU2VuZGVyLnNlbmQocGFyYW1zKTtcbiAgICB9XG4gICAgaWYgKHJlY3YgJiYgdHJhbnNjZWl2ZXIucnRwUmVjZWl2ZXIgJiYgcGFyYW1zLmNvZGVjcy5sZW5ndGggPiAwKSB7XG4gICAgICAvLyByZW1vdmUgUlRYIGZpZWxkIGluIEVkZ2UgMTQ5NDJcbiAgICAgIGlmICh0cmFuc2NlaXZlci5raW5kID09PSAndmlkZW8nXG4gICAgICAgICAgJiYgdHJhbnNjZWl2ZXIucmVjdkVuY29kaW5nUGFyYW1ldGVyc1xuICAgICAgICAgICYmIGVkZ2VWZXJzaW9uIDwgMTUwMTkpIHtcbiAgICAgICAgdHJhbnNjZWl2ZXIucmVjdkVuY29kaW5nUGFyYW1ldGVycy5mb3JFYWNoKGZ1bmN0aW9uKHApIHtcbiAgICAgICAgICBkZWxldGUgcC5ydHg7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgaWYgKHRyYW5zY2VpdmVyLnJlY3ZFbmNvZGluZ1BhcmFtZXRlcnMubGVuZ3RoKSB7XG4gICAgICAgIHBhcmFtcy5lbmNvZGluZ3MgPSB0cmFuc2NlaXZlci5yZWN2RW5jb2RpbmdQYXJhbWV0ZXJzO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGFyYW1zLmVuY29kaW5ncyA9IFt7fV07XG4gICAgICB9XG4gICAgICBwYXJhbXMucnRjcCA9IHtcbiAgICAgICAgY29tcG91bmQ6IHRyYW5zY2VpdmVyLnJ0Y3BQYXJhbWV0ZXJzLmNvbXBvdW5kXG4gICAgICB9O1xuICAgICAgaWYgKHRyYW5zY2VpdmVyLnJ0Y3BQYXJhbWV0ZXJzLmNuYW1lKSB7XG4gICAgICAgIHBhcmFtcy5ydGNwLmNuYW1lID0gdHJhbnNjZWl2ZXIucnRjcFBhcmFtZXRlcnMuY25hbWU7XG4gICAgICB9XG4gICAgICBpZiAodHJhbnNjZWl2ZXIuc2VuZEVuY29kaW5nUGFyYW1ldGVycy5sZW5ndGgpIHtcbiAgICAgICAgcGFyYW1zLnJ0Y3Auc3NyYyA9IHRyYW5zY2VpdmVyLnNlbmRFbmNvZGluZ1BhcmFtZXRlcnNbMF0uc3NyYztcbiAgICAgIH1cbiAgICAgIHRyYW5zY2VpdmVyLnJ0cFJlY2VpdmVyLnJlY2VpdmUocGFyYW1zKTtcbiAgICB9XG4gIH07XG5cbiAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnNldExvY2FsRGVzY3JpcHRpb24gPSBmdW5jdGlvbihkZXNjcmlwdGlvbikge1xuICAgIHZhciBwYyA9IHRoaXM7XG5cbiAgICAvLyBOb3RlOiBwcmFuc3dlciBpcyBub3Qgc3VwcG9ydGVkLlxuICAgIGlmIChbJ29mZmVyJywgJ2Fuc3dlciddLmluZGV4T2YoZGVzY3JpcHRpb24udHlwZSkgPT09IC0xKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobWFrZUVycm9yKCdUeXBlRXJyb3InLFxuICAgICAgICAgICdVbnN1cHBvcnRlZCB0eXBlIFwiJyArIGRlc2NyaXB0aW9uLnR5cGUgKyAnXCInKSk7XG4gICAgfVxuXG4gICAgaWYgKCFpc0FjdGlvbkFsbG93ZWRJblNpZ25hbGluZ1N0YXRlKCdzZXRMb2NhbERlc2NyaXB0aW9uJyxcbiAgICAgICAgZGVzY3JpcHRpb24udHlwZSwgcGMuc2lnbmFsaW5nU3RhdGUpIHx8IHBjLl9pc0Nsb3NlZCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG1ha2VFcnJvcignSW52YWxpZFN0YXRlRXJyb3InLFxuICAgICAgICAgICdDYW4gbm90IHNldCBsb2NhbCAnICsgZGVzY3JpcHRpb24udHlwZSArXG4gICAgICAgICAgJyBpbiBzdGF0ZSAnICsgcGMuc2lnbmFsaW5nU3RhdGUpKTtcbiAgICB9XG5cbiAgICB2YXIgc2VjdGlvbnM7XG4gICAgdmFyIHNlc3Npb25wYXJ0O1xuICAgIGlmIChkZXNjcmlwdGlvbi50eXBlID09PSAnb2ZmZXInKSB7XG4gICAgICAvLyBWRVJZIGxpbWl0ZWQgc3VwcG9ydCBmb3IgU0RQIG11bmdpbmcuIExpbWl0ZWQgdG86XG4gICAgICAvLyAqIGNoYW5naW5nIHRoZSBvcmRlciBvZiBjb2RlY3NcbiAgICAgIHNlY3Rpb25zID0gU0RQVXRpbHMuc3BsaXRTZWN0aW9ucyhkZXNjcmlwdGlvbi5zZHApO1xuICAgICAgc2Vzc2lvbnBhcnQgPSBzZWN0aW9ucy5zaGlmdCgpO1xuICAgICAgc2VjdGlvbnMuZm9yRWFjaChmdW5jdGlvbihtZWRpYVNlY3Rpb24sIHNkcE1MaW5lSW5kZXgpIHtcbiAgICAgICAgdmFyIGNhcHMgPSBTRFBVdGlscy5wYXJzZVJ0cFBhcmFtZXRlcnMobWVkaWFTZWN0aW9uKTtcbiAgICAgICAgcGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLmxvY2FsQ2FwYWJpbGl0aWVzID0gY2FwcztcbiAgICAgIH0pO1xuXG4gICAgICBwYy50cmFuc2NlaXZlcnMuZm9yRWFjaChmdW5jdGlvbih0cmFuc2NlaXZlciwgc2RwTUxpbmVJbmRleCkge1xuICAgICAgICBwYy5fZ2F0aGVyKHRyYW5zY2VpdmVyLm1pZCwgc2RwTUxpbmVJbmRleCk7XG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKGRlc2NyaXB0aW9uLnR5cGUgPT09ICdhbnN3ZXInKSB7XG4gICAgICBzZWN0aW9ucyA9IFNEUFV0aWxzLnNwbGl0U2VjdGlvbnMocGMucmVtb3RlRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgIHNlc3Npb25wYXJ0ID0gc2VjdGlvbnMuc2hpZnQoKTtcbiAgICAgIHZhciBpc0ljZUxpdGUgPSBTRFBVdGlscy5tYXRjaFByZWZpeChzZXNzaW9ucGFydCxcbiAgICAgICAgICAnYT1pY2UtbGl0ZScpLmxlbmd0aCA+IDA7XG4gICAgICBzZWN0aW9ucy5mb3JFYWNoKGZ1bmN0aW9uKG1lZGlhU2VjdGlvbiwgc2RwTUxpbmVJbmRleCkge1xuICAgICAgICB2YXIgdHJhbnNjZWl2ZXIgPSBwYy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF07XG4gICAgICAgIHZhciBpY2VHYXRoZXJlciA9IHRyYW5zY2VpdmVyLmljZUdhdGhlcmVyO1xuICAgICAgICB2YXIgaWNlVHJhbnNwb3J0ID0gdHJhbnNjZWl2ZXIuaWNlVHJhbnNwb3J0O1xuICAgICAgICB2YXIgZHRsc1RyYW5zcG9ydCA9IHRyYW5zY2VpdmVyLmR0bHNUcmFuc3BvcnQ7XG4gICAgICAgIHZhciBsb2NhbENhcGFiaWxpdGllcyA9IHRyYW5zY2VpdmVyLmxvY2FsQ2FwYWJpbGl0aWVzO1xuICAgICAgICB2YXIgcmVtb3RlQ2FwYWJpbGl0aWVzID0gdHJhbnNjZWl2ZXIucmVtb3RlQ2FwYWJpbGl0aWVzO1xuXG4gICAgICAgIC8vIHRyZWF0IGJ1bmRsZS1vbmx5IGFzIG5vdC1yZWplY3RlZC5cbiAgICAgICAgdmFyIHJlamVjdGVkID0gU0RQVXRpbHMuaXNSZWplY3RlZChtZWRpYVNlY3Rpb24pICYmXG4gICAgICAgICAgICBTRFBVdGlscy5tYXRjaFByZWZpeChtZWRpYVNlY3Rpb24sICdhPWJ1bmRsZS1vbmx5JykubGVuZ3RoID09PSAwO1xuXG4gICAgICAgIGlmICghcmVqZWN0ZWQgJiYgIXRyYW5zY2VpdmVyLnJlamVjdGVkKSB7XG4gICAgICAgICAgdmFyIHJlbW90ZUljZVBhcmFtZXRlcnMgPSBTRFBVdGlscy5nZXRJY2VQYXJhbWV0ZXJzKFxuICAgICAgICAgICAgICBtZWRpYVNlY3Rpb24sIHNlc3Npb25wYXJ0KTtcbiAgICAgICAgICB2YXIgcmVtb3RlRHRsc1BhcmFtZXRlcnMgPSBTRFBVdGlscy5nZXREdGxzUGFyYW1ldGVycyhcbiAgICAgICAgICAgICAgbWVkaWFTZWN0aW9uLCBzZXNzaW9ucGFydCk7XG4gICAgICAgICAgaWYgKGlzSWNlTGl0ZSkge1xuICAgICAgICAgICAgcmVtb3RlRHRsc1BhcmFtZXRlcnMucm9sZSA9ICdzZXJ2ZXInO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghcGMudXNpbmdCdW5kbGUgfHwgc2RwTUxpbmVJbmRleCA9PT0gMCkge1xuICAgICAgICAgICAgcGMuX2dhdGhlcih0cmFuc2NlaXZlci5taWQsIHNkcE1MaW5lSW5kZXgpO1xuICAgICAgICAgICAgaWYgKGljZVRyYW5zcG9ydC5zdGF0ZSA9PT0gJ25ldycpIHtcbiAgICAgICAgICAgICAgaWNlVHJhbnNwb3J0LnN0YXJ0KGljZUdhdGhlcmVyLCByZW1vdGVJY2VQYXJhbWV0ZXJzLFxuICAgICAgICAgICAgICAgICAgaXNJY2VMaXRlID8gJ2NvbnRyb2xsaW5nJyA6ICdjb250cm9sbGVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZHRsc1RyYW5zcG9ydC5zdGF0ZSA9PT0gJ25ldycpIHtcbiAgICAgICAgICAgICAgZHRsc1RyYW5zcG9ydC5zdGFydChyZW1vdGVEdGxzUGFyYW1ldGVycyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gQ2FsY3VsYXRlIGludGVyc2VjdGlvbiBvZiBjYXBhYmlsaXRpZXMuXG4gICAgICAgICAgdmFyIHBhcmFtcyA9IGdldENvbW1vbkNhcGFiaWxpdGllcyhsb2NhbENhcGFiaWxpdGllcyxcbiAgICAgICAgICAgICAgcmVtb3RlQ2FwYWJpbGl0aWVzKTtcblxuICAgICAgICAgIC8vIFN0YXJ0IHRoZSBSVENSdHBTZW5kZXIuIFRoZSBSVENSdHBSZWNlaXZlciBmb3IgdGhpc1xuICAgICAgICAgIC8vIHRyYW5zY2VpdmVyIGhhcyBhbHJlYWR5IGJlZW4gc3RhcnRlZCBpbiBzZXRSZW1vdGVEZXNjcmlwdGlvbi5cbiAgICAgICAgICBwYy5fdHJhbnNjZWl2ZSh0cmFuc2NlaXZlcixcbiAgICAgICAgICAgICAgcGFyYW1zLmNvZGVjcy5sZW5ndGggPiAwLFxuICAgICAgICAgICAgICBmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHBjLmxvY2FsRGVzY3JpcHRpb24gPSB7XG4gICAgICB0eXBlOiBkZXNjcmlwdGlvbi50eXBlLFxuICAgICAgc2RwOiBkZXNjcmlwdGlvbi5zZHBcbiAgICB9O1xuICAgIGlmIChkZXNjcmlwdGlvbi50eXBlID09PSAnb2ZmZXInKSB7XG4gICAgICBwYy5fdXBkYXRlU2lnbmFsaW5nU3RhdGUoJ2hhdmUtbG9jYWwtb2ZmZXInKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcGMuX3VwZGF0ZVNpZ25hbGluZ1N0YXRlKCdzdGFibGUnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH07XG5cbiAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnNldFJlbW90ZURlc2NyaXB0aW9uID0gZnVuY3Rpb24oZGVzY3JpcHRpb24pIHtcbiAgICB2YXIgcGMgPSB0aGlzO1xuXG4gICAgLy8gTm90ZTogcHJhbnN3ZXIgaXMgbm90IHN1cHBvcnRlZC5cbiAgICBpZiAoWydvZmZlcicsICdhbnN3ZXInXS5pbmRleE9mKGRlc2NyaXB0aW9uLnR5cGUpID09PSAtMSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG1ha2VFcnJvcignVHlwZUVycm9yJyxcbiAgICAgICAgICAnVW5zdXBwb3J0ZWQgdHlwZSBcIicgKyBkZXNjcmlwdGlvbi50eXBlICsgJ1wiJykpO1xuICAgIH1cblxuICAgIGlmICghaXNBY3Rpb25BbGxvd2VkSW5TaWduYWxpbmdTdGF0ZSgnc2V0UmVtb3RlRGVzY3JpcHRpb24nLFxuICAgICAgICBkZXNjcmlwdGlvbi50eXBlLCBwYy5zaWduYWxpbmdTdGF0ZSkgfHwgcGMuX2lzQ2xvc2VkKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobWFrZUVycm9yKCdJbnZhbGlkU3RhdGVFcnJvcicsXG4gICAgICAgICAgJ0NhbiBub3Qgc2V0IHJlbW90ZSAnICsgZGVzY3JpcHRpb24udHlwZSArXG4gICAgICAgICAgJyBpbiBzdGF0ZSAnICsgcGMuc2lnbmFsaW5nU3RhdGUpKTtcbiAgICB9XG5cbiAgICB2YXIgc3RyZWFtcyA9IHt9O1xuICAgIHBjLnJlbW90ZVN0cmVhbXMuZm9yRWFjaChmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgIHN0cmVhbXNbc3RyZWFtLmlkXSA9IHN0cmVhbTtcbiAgICB9KTtcbiAgICB2YXIgcmVjZWl2ZXJMaXN0ID0gW107XG4gICAgdmFyIHNlY3Rpb25zID0gU0RQVXRpbHMuc3BsaXRTZWN0aW9ucyhkZXNjcmlwdGlvbi5zZHApO1xuICAgIHZhciBzZXNzaW9ucGFydCA9IHNlY3Rpb25zLnNoaWZ0KCk7XG4gICAgdmFyIGlzSWNlTGl0ZSA9IFNEUFV0aWxzLm1hdGNoUHJlZml4KHNlc3Npb25wYXJ0LFxuICAgICAgICAnYT1pY2UtbGl0ZScpLmxlbmd0aCA+IDA7XG4gICAgdmFyIHVzaW5nQnVuZGxlID0gU0RQVXRpbHMubWF0Y2hQcmVmaXgoc2Vzc2lvbnBhcnQsXG4gICAgICAgICdhPWdyb3VwOkJVTkRMRSAnKS5sZW5ndGggPiAwO1xuICAgIHBjLnVzaW5nQnVuZGxlID0gdXNpbmdCdW5kbGU7XG4gICAgdmFyIGljZU9wdGlvbnMgPSBTRFBVdGlscy5tYXRjaFByZWZpeChzZXNzaW9ucGFydCxcbiAgICAgICAgJ2E9aWNlLW9wdGlvbnM6JylbMF07XG4gICAgaWYgKGljZU9wdGlvbnMpIHtcbiAgICAgIHBjLmNhblRyaWNrbGVJY2VDYW5kaWRhdGVzID0gaWNlT3B0aW9ucy5zdWJzdHIoMTQpLnNwbGl0KCcgJylcbiAgICAgICAgICAuaW5kZXhPZigndHJpY2tsZScpID49IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIHBjLmNhblRyaWNrbGVJY2VDYW5kaWRhdGVzID0gZmFsc2U7XG4gICAgfVxuXG4gICAgc2VjdGlvbnMuZm9yRWFjaChmdW5jdGlvbihtZWRpYVNlY3Rpb24sIHNkcE1MaW5lSW5kZXgpIHtcbiAgICAgIHZhciBsaW5lcyA9IFNEUFV0aWxzLnNwbGl0TGluZXMobWVkaWFTZWN0aW9uKTtcbiAgICAgIHZhciBraW5kID0gU0RQVXRpbHMuZ2V0S2luZChtZWRpYVNlY3Rpb24pO1xuICAgICAgLy8gdHJlYXQgYnVuZGxlLW9ubHkgYXMgbm90LXJlamVjdGVkLlxuICAgICAgdmFyIHJlamVjdGVkID0gU0RQVXRpbHMuaXNSZWplY3RlZChtZWRpYVNlY3Rpb24pICYmXG4gICAgICAgICAgU0RQVXRpbHMubWF0Y2hQcmVmaXgobWVkaWFTZWN0aW9uLCAnYT1idW5kbGUtb25seScpLmxlbmd0aCA9PT0gMDtcbiAgICAgIHZhciBwcm90b2NvbCA9IGxpbmVzWzBdLnN1YnN0cigyKS5zcGxpdCgnICcpWzJdO1xuXG4gICAgICB2YXIgZGlyZWN0aW9uID0gU0RQVXRpbHMuZ2V0RGlyZWN0aW9uKG1lZGlhU2VjdGlvbiwgc2Vzc2lvbnBhcnQpO1xuICAgICAgdmFyIHJlbW90ZU1zaWQgPSBTRFBVdGlscy5wYXJzZU1zaWQobWVkaWFTZWN0aW9uKTtcblxuICAgICAgdmFyIG1pZCA9IFNEUFV0aWxzLmdldE1pZChtZWRpYVNlY3Rpb24pIHx8IFNEUFV0aWxzLmdlbmVyYXRlSWRlbnRpZmllcigpO1xuXG4gICAgICAvLyBSZWplY3QgZGF0YWNoYW5uZWxzIHdoaWNoIGFyZSBub3QgaW1wbGVtZW50ZWQgeWV0LlxuICAgICAgaWYgKChraW5kID09PSAnYXBwbGljYXRpb24nICYmIHByb3RvY29sID09PSAnRFRMUy9TQ1RQJykgfHwgcmVqZWN0ZWQpIHtcbiAgICAgICAgLy8gVE9ETzogdGhpcyBpcyBkYW5nZXJvdXMgaW4gdGhlIGNhc2Ugd2hlcmUgYSBub24tcmVqZWN0ZWQgbS1saW5lXG4gICAgICAgIC8vICAgICBiZWNvbWVzIHJlamVjdGVkLlxuICAgICAgICBwYy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF0gPSB7XG4gICAgICAgICAgbWlkOiBtaWQsXG4gICAgICAgICAga2luZDoga2luZCxcbiAgICAgICAgICByZWplY3RlZDogdHJ1ZVxuICAgICAgICB9O1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmICghcmVqZWN0ZWQgJiYgcGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdICYmXG4gICAgICAgICAgcGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLnJlamVjdGVkKSB7XG4gICAgICAgIC8vIHJlY3ljbGUgYSByZWplY3RlZCB0cmFuc2NlaXZlci5cbiAgICAgICAgcGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdID0gcGMuX2NyZWF0ZVRyYW5zY2VpdmVyKGtpbmQsIHRydWUpO1xuICAgICAgfVxuXG4gICAgICB2YXIgdHJhbnNjZWl2ZXI7XG4gICAgICB2YXIgaWNlR2F0aGVyZXI7XG4gICAgICB2YXIgaWNlVHJhbnNwb3J0O1xuICAgICAgdmFyIGR0bHNUcmFuc3BvcnQ7XG4gICAgICB2YXIgcnRwUmVjZWl2ZXI7XG4gICAgICB2YXIgc2VuZEVuY29kaW5nUGFyYW1ldGVycztcbiAgICAgIHZhciByZWN2RW5jb2RpbmdQYXJhbWV0ZXJzO1xuICAgICAgdmFyIGxvY2FsQ2FwYWJpbGl0aWVzO1xuXG4gICAgICB2YXIgdHJhY2s7XG4gICAgICAvLyBGSVhNRTogZW5zdXJlIHRoZSBtZWRpYVNlY3Rpb24gaGFzIHJ0Y3AtbXV4IHNldC5cbiAgICAgIHZhciByZW1vdGVDYXBhYmlsaXRpZXMgPSBTRFBVdGlscy5wYXJzZVJ0cFBhcmFtZXRlcnMobWVkaWFTZWN0aW9uKTtcbiAgICAgIHZhciByZW1vdGVJY2VQYXJhbWV0ZXJzO1xuICAgICAgdmFyIHJlbW90ZUR0bHNQYXJhbWV0ZXJzO1xuICAgICAgaWYgKCFyZWplY3RlZCkge1xuICAgICAgICByZW1vdGVJY2VQYXJhbWV0ZXJzID0gU0RQVXRpbHMuZ2V0SWNlUGFyYW1ldGVycyhtZWRpYVNlY3Rpb24sXG4gICAgICAgICAgICBzZXNzaW9ucGFydCk7XG4gICAgICAgIHJlbW90ZUR0bHNQYXJhbWV0ZXJzID0gU0RQVXRpbHMuZ2V0RHRsc1BhcmFtZXRlcnMobWVkaWFTZWN0aW9uLFxuICAgICAgICAgICAgc2Vzc2lvbnBhcnQpO1xuICAgICAgICByZW1vdGVEdGxzUGFyYW1ldGVycy5yb2xlID0gJ2NsaWVudCc7XG4gICAgICB9XG4gICAgICByZWN2RW5jb2RpbmdQYXJhbWV0ZXJzID1cbiAgICAgICAgICBTRFBVdGlscy5wYXJzZVJ0cEVuY29kaW5nUGFyYW1ldGVycyhtZWRpYVNlY3Rpb24pO1xuXG4gICAgICB2YXIgcnRjcFBhcmFtZXRlcnMgPSBTRFBVdGlscy5wYXJzZVJ0Y3BQYXJhbWV0ZXJzKG1lZGlhU2VjdGlvbik7XG5cbiAgICAgIHZhciBpc0NvbXBsZXRlID0gU0RQVXRpbHMubWF0Y2hQcmVmaXgobWVkaWFTZWN0aW9uLFxuICAgICAgICAgICdhPWVuZC1vZi1jYW5kaWRhdGVzJywgc2Vzc2lvbnBhcnQpLmxlbmd0aCA+IDA7XG4gICAgICB2YXIgY2FuZHMgPSBTRFBVdGlscy5tYXRjaFByZWZpeChtZWRpYVNlY3Rpb24sICdhPWNhbmRpZGF0ZTonKVxuICAgICAgICAgIC5tYXAoZnVuY3Rpb24oY2FuZCkge1xuICAgICAgICAgICAgcmV0dXJuIFNEUFV0aWxzLnBhcnNlQ2FuZGlkYXRlKGNhbmQpO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLmZpbHRlcihmdW5jdGlvbihjYW5kKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FuZC5jb21wb25lbnQgPT09IDE7XG4gICAgICAgICAgfSk7XG5cbiAgICAgIC8vIENoZWNrIGlmIHdlIGNhbiB1c2UgQlVORExFIGFuZCBkaXNwb3NlIHRyYW5zcG9ydHMuXG4gICAgICBpZiAoKGRlc2NyaXB0aW9uLnR5cGUgPT09ICdvZmZlcicgfHwgZGVzY3JpcHRpb24udHlwZSA9PT0gJ2Fuc3dlcicpICYmXG4gICAgICAgICAgIXJlamVjdGVkICYmIHVzaW5nQnVuZGxlICYmIHNkcE1MaW5lSW5kZXggPiAwICYmXG4gICAgICAgICAgcGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdKSB7XG4gICAgICAgIHBjLl9kaXNwb3NlSWNlQW5kRHRsc1RyYW5zcG9ydHMoc2RwTUxpbmVJbmRleCk7XG4gICAgICAgIHBjLnRyYW5zY2VpdmVyc1tzZHBNTGluZUluZGV4XS5pY2VHYXRoZXJlciA9XG4gICAgICAgICAgICBwYy50cmFuc2NlaXZlcnNbMF0uaWNlR2F0aGVyZXI7XG4gICAgICAgIHBjLnRyYW5zY2VpdmVyc1tzZHBNTGluZUluZGV4XS5pY2VUcmFuc3BvcnQgPVxuICAgICAgICAgICAgcGMudHJhbnNjZWl2ZXJzWzBdLmljZVRyYW5zcG9ydDtcbiAgICAgICAgcGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLmR0bHNUcmFuc3BvcnQgPVxuICAgICAgICAgICAgcGMudHJhbnNjZWl2ZXJzWzBdLmR0bHNUcmFuc3BvcnQ7XG4gICAgICAgIGlmIChwYy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF0ucnRwU2VuZGVyKSB7XG4gICAgICAgICAgcGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLnJ0cFNlbmRlci5zZXRUcmFuc3BvcnQoXG4gICAgICAgICAgICAgIHBjLnRyYW5zY2VpdmVyc1swXS5kdGxzVHJhbnNwb3J0KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLnJ0cFJlY2VpdmVyKSB7XG4gICAgICAgICAgcGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLnJ0cFJlY2VpdmVyLnNldFRyYW5zcG9ydChcbiAgICAgICAgICAgICAgcGMudHJhbnNjZWl2ZXJzWzBdLmR0bHNUcmFuc3BvcnQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoZGVzY3JpcHRpb24udHlwZSA9PT0gJ29mZmVyJyAmJiAhcmVqZWN0ZWQpIHtcbiAgICAgICAgdHJhbnNjZWl2ZXIgPSBwYy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF0gfHxcbiAgICAgICAgICAgIHBjLl9jcmVhdGVUcmFuc2NlaXZlcihraW5kKTtcbiAgICAgICAgdHJhbnNjZWl2ZXIubWlkID0gbWlkO1xuXG4gICAgICAgIGlmICghdHJhbnNjZWl2ZXIuaWNlR2F0aGVyZXIpIHtcbiAgICAgICAgICB0cmFuc2NlaXZlci5pY2VHYXRoZXJlciA9IHBjLl9jcmVhdGVJY2VHYXRoZXJlcihzZHBNTGluZUluZGV4LFxuICAgICAgICAgICAgICB1c2luZ0J1bmRsZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY2FuZHMubGVuZ3RoICYmIHRyYW5zY2VpdmVyLmljZVRyYW5zcG9ydC5zdGF0ZSA9PT0gJ25ldycpIHtcbiAgICAgICAgICBpZiAoaXNDb21wbGV0ZSAmJiAoIXVzaW5nQnVuZGxlIHx8IHNkcE1MaW5lSW5kZXggPT09IDApKSB7XG4gICAgICAgICAgICB0cmFuc2NlaXZlci5pY2VUcmFuc3BvcnQuc2V0UmVtb3RlQ2FuZGlkYXRlcyhjYW5kcyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNhbmRzLmZvckVhY2goZnVuY3Rpb24oY2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgIG1heWJlQWRkQ2FuZGlkYXRlKHRyYW5zY2VpdmVyLmljZVRyYW5zcG9ydCwgY2FuZGlkYXRlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxvY2FsQ2FwYWJpbGl0aWVzID0gd2luZG93LlJUQ1J0cFJlY2VpdmVyLmdldENhcGFiaWxpdGllcyhraW5kKTtcblxuICAgICAgICAvLyBmaWx0ZXIgUlRYIHVudGlsIGFkZGl0aW9uYWwgc3R1ZmYgbmVlZGVkIGZvciBSVFggaXMgaW1wbGVtZW50ZWRcbiAgICAgICAgLy8gaW4gYWRhcHRlci5qc1xuICAgICAgICBpZiAoZWRnZVZlcnNpb24gPCAxNTAxOSkge1xuICAgICAgICAgIGxvY2FsQ2FwYWJpbGl0aWVzLmNvZGVjcyA9IGxvY2FsQ2FwYWJpbGl0aWVzLmNvZGVjcy5maWx0ZXIoXG4gICAgICAgICAgICAgIGZ1bmN0aW9uKGNvZGVjKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvZGVjLm5hbWUgIT09ICdydHgnO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNlbmRFbmNvZGluZ1BhcmFtZXRlcnMgPSB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzIHx8IFt7XG4gICAgICAgICAgc3NyYzogKDIgKiBzZHBNTGluZUluZGV4ICsgMikgKiAxMDAxXG4gICAgICAgIH1dO1xuXG4gICAgICAgIC8vIFRPRE86IHJld3JpdGUgdG8gdXNlIGh0dHA6Ly93M2MuZ2l0aHViLmlvL3dlYnJ0Yy1wYy8jc2V0LWFzc29jaWF0ZWQtcmVtb3RlLXN0cmVhbXNcbiAgICAgICAgdmFyIGlzTmV3VHJhY2sgPSBmYWxzZTtcbiAgICAgICAgaWYgKGRpcmVjdGlvbiA9PT0gJ3NlbmRyZWN2JyB8fCBkaXJlY3Rpb24gPT09ICdzZW5kb25seScpIHtcbiAgICAgICAgICBpc05ld1RyYWNrID0gIXRyYW5zY2VpdmVyLnJ0cFJlY2VpdmVyO1xuICAgICAgICAgIHJ0cFJlY2VpdmVyID0gdHJhbnNjZWl2ZXIucnRwUmVjZWl2ZXIgfHxcbiAgICAgICAgICAgICAgbmV3IHdpbmRvdy5SVENSdHBSZWNlaXZlcih0cmFuc2NlaXZlci5kdGxzVHJhbnNwb3J0LCBraW5kKTtcblxuICAgICAgICAgIGlmIChpc05ld1RyYWNrKSB7XG4gICAgICAgICAgICB2YXIgc3RyZWFtO1xuICAgICAgICAgICAgdHJhY2sgPSBydHBSZWNlaXZlci50cmFjaztcbiAgICAgICAgICAgIC8vIEZJWE1FOiBkb2VzIG5vdCB3b3JrIHdpdGggUGxhbiBCLlxuICAgICAgICAgICAgaWYgKHJlbW90ZU1zaWQgJiYgcmVtb3RlTXNpZC5zdHJlYW0gPT09ICctJykge1xuICAgICAgICAgICAgICAvLyBuby1vcC4gYSBzdHJlYW0gaWQgb2YgJy0nIG1lYW5zOiBubyBhc3NvY2lhdGVkIHN0cmVhbS5cbiAgICAgICAgICAgIH0gZWxzZSBpZiAocmVtb3RlTXNpZCkge1xuICAgICAgICAgICAgICBpZiAoIXN0cmVhbXNbcmVtb3RlTXNpZC5zdHJlYW1dKSB7XG4gICAgICAgICAgICAgICAgc3RyZWFtc1tyZW1vdGVNc2lkLnN0cmVhbV0gPSBuZXcgd2luZG93Lk1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHN0cmVhbXNbcmVtb3RlTXNpZC5zdHJlYW1dLCAnaWQnLCB7XG4gICAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVtb3RlTXNpZC5zdHJlYW07XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRyYWNrLCAnaWQnLCB7XG4gICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiByZW1vdGVNc2lkLnRyYWNrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHN0cmVhbSA9IHN0cmVhbXNbcmVtb3RlTXNpZC5zdHJlYW1dO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaWYgKCFzdHJlYW1zLmRlZmF1bHQpIHtcbiAgICAgICAgICAgICAgICBzdHJlYW1zLmRlZmF1bHQgPSBuZXcgd2luZG93Lk1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgc3RyZWFtID0gc3RyZWFtcy5kZWZhdWx0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHN0cmVhbSkge1xuICAgICAgICAgICAgICBhZGRUcmFja1RvU3RyZWFtQW5kRmlyZUV2ZW50KHRyYWNrLCBzdHJlYW0pO1xuICAgICAgICAgICAgICB0cmFuc2NlaXZlci5hc3NvY2lhdGVkUmVtb3RlTWVkaWFTdHJlYW1zLnB1c2goc3RyZWFtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlY2VpdmVyTGlzdC5wdXNoKFt0cmFjaywgcnRwUmVjZWl2ZXIsIHN0cmVhbV0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0cmFuc2NlaXZlci5ydHBSZWNlaXZlciAmJiB0cmFuc2NlaXZlci5ydHBSZWNlaXZlci50cmFjaykge1xuICAgICAgICAgIHRyYW5zY2VpdmVyLmFzc29jaWF0ZWRSZW1vdGVNZWRpYVN0cmVhbXMuZm9yRWFjaChmdW5jdGlvbihzKSB7XG4gICAgICAgICAgICB2YXIgbmF0aXZlVHJhY2sgPSBzLmdldFRyYWNrcygpLmZpbmQoZnVuY3Rpb24odCkge1xuICAgICAgICAgICAgICByZXR1cm4gdC5pZCA9PT0gdHJhbnNjZWl2ZXIucnRwUmVjZWl2ZXIudHJhY2suaWQ7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChuYXRpdmVUcmFjaykge1xuICAgICAgICAgICAgICByZW1vdmVUcmFja0Zyb21TdHJlYW1BbmRGaXJlRXZlbnQobmF0aXZlVHJhY2ssIHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHRyYW5zY2VpdmVyLmFzc29jaWF0ZWRSZW1vdGVNZWRpYVN0cmVhbXMgPSBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyYW5zY2VpdmVyLmxvY2FsQ2FwYWJpbGl0aWVzID0gbG9jYWxDYXBhYmlsaXRpZXM7XG4gICAgICAgIHRyYW5zY2VpdmVyLnJlbW90ZUNhcGFiaWxpdGllcyA9IHJlbW90ZUNhcGFiaWxpdGllcztcbiAgICAgICAgdHJhbnNjZWl2ZXIucnRwUmVjZWl2ZXIgPSBydHBSZWNlaXZlcjtcbiAgICAgICAgdHJhbnNjZWl2ZXIucnRjcFBhcmFtZXRlcnMgPSBydGNwUGFyYW1ldGVycztcbiAgICAgICAgdHJhbnNjZWl2ZXIuc2VuZEVuY29kaW5nUGFyYW1ldGVycyA9IHNlbmRFbmNvZGluZ1BhcmFtZXRlcnM7XG4gICAgICAgIHRyYW5zY2VpdmVyLnJlY3ZFbmNvZGluZ1BhcmFtZXRlcnMgPSByZWN2RW5jb2RpbmdQYXJhbWV0ZXJzO1xuXG4gICAgICAgIC8vIFN0YXJ0IHRoZSBSVENSdHBSZWNlaXZlciBub3cuIFRoZSBSVFBTZW5kZXIgaXMgc3RhcnRlZCBpblxuICAgICAgICAvLyBzZXRMb2NhbERlc2NyaXB0aW9uLlxuICAgICAgICBwYy5fdHJhbnNjZWl2ZShwYy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF0sXG4gICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgIGlzTmV3VHJhY2spO1xuICAgICAgfSBlbHNlIGlmIChkZXNjcmlwdGlvbi50eXBlID09PSAnYW5zd2VyJyAmJiAhcmVqZWN0ZWQpIHtcbiAgICAgICAgdHJhbnNjZWl2ZXIgPSBwYy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF07XG4gICAgICAgIGljZUdhdGhlcmVyID0gdHJhbnNjZWl2ZXIuaWNlR2F0aGVyZXI7XG4gICAgICAgIGljZVRyYW5zcG9ydCA9IHRyYW5zY2VpdmVyLmljZVRyYW5zcG9ydDtcbiAgICAgICAgZHRsc1RyYW5zcG9ydCA9IHRyYW5zY2VpdmVyLmR0bHNUcmFuc3BvcnQ7XG4gICAgICAgIHJ0cFJlY2VpdmVyID0gdHJhbnNjZWl2ZXIucnRwUmVjZWl2ZXI7XG4gICAgICAgIHNlbmRFbmNvZGluZ1BhcmFtZXRlcnMgPSB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzO1xuICAgICAgICBsb2NhbENhcGFiaWxpdGllcyA9IHRyYW5zY2VpdmVyLmxvY2FsQ2FwYWJpbGl0aWVzO1xuXG4gICAgICAgIHBjLnRyYW5zY2VpdmVyc1tzZHBNTGluZUluZGV4XS5yZWN2RW5jb2RpbmdQYXJhbWV0ZXJzID1cbiAgICAgICAgICAgIHJlY3ZFbmNvZGluZ1BhcmFtZXRlcnM7XG4gICAgICAgIHBjLnRyYW5zY2VpdmVyc1tzZHBNTGluZUluZGV4XS5yZW1vdGVDYXBhYmlsaXRpZXMgPVxuICAgICAgICAgICAgcmVtb3RlQ2FwYWJpbGl0aWVzO1xuICAgICAgICBwYy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF0ucnRjcFBhcmFtZXRlcnMgPSBydGNwUGFyYW1ldGVycztcblxuICAgICAgICBpZiAoY2FuZHMubGVuZ3RoICYmIGljZVRyYW5zcG9ydC5zdGF0ZSA9PT0gJ25ldycpIHtcbiAgICAgICAgICBpZiAoKGlzSWNlTGl0ZSB8fCBpc0NvbXBsZXRlKSAmJlxuICAgICAgICAgICAgICAoIXVzaW5nQnVuZGxlIHx8IHNkcE1MaW5lSW5kZXggPT09IDApKSB7XG4gICAgICAgICAgICBpY2VUcmFuc3BvcnQuc2V0UmVtb3RlQ2FuZGlkYXRlcyhjYW5kcyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNhbmRzLmZvckVhY2goZnVuY3Rpb24oY2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgIG1heWJlQWRkQ2FuZGlkYXRlKHRyYW5zY2VpdmVyLmljZVRyYW5zcG9ydCwgY2FuZGlkYXRlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdXNpbmdCdW5kbGUgfHwgc2RwTUxpbmVJbmRleCA9PT0gMCkge1xuICAgICAgICAgIGlmIChpY2VUcmFuc3BvcnQuc3RhdGUgPT09ICduZXcnKSB7XG4gICAgICAgICAgICBpY2VUcmFuc3BvcnQuc3RhcnQoaWNlR2F0aGVyZXIsIHJlbW90ZUljZVBhcmFtZXRlcnMsXG4gICAgICAgICAgICAgICAgJ2NvbnRyb2xsaW5nJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChkdGxzVHJhbnNwb3J0LnN0YXRlID09PSAnbmV3Jykge1xuICAgICAgICAgICAgZHRsc1RyYW5zcG9ydC5zdGFydChyZW1vdGVEdGxzUGFyYW1ldGVycyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcGMuX3RyYW5zY2VpdmUodHJhbnNjZWl2ZXIsXG4gICAgICAgICAgICBkaXJlY3Rpb24gPT09ICdzZW5kcmVjdicgfHwgZGlyZWN0aW9uID09PSAncmVjdm9ubHknLFxuICAgICAgICAgICAgZGlyZWN0aW9uID09PSAnc2VuZHJlY3YnIHx8IGRpcmVjdGlvbiA9PT0gJ3NlbmRvbmx5Jyk7XG5cbiAgICAgICAgLy8gVE9ETzogcmV3cml0ZSB0byB1c2UgaHR0cDovL3czYy5naXRodWIuaW8vd2VicnRjLXBjLyNzZXQtYXNzb2NpYXRlZC1yZW1vdGUtc3RyZWFtc1xuICAgICAgICBpZiAocnRwUmVjZWl2ZXIgJiZcbiAgICAgICAgICAgIChkaXJlY3Rpb24gPT09ICdzZW5kcmVjdicgfHwgZGlyZWN0aW9uID09PSAnc2VuZG9ubHknKSkge1xuICAgICAgICAgIHRyYWNrID0gcnRwUmVjZWl2ZXIudHJhY2s7XG4gICAgICAgICAgaWYgKHJlbW90ZU1zaWQpIHtcbiAgICAgICAgICAgIGlmICghc3RyZWFtc1tyZW1vdGVNc2lkLnN0cmVhbV0pIHtcbiAgICAgICAgICAgICAgc3RyZWFtc1tyZW1vdGVNc2lkLnN0cmVhbV0gPSBuZXcgd2luZG93Lk1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhZGRUcmFja1RvU3RyZWFtQW5kRmlyZUV2ZW50KHRyYWNrLCBzdHJlYW1zW3JlbW90ZU1zaWQuc3RyZWFtXSk7XG4gICAgICAgICAgICByZWNlaXZlckxpc3QucHVzaChbdHJhY2ssIHJ0cFJlY2VpdmVyLCBzdHJlYW1zW3JlbW90ZU1zaWQuc3RyZWFtXV0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoIXN0cmVhbXMuZGVmYXVsdCkge1xuICAgICAgICAgICAgICBzdHJlYW1zLmRlZmF1bHQgPSBuZXcgd2luZG93Lk1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhZGRUcmFja1RvU3RyZWFtQW5kRmlyZUV2ZW50KHRyYWNrLCBzdHJlYW1zLmRlZmF1bHQpO1xuICAgICAgICAgICAgcmVjZWl2ZXJMaXN0LnB1c2goW3RyYWNrLCBydHBSZWNlaXZlciwgc3RyZWFtcy5kZWZhdWx0XSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIEZJWE1FOiBhY3R1YWxseSB0aGUgcmVjZWl2ZXIgc2hvdWxkIGJlIGNyZWF0ZWQgbGF0ZXIuXG4gICAgICAgICAgZGVsZXRlIHRyYW5zY2VpdmVyLnJ0cFJlY2VpdmVyO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpZiAocGMuX2R0bHNSb2xlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHBjLl9kdGxzUm9sZSA9IGRlc2NyaXB0aW9uLnR5cGUgPT09ICdvZmZlcicgPyAnYWN0aXZlJyA6ICdwYXNzaXZlJztcbiAgICB9XG5cbiAgICBwYy5yZW1vdGVEZXNjcmlwdGlvbiA9IHtcbiAgICAgIHR5cGU6IGRlc2NyaXB0aW9uLnR5cGUsXG4gICAgICBzZHA6IGRlc2NyaXB0aW9uLnNkcFxuICAgIH07XG4gICAgaWYgKGRlc2NyaXB0aW9uLnR5cGUgPT09ICdvZmZlcicpIHtcbiAgICAgIHBjLl91cGRhdGVTaWduYWxpbmdTdGF0ZSgnaGF2ZS1yZW1vdGUtb2ZmZXInKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcGMuX3VwZGF0ZVNpZ25hbGluZ1N0YXRlKCdzdGFibGUnKTtcbiAgICB9XG4gICAgT2JqZWN0LmtleXMoc3RyZWFtcykuZm9yRWFjaChmdW5jdGlvbihzaWQpIHtcbiAgICAgIHZhciBzdHJlYW0gPSBzdHJlYW1zW3NpZF07XG4gICAgICBpZiAoc3RyZWFtLmdldFRyYWNrcygpLmxlbmd0aCkge1xuICAgICAgICBpZiAocGMucmVtb3RlU3RyZWFtcy5pbmRleE9mKHN0cmVhbSkgPT09IC0xKSB7XG4gICAgICAgICAgcGMucmVtb3RlU3RyZWFtcy5wdXNoKHN0cmVhbSk7XG4gICAgICAgICAgdmFyIGV2ZW50ID0gbmV3IEV2ZW50KCdhZGRzdHJlYW0nKTtcbiAgICAgICAgICBldmVudC5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBwYy5fZGlzcGF0Y2hFdmVudCgnYWRkc3RyZWFtJywgZXZlbnQpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVjZWl2ZXJMaXN0LmZvckVhY2goZnVuY3Rpb24oaXRlbSkge1xuICAgICAgICAgIHZhciB0cmFjayA9IGl0ZW1bMF07XG4gICAgICAgICAgdmFyIHJlY2VpdmVyID0gaXRlbVsxXTtcbiAgICAgICAgICBpZiAoc3RyZWFtLmlkICE9PSBpdGVtWzJdLmlkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIGZpcmVBZGRUcmFjayhwYywgdHJhY2ssIHJlY2VpdmVyLCBbc3RyZWFtXSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJlY2VpdmVyTGlzdC5mb3JFYWNoKGZ1bmN0aW9uKGl0ZW0pIHtcbiAgICAgIGlmIChpdGVtWzJdKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGZpcmVBZGRUcmFjayhwYywgaXRlbVswXSwgaXRlbVsxXSwgW10pO1xuICAgIH0pO1xuXG4gICAgLy8gY2hlY2sgd2hldGhlciBhZGRJY2VDYW5kaWRhdGUoe30pIHdhcyBjYWxsZWQgd2l0aGluIGZvdXIgc2Vjb25kcyBhZnRlclxuICAgIC8vIHNldFJlbW90ZURlc2NyaXB0aW9uLlxuICAgIHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKCEocGMgJiYgcGMudHJhbnNjZWl2ZXJzKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBwYy50cmFuc2NlaXZlcnMuZm9yRWFjaChmdW5jdGlvbih0cmFuc2NlaXZlcikge1xuICAgICAgICBpZiAodHJhbnNjZWl2ZXIuaWNlVHJhbnNwb3J0ICYmXG4gICAgICAgICAgICB0cmFuc2NlaXZlci5pY2VUcmFuc3BvcnQuc3RhdGUgPT09ICduZXcnICYmXG4gICAgICAgICAgICB0cmFuc2NlaXZlci5pY2VUcmFuc3BvcnQuZ2V0UmVtb3RlQ2FuZGlkYXRlcygpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oJ1RpbWVvdXQgZm9yIGFkZFJlbW90ZUNhbmRpZGF0ZS4gQ29uc2lkZXIgc2VuZGluZyAnICtcbiAgICAgICAgICAgICAgJ2FuIGVuZC1vZi1jYW5kaWRhdGVzIG5vdGlmaWNhdGlvbicpO1xuICAgICAgICAgIHRyYW5zY2VpdmVyLmljZVRyYW5zcG9ydC5hZGRSZW1vdGVDYW5kaWRhdGUoe30pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9LCA0MDAwKTtcblxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfTtcblxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuY2xvc2UgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnRyYW5zY2VpdmVycy5mb3JFYWNoKGZ1bmN0aW9uKHRyYW5zY2VpdmVyKSB7XG4gICAgICAvKiBub3QgeWV0XG4gICAgICBpZiAodHJhbnNjZWl2ZXIuaWNlR2F0aGVyZXIpIHtcbiAgICAgICAgdHJhbnNjZWl2ZXIuaWNlR2F0aGVyZXIuY2xvc2UoKTtcbiAgICAgIH1cbiAgICAgICovXG4gICAgICBpZiAodHJhbnNjZWl2ZXIuaWNlVHJhbnNwb3J0KSB7XG4gICAgICAgIHRyYW5zY2VpdmVyLmljZVRyYW5zcG9ydC5zdG9wKCk7XG4gICAgICB9XG4gICAgICBpZiAodHJhbnNjZWl2ZXIuZHRsc1RyYW5zcG9ydCkge1xuICAgICAgICB0cmFuc2NlaXZlci5kdGxzVHJhbnNwb3J0LnN0b3AoKTtcbiAgICAgIH1cbiAgICAgIGlmICh0cmFuc2NlaXZlci5ydHBTZW5kZXIpIHtcbiAgICAgICAgdHJhbnNjZWl2ZXIucnRwU2VuZGVyLnN0b3AoKTtcbiAgICAgIH1cbiAgICAgIGlmICh0cmFuc2NlaXZlci5ydHBSZWNlaXZlcikge1xuICAgICAgICB0cmFuc2NlaXZlci5ydHBSZWNlaXZlci5zdG9wKCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgLy8gRklYTUU6IGNsZWFuIHVwIHRyYWNrcywgbG9jYWwgc3RyZWFtcywgcmVtb3RlIHN0cmVhbXMsIGV0Y1xuICAgIHRoaXMuX2lzQ2xvc2VkID0gdHJ1ZTtcbiAgICB0aGlzLl91cGRhdGVTaWduYWxpbmdTdGF0ZSgnY2xvc2VkJyk7XG4gIH07XG5cbiAgLy8gVXBkYXRlIHRoZSBzaWduYWxpbmcgc3RhdGUuXG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5fdXBkYXRlU2lnbmFsaW5nU3RhdGUgPSBmdW5jdGlvbihuZXdTdGF0ZSkge1xuICAgIHRoaXMuc2lnbmFsaW5nU3RhdGUgPSBuZXdTdGF0ZTtcbiAgICB2YXIgZXZlbnQgPSBuZXcgRXZlbnQoJ3NpZ25hbGluZ3N0YXRlY2hhbmdlJyk7XG4gICAgdGhpcy5fZGlzcGF0Y2hFdmVudCgnc2lnbmFsaW5nc3RhdGVjaGFuZ2UnLCBldmVudCk7XG4gIH07XG5cbiAgLy8gRGV0ZXJtaW5lIHdoZXRoZXIgdG8gZmlyZSB0aGUgbmVnb3RpYXRpb25uZWVkZWQgZXZlbnQuXG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5fbWF5YmVGaXJlTmVnb3RpYXRpb25OZWVkZWQgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgcGMgPSB0aGlzO1xuICAgIGlmICh0aGlzLnNpZ25hbGluZ1N0YXRlICE9PSAnc3RhYmxlJyB8fCB0aGlzLm5lZWROZWdvdGlhdGlvbiA9PT0gdHJ1ZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLm5lZWROZWdvdGlhdGlvbiA9IHRydWU7XG4gICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICBpZiAocGMubmVlZE5lZ290aWF0aW9uKSB7XG4gICAgICAgIHBjLm5lZWROZWdvdGlhdGlvbiA9IGZhbHNlO1xuICAgICAgICB2YXIgZXZlbnQgPSBuZXcgRXZlbnQoJ25lZ290aWF0aW9ubmVlZGVkJyk7XG4gICAgICAgIHBjLl9kaXNwYXRjaEV2ZW50KCduZWdvdGlhdGlvbm5lZWRlZCcsIGV2ZW50KTtcbiAgICAgIH1cbiAgICB9LCAwKTtcbiAgfTtcblxuICAvLyBVcGRhdGUgdGhlIGljZSBjb25uZWN0aW9uIHN0YXRlLlxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuX3VwZGF0ZUljZUNvbm5lY3Rpb25TdGF0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBuZXdTdGF0ZTtcbiAgICB2YXIgc3RhdGVzID0ge1xuICAgICAgJ25ldyc6IDAsXG4gICAgICBjbG9zZWQ6IDAsXG4gICAgICBjaGVja2luZzogMCxcbiAgICAgIGNvbm5lY3RlZDogMCxcbiAgICAgIGNvbXBsZXRlZDogMCxcbiAgICAgIGRpc2Nvbm5lY3RlZDogMCxcbiAgICAgIGZhaWxlZDogMFxuICAgIH07XG4gICAgdGhpcy50cmFuc2NlaXZlcnMuZm9yRWFjaChmdW5jdGlvbih0cmFuc2NlaXZlcikge1xuICAgICAgc3RhdGVzW3RyYW5zY2VpdmVyLmljZVRyYW5zcG9ydC5zdGF0ZV0rKztcbiAgICB9KTtcblxuICAgIG5ld1N0YXRlID0gJ25ldyc7XG4gICAgaWYgKHN0YXRlcy5mYWlsZWQgPiAwKSB7XG4gICAgICBuZXdTdGF0ZSA9ICdmYWlsZWQnO1xuICAgIH0gZWxzZSBpZiAoc3RhdGVzLmNoZWNraW5nID4gMCkge1xuICAgICAgbmV3U3RhdGUgPSAnY2hlY2tpbmcnO1xuICAgIH0gZWxzZSBpZiAoc3RhdGVzLmRpc2Nvbm5lY3RlZCA+IDApIHtcbiAgICAgIG5ld1N0YXRlID0gJ2Rpc2Nvbm5lY3RlZCc7XG4gICAgfSBlbHNlIGlmIChzdGF0ZXMubmV3ID4gMCkge1xuICAgICAgbmV3U3RhdGUgPSAnbmV3JztcbiAgICB9IGVsc2UgaWYgKHN0YXRlcy5jb25uZWN0ZWQgPiAwKSB7XG4gICAgICBuZXdTdGF0ZSA9ICdjb25uZWN0ZWQnO1xuICAgIH0gZWxzZSBpZiAoc3RhdGVzLmNvbXBsZXRlZCA+IDApIHtcbiAgICAgIG5ld1N0YXRlID0gJ2NvbXBsZXRlZCc7XG4gICAgfVxuXG4gICAgaWYgKG5ld1N0YXRlICE9PSB0aGlzLmljZUNvbm5lY3Rpb25TdGF0ZSkge1xuICAgICAgdGhpcy5pY2VDb25uZWN0aW9uU3RhdGUgPSBuZXdTdGF0ZTtcbiAgICAgIHZhciBldmVudCA9IG5ldyBFdmVudCgnaWNlY29ubmVjdGlvbnN0YXRlY2hhbmdlJyk7XG4gICAgICB0aGlzLl9kaXNwYXRjaEV2ZW50KCdpY2Vjb25uZWN0aW9uc3RhdGVjaGFuZ2UnLCBldmVudCk7XG4gICAgfVxuICB9O1xuXG4gIC8vIFVwZGF0ZSB0aGUgY29ubmVjdGlvbiBzdGF0ZS5cbiAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLl91cGRhdGVDb25uZWN0aW9uU3RhdGUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgbmV3U3RhdGU7XG4gICAgdmFyIHN0YXRlcyA9IHtcbiAgICAgICduZXcnOiAwLFxuICAgICAgY2xvc2VkOiAwLFxuICAgICAgY29ubmVjdGluZzogMCxcbiAgICAgIGNvbm5lY3RlZDogMCxcbiAgICAgIGNvbXBsZXRlZDogMCxcbiAgICAgIGRpc2Nvbm5lY3RlZDogMCxcbiAgICAgIGZhaWxlZDogMFxuICAgIH07XG4gICAgdGhpcy50cmFuc2NlaXZlcnMuZm9yRWFjaChmdW5jdGlvbih0cmFuc2NlaXZlcikge1xuICAgICAgc3RhdGVzW3RyYW5zY2VpdmVyLmljZVRyYW5zcG9ydC5zdGF0ZV0rKztcbiAgICAgIHN0YXRlc1t0cmFuc2NlaXZlci5kdGxzVHJhbnNwb3J0LnN0YXRlXSsrO1xuICAgIH0pO1xuICAgIC8vIElDRVRyYW5zcG9ydC5jb21wbGV0ZWQgYW5kIGNvbm5lY3RlZCBhcmUgdGhlIHNhbWUgZm9yIHRoaXMgcHVycG9zZS5cbiAgICBzdGF0ZXMuY29ubmVjdGVkICs9IHN0YXRlcy5jb21wbGV0ZWQ7XG5cbiAgICBuZXdTdGF0ZSA9ICduZXcnO1xuICAgIGlmIChzdGF0ZXMuZmFpbGVkID4gMCkge1xuICAgICAgbmV3U3RhdGUgPSAnZmFpbGVkJztcbiAgICB9IGVsc2UgaWYgKHN0YXRlcy5jb25uZWN0aW5nID4gMCkge1xuICAgICAgbmV3U3RhdGUgPSAnY29ubmVjdGluZyc7XG4gICAgfSBlbHNlIGlmIChzdGF0ZXMuZGlzY29ubmVjdGVkID4gMCkge1xuICAgICAgbmV3U3RhdGUgPSAnZGlzY29ubmVjdGVkJztcbiAgICB9IGVsc2UgaWYgKHN0YXRlcy5uZXcgPiAwKSB7XG4gICAgICBuZXdTdGF0ZSA9ICduZXcnO1xuICAgIH0gZWxzZSBpZiAoc3RhdGVzLmNvbm5lY3RlZCA+IDApIHtcbiAgICAgIG5ld1N0YXRlID0gJ2Nvbm5lY3RlZCc7XG4gICAgfVxuXG4gICAgaWYgKG5ld1N0YXRlICE9PSB0aGlzLmNvbm5lY3Rpb25TdGF0ZSkge1xuICAgICAgdGhpcy5jb25uZWN0aW9uU3RhdGUgPSBuZXdTdGF0ZTtcbiAgICAgIHZhciBldmVudCA9IG5ldyBFdmVudCgnY29ubmVjdGlvbnN0YXRlY2hhbmdlJyk7XG4gICAgICB0aGlzLl9kaXNwYXRjaEV2ZW50KCdjb25uZWN0aW9uc3RhdGVjaGFuZ2UnLCBldmVudCk7XG4gICAgfVxuICB9O1xuXG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5jcmVhdGVPZmZlciA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBwYyA9IHRoaXM7XG5cbiAgICBpZiAocGMuX2lzQ2xvc2VkKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobWFrZUVycm9yKCdJbnZhbGlkU3RhdGVFcnJvcicsXG4gICAgICAgICAgJ0NhbiBub3QgY2FsbCBjcmVhdGVPZmZlciBhZnRlciBjbG9zZScpKTtcbiAgICB9XG5cbiAgICB2YXIgbnVtQXVkaW9UcmFja3MgPSBwYy50cmFuc2NlaXZlcnMuZmlsdGVyKGZ1bmN0aW9uKHQpIHtcbiAgICAgIHJldHVybiB0LmtpbmQgPT09ICdhdWRpbyc7XG4gICAgfSkubGVuZ3RoO1xuICAgIHZhciBudW1WaWRlb1RyYWNrcyA9IHBjLnRyYW5zY2VpdmVycy5maWx0ZXIoZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIHQua2luZCA9PT0gJ3ZpZGVvJztcbiAgICB9KS5sZW5ndGg7XG5cbiAgICAvLyBEZXRlcm1pbmUgbnVtYmVyIG9mIGF1ZGlvIGFuZCB2aWRlbyB0cmFja3Mgd2UgbmVlZCB0byBzZW5kL3JlY3YuXG4gICAgdmFyIG9mZmVyT3B0aW9ucyA9IGFyZ3VtZW50c1swXTtcbiAgICBpZiAob2ZmZXJPcHRpb25zKSB7XG4gICAgICAvLyBSZWplY3QgQ2hyb21lIGxlZ2FjeSBjb25zdHJhaW50cy5cbiAgICAgIGlmIChvZmZlck9wdGlvbnMubWFuZGF0b3J5IHx8IG9mZmVyT3B0aW9ucy5vcHRpb25hbCkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgICAgJ0xlZ2FjeSBtYW5kYXRvcnkvb3B0aW9uYWwgY29uc3RyYWludHMgbm90IHN1cHBvcnRlZC4nKTtcbiAgICAgIH1cbiAgICAgIGlmIChvZmZlck9wdGlvbnMub2ZmZXJUb1JlY2VpdmVBdWRpbyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGlmIChvZmZlck9wdGlvbnMub2ZmZXJUb1JlY2VpdmVBdWRpbyA9PT0gdHJ1ZSkge1xuICAgICAgICAgIG51bUF1ZGlvVHJhY2tzID0gMTtcbiAgICAgICAgfSBlbHNlIGlmIChvZmZlck9wdGlvbnMub2ZmZXJUb1JlY2VpdmVBdWRpbyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICBudW1BdWRpb1RyYWNrcyA9IDA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbnVtQXVkaW9UcmFja3MgPSBvZmZlck9wdGlvbnMub2ZmZXJUb1JlY2VpdmVBdWRpbztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKG9mZmVyT3B0aW9ucy5vZmZlclRvUmVjZWl2ZVZpZGVvICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKG9mZmVyT3B0aW9ucy5vZmZlclRvUmVjZWl2ZVZpZGVvID09PSB0cnVlKSB7XG4gICAgICAgICAgbnVtVmlkZW9UcmFja3MgPSAxO1xuICAgICAgICB9IGVsc2UgaWYgKG9mZmVyT3B0aW9ucy5vZmZlclRvUmVjZWl2ZVZpZGVvID09PSBmYWxzZSkge1xuICAgICAgICAgIG51bVZpZGVvVHJhY2tzID0gMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBudW1WaWRlb1RyYWNrcyA9IG9mZmVyT3B0aW9ucy5vZmZlclRvUmVjZWl2ZVZpZGVvO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcGMudHJhbnNjZWl2ZXJzLmZvckVhY2goZnVuY3Rpb24odHJhbnNjZWl2ZXIpIHtcbiAgICAgIGlmICh0cmFuc2NlaXZlci5raW5kID09PSAnYXVkaW8nKSB7XG4gICAgICAgIG51bUF1ZGlvVHJhY2tzLS07XG4gICAgICAgIGlmIChudW1BdWRpb1RyYWNrcyA8IDApIHtcbiAgICAgICAgICB0cmFuc2NlaXZlci53YW50UmVjZWl2ZSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHRyYW5zY2VpdmVyLmtpbmQgPT09ICd2aWRlbycpIHtcbiAgICAgICAgbnVtVmlkZW9UcmFja3MtLTtcbiAgICAgICAgaWYgKG51bVZpZGVvVHJhY2tzIDwgMCkge1xuICAgICAgICAgIHRyYW5zY2VpdmVyLndhbnRSZWNlaXZlID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIENyZWF0ZSBNLWxpbmVzIGZvciByZWN2b25seSBzdHJlYW1zLlxuICAgIHdoaWxlIChudW1BdWRpb1RyYWNrcyA+IDAgfHwgbnVtVmlkZW9UcmFja3MgPiAwKSB7XG4gICAgICBpZiAobnVtQXVkaW9UcmFja3MgPiAwKSB7XG4gICAgICAgIHBjLl9jcmVhdGVUcmFuc2NlaXZlcignYXVkaW8nKTtcbiAgICAgICAgbnVtQXVkaW9UcmFja3MtLTtcbiAgICAgIH1cbiAgICAgIGlmIChudW1WaWRlb1RyYWNrcyA+IDApIHtcbiAgICAgICAgcGMuX2NyZWF0ZVRyYW5zY2VpdmVyKCd2aWRlbycpO1xuICAgICAgICBudW1WaWRlb1RyYWNrcy0tO1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBzZHAgPSBTRFBVdGlscy53cml0ZVNlc3Npb25Cb2lsZXJwbGF0ZShwYy5fc2RwU2Vzc2lvbklkLFxuICAgICAgICBwYy5fc2RwU2Vzc2lvblZlcnNpb24rKyk7XG4gICAgcGMudHJhbnNjZWl2ZXJzLmZvckVhY2goZnVuY3Rpb24odHJhbnNjZWl2ZXIsIHNkcE1MaW5lSW5kZXgpIHtcbiAgICAgIC8vIEZvciBlYWNoIHRyYWNrLCBjcmVhdGUgYW4gaWNlIGdhdGhlcmVyLCBpY2UgdHJhbnNwb3J0LFxuICAgICAgLy8gZHRscyB0cmFuc3BvcnQsIHBvdGVudGlhbGx5IHJ0cHNlbmRlciBhbmQgcnRwcmVjZWl2ZXIuXG4gICAgICB2YXIgdHJhY2sgPSB0cmFuc2NlaXZlci50cmFjaztcbiAgICAgIHZhciBraW5kID0gdHJhbnNjZWl2ZXIua2luZDtcbiAgICAgIHZhciBtaWQgPSB0cmFuc2NlaXZlci5taWQgfHwgU0RQVXRpbHMuZ2VuZXJhdGVJZGVudGlmaWVyKCk7XG4gICAgICB0cmFuc2NlaXZlci5taWQgPSBtaWQ7XG5cbiAgICAgIGlmICghdHJhbnNjZWl2ZXIuaWNlR2F0aGVyZXIpIHtcbiAgICAgICAgdHJhbnNjZWl2ZXIuaWNlR2F0aGVyZXIgPSBwYy5fY3JlYXRlSWNlR2F0aGVyZXIoc2RwTUxpbmVJbmRleCxcbiAgICAgICAgICAgIHBjLnVzaW5nQnVuZGxlKTtcbiAgICAgIH1cblxuICAgICAgdmFyIGxvY2FsQ2FwYWJpbGl0aWVzID0gd2luZG93LlJUQ1J0cFNlbmRlci5nZXRDYXBhYmlsaXRpZXMoa2luZCk7XG4gICAgICAvLyBmaWx0ZXIgUlRYIHVudGlsIGFkZGl0aW9uYWwgc3R1ZmYgbmVlZGVkIGZvciBSVFggaXMgaW1wbGVtZW50ZWRcbiAgICAgIC8vIGluIGFkYXB0ZXIuanNcbiAgICAgIGlmIChlZGdlVmVyc2lvbiA8IDE1MDE5KSB7XG4gICAgICAgIGxvY2FsQ2FwYWJpbGl0aWVzLmNvZGVjcyA9IGxvY2FsQ2FwYWJpbGl0aWVzLmNvZGVjcy5maWx0ZXIoXG4gICAgICAgICAgICBmdW5jdGlvbihjb2RlYykge1xuICAgICAgICAgICAgICByZXR1cm4gY29kZWMubmFtZSAhPT0gJ3J0eCc7XG4gICAgICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGxvY2FsQ2FwYWJpbGl0aWVzLmNvZGVjcy5mb3JFYWNoKGZ1bmN0aW9uKGNvZGVjKSB7XG4gICAgICAgIC8vIHdvcmsgYXJvdW5kIGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC93ZWJydGMvaXNzdWVzL2RldGFpbD9pZD02NTUyXG4gICAgICAgIC8vIGJ5IGFkZGluZyBsZXZlbC1hc3ltbWV0cnktYWxsb3dlZD0xXG4gICAgICAgIGlmIChjb2RlYy5uYW1lID09PSAnSDI2NCcgJiZcbiAgICAgICAgICAgIGNvZGVjLnBhcmFtZXRlcnNbJ2xldmVsLWFzeW1tZXRyeS1hbGxvd2VkJ10gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGNvZGVjLnBhcmFtZXRlcnNbJ2xldmVsLWFzeW1tZXRyeS1hbGxvd2VkJ10gPSAnMSc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBmb3Igc3Vic2VxdWVudCBvZmZlcnMsIHdlIG1pZ2h0IGhhdmUgdG8gcmUtdXNlIHRoZSBwYXlsb2FkXG4gICAgICAgIC8vIHR5cGUgb2YgdGhlIGxhc3Qgb2ZmZXIuXG4gICAgICAgIGlmICh0cmFuc2NlaXZlci5yZW1vdGVDYXBhYmlsaXRpZXMgJiZcbiAgICAgICAgICAgIHRyYW5zY2VpdmVyLnJlbW90ZUNhcGFiaWxpdGllcy5jb2RlY3MpIHtcbiAgICAgICAgICB0cmFuc2NlaXZlci5yZW1vdGVDYXBhYmlsaXRpZXMuY29kZWNzLmZvckVhY2goZnVuY3Rpb24ocmVtb3RlQ29kZWMpIHtcbiAgICAgICAgICAgIGlmIChjb2RlYy5uYW1lLnRvTG93ZXJDYXNlKCkgPT09IHJlbW90ZUNvZGVjLm5hbWUudG9Mb3dlckNhc2UoKSAmJlxuICAgICAgICAgICAgICAgIGNvZGVjLmNsb2NrUmF0ZSA9PT0gcmVtb3RlQ29kZWMuY2xvY2tSYXRlKSB7XG4gICAgICAgICAgICAgIGNvZGVjLnByZWZlcnJlZFBheWxvYWRUeXBlID0gcmVtb3RlQ29kZWMucGF5bG9hZFR5cGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgbG9jYWxDYXBhYmlsaXRpZXMuaGVhZGVyRXh0ZW5zaW9ucy5mb3JFYWNoKGZ1bmN0aW9uKGhkckV4dCkge1xuICAgICAgICB2YXIgcmVtb3RlRXh0ZW5zaW9ucyA9IHRyYW5zY2VpdmVyLnJlbW90ZUNhcGFiaWxpdGllcyAmJlxuICAgICAgICAgICAgdHJhbnNjZWl2ZXIucmVtb3RlQ2FwYWJpbGl0aWVzLmhlYWRlckV4dGVuc2lvbnMgfHwgW107XG4gICAgICAgIHJlbW90ZUV4dGVuc2lvbnMuZm9yRWFjaChmdW5jdGlvbihySGRyRXh0KSB7XG4gICAgICAgICAgaWYgKGhkckV4dC51cmkgPT09IHJIZHJFeHQudXJpKSB7XG4gICAgICAgICAgICBoZHJFeHQuaWQgPSBySGRyRXh0LmlkO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgLy8gZ2VuZXJhdGUgYW4gc3NyYyBub3csIHRvIGJlIHVzZWQgbGF0ZXIgaW4gcnRwU2VuZGVyLnNlbmRcbiAgICAgIHZhciBzZW5kRW5jb2RpbmdQYXJhbWV0ZXJzID0gdHJhbnNjZWl2ZXIuc2VuZEVuY29kaW5nUGFyYW1ldGVycyB8fCBbe1xuICAgICAgICBzc3JjOiAoMiAqIHNkcE1MaW5lSW5kZXggKyAxKSAqIDEwMDFcbiAgICAgIH1dO1xuICAgICAgaWYgKHRyYWNrKSB7XG4gICAgICAgIC8vIGFkZCBSVFhcbiAgICAgICAgaWYgKGVkZ2VWZXJzaW9uID49IDE1MDE5ICYmIGtpbmQgPT09ICd2aWRlbycgJiZcbiAgICAgICAgICAgICFzZW5kRW5jb2RpbmdQYXJhbWV0ZXJzWzBdLnJ0eCkge1xuICAgICAgICAgIHNlbmRFbmNvZGluZ1BhcmFtZXRlcnNbMF0ucnR4ID0ge1xuICAgICAgICAgICAgc3NyYzogc2VuZEVuY29kaW5nUGFyYW1ldGVyc1swXS5zc3JjICsgMVxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHRyYW5zY2VpdmVyLndhbnRSZWNlaXZlKSB7XG4gICAgICAgIHRyYW5zY2VpdmVyLnJ0cFJlY2VpdmVyID0gbmV3IHdpbmRvdy5SVENSdHBSZWNlaXZlcihcbiAgICAgICAgICAgIHRyYW5zY2VpdmVyLmR0bHNUcmFuc3BvcnQsIGtpbmQpO1xuICAgICAgfVxuXG4gICAgICB0cmFuc2NlaXZlci5sb2NhbENhcGFiaWxpdGllcyA9IGxvY2FsQ2FwYWJpbGl0aWVzO1xuICAgICAgdHJhbnNjZWl2ZXIuc2VuZEVuY29kaW5nUGFyYW1ldGVycyA9IHNlbmRFbmNvZGluZ1BhcmFtZXRlcnM7XG4gICAgfSk7XG5cbiAgICAvLyBhbHdheXMgb2ZmZXIgQlVORExFIGFuZCBkaXNwb3NlIG9uIHJldHVybiBpZiBub3Qgc3VwcG9ydGVkLlxuICAgIGlmIChwYy5fY29uZmlnLmJ1bmRsZVBvbGljeSAhPT0gJ21heC1jb21wYXQnKSB7XG4gICAgICBzZHAgKz0gJ2E9Z3JvdXA6QlVORExFICcgKyBwYy50cmFuc2NlaXZlcnMubWFwKGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgcmV0dXJuIHQubWlkO1xuICAgICAgfSkuam9pbignICcpICsgJ1xcclxcbic7XG4gICAgfVxuICAgIHNkcCArPSAnYT1pY2Utb3B0aW9uczp0cmlja2xlXFxyXFxuJztcblxuICAgIHBjLnRyYW5zY2VpdmVycy5mb3JFYWNoKGZ1bmN0aW9uKHRyYW5zY2VpdmVyLCBzZHBNTGluZUluZGV4KSB7XG4gICAgICBzZHAgKz0gd3JpdGVNZWRpYVNlY3Rpb24odHJhbnNjZWl2ZXIsIHRyYW5zY2VpdmVyLmxvY2FsQ2FwYWJpbGl0aWVzLFxuICAgICAgICAgICdvZmZlcicsIHRyYW5zY2VpdmVyLnN0cmVhbSwgcGMuX2R0bHNSb2xlKTtcbiAgICAgIHNkcCArPSAnYT1ydGNwLXJzaXplXFxyXFxuJztcblxuICAgICAgaWYgKHRyYW5zY2VpdmVyLmljZUdhdGhlcmVyICYmIHBjLmljZUdhdGhlcmluZ1N0YXRlICE9PSAnbmV3JyAmJlxuICAgICAgICAgIChzZHBNTGluZUluZGV4ID09PSAwIHx8ICFwYy51c2luZ0J1bmRsZSkpIHtcbiAgICAgICAgdHJhbnNjZWl2ZXIuaWNlR2F0aGVyZXIuZ2V0TG9jYWxDYW5kaWRhdGVzKCkuZm9yRWFjaChmdW5jdGlvbihjYW5kKSB7XG4gICAgICAgICAgY2FuZC5jb21wb25lbnQgPSAxO1xuICAgICAgICAgIHNkcCArPSAnYT0nICsgU0RQVXRpbHMud3JpdGVDYW5kaWRhdGUoY2FuZCkgKyAnXFxyXFxuJztcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHRyYW5zY2VpdmVyLmljZUdhdGhlcmVyLnN0YXRlID09PSAnY29tcGxldGVkJykge1xuICAgICAgICAgIHNkcCArPSAnYT1lbmQtb2YtY2FuZGlkYXRlc1xcclxcbic7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHZhciBkZXNjID0gbmV3IHdpbmRvdy5SVENTZXNzaW9uRGVzY3JpcHRpb24oe1xuICAgICAgdHlwZTogJ29mZmVyJyxcbiAgICAgIHNkcDogc2RwXG4gICAgfSk7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShkZXNjKTtcbiAgfTtcblxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuY3JlYXRlQW5zd2VyID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHBjID0gdGhpcztcblxuICAgIGlmIChwYy5faXNDbG9zZWQpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChtYWtlRXJyb3IoJ0ludmFsaWRTdGF0ZUVycm9yJyxcbiAgICAgICAgICAnQ2FuIG5vdCBjYWxsIGNyZWF0ZUFuc3dlciBhZnRlciBjbG9zZScpKTtcbiAgICB9XG5cbiAgICBpZiAoIShwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2hhdmUtcmVtb3RlLW9mZmVyJyB8fFxuICAgICAgICBwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2hhdmUtbG9jYWwtcHJhbnN3ZXInKSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG1ha2VFcnJvcignSW52YWxpZFN0YXRlRXJyb3InLFxuICAgICAgICAgICdDYW4gbm90IGNhbGwgY3JlYXRlQW5zd2VyIGluIHNpZ25hbGluZ1N0YXRlICcgKyBwYy5zaWduYWxpbmdTdGF0ZSkpO1xuICAgIH1cblxuICAgIHZhciBzZHAgPSBTRFBVdGlscy53cml0ZVNlc3Npb25Cb2lsZXJwbGF0ZShwYy5fc2RwU2Vzc2lvbklkLFxuICAgICAgICBwYy5fc2RwU2Vzc2lvblZlcnNpb24rKyk7XG4gICAgaWYgKHBjLnVzaW5nQnVuZGxlKSB7XG4gICAgICBzZHAgKz0gJ2E9Z3JvdXA6QlVORExFICcgKyBwYy50cmFuc2NlaXZlcnMubWFwKGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgcmV0dXJuIHQubWlkO1xuICAgICAgfSkuam9pbignICcpICsgJ1xcclxcbic7XG4gICAgfVxuICAgIHZhciBtZWRpYVNlY3Rpb25zSW5PZmZlciA9IFNEUFV0aWxzLmdldE1lZGlhU2VjdGlvbnMoXG4gICAgICAgIHBjLnJlbW90ZURlc2NyaXB0aW9uLnNkcCkubGVuZ3RoO1xuICAgIHBjLnRyYW5zY2VpdmVycy5mb3JFYWNoKGZ1bmN0aW9uKHRyYW5zY2VpdmVyLCBzZHBNTGluZUluZGV4KSB7XG4gICAgICBpZiAoc2RwTUxpbmVJbmRleCArIDEgPiBtZWRpYVNlY3Rpb25zSW5PZmZlcikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAodHJhbnNjZWl2ZXIucmVqZWN0ZWQpIHtcbiAgICAgICAgaWYgKHRyYW5zY2VpdmVyLmtpbmQgPT09ICdhcHBsaWNhdGlvbicpIHtcbiAgICAgICAgICBzZHAgKz0gJ209YXBwbGljYXRpb24gMCBEVExTL1NDVFAgNTAwMFxcclxcbic7XG4gICAgICAgIH0gZWxzZSBpZiAodHJhbnNjZWl2ZXIua2luZCA9PT0gJ2F1ZGlvJykge1xuICAgICAgICAgIHNkcCArPSAnbT1hdWRpbyAwIFVEUC9UTFMvUlRQL1NBVlBGIDBcXHJcXG4nICtcbiAgICAgICAgICAgICAgJ2E9cnRwbWFwOjAgUENNVS84MDAwXFxyXFxuJztcbiAgICAgICAgfSBlbHNlIGlmICh0cmFuc2NlaXZlci5raW5kID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgc2RwICs9ICdtPXZpZGVvIDAgVURQL1RMUy9SVFAvU0FWUEYgMTIwXFxyXFxuJyArXG4gICAgICAgICAgICAgICdhPXJ0cG1hcDoxMjAgVlA4LzkwMDAwXFxyXFxuJztcbiAgICAgICAgfVxuICAgICAgICBzZHAgKz0gJ2M9SU4gSVA0IDAuMC4wLjBcXHJcXG4nICtcbiAgICAgICAgICAgICdhPWluYWN0aXZlXFxyXFxuJyArXG4gICAgICAgICAgICAnYT1taWQ6JyArIHRyYW5zY2VpdmVyLm1pZCArICdcXHJcXG4nO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIEZJWE1FOiBsb29rIGF0IGRpcmVjdGlvbi5cbiAgICAgIGlmICh0cmFuc2NlaXZlci5zdHJlYW0pIHtcbiAgICAgICAgdmFyIGxvY2FsVHJhY2s7XG4gICAgICAgIGlmICh0cmFuc2NlaXZlci5raW5kID09PSAnYXVkaW8nKSB7XG4gICAgICAgICAgbG9jYWxUcmFjayA9IHRyYW5zY2VpdmVyLnN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdO1xuICAgICAgICB9IGVsc2UgaWYgKHRyYW5zY2VpdmVyLmtpbmQgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICBsb2NhbFRyYWNrID0gdHJhbnNjZWl2ZXIuc3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGxvY2FsVHJhY2spIHtcbiAgICAgICAgICAvLyBhZGQgUlRYXG4gICAgICAgICAgaWYgKGVkZ2VWZXJzaW9uID49IDE1MDE5ICYmIHRyYW5zY2VpdmVyLmtpbmQgPT09ICd2aWRlbycgJiZcbiAgICAgICAgICAgICAgIXRyYW5zY2VpdmVyLnNlbmRFbmNvZGluZ1BhcmFtZXRlcnNbMF0ucnR4KSB7XG4gICAgICAgICAgICB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzWzBdLnJ0eCA9IHtcbiAgICAgICAgICAgICAgc3NyYzogdHJhbnNjZWl2ZXIuc2VuZEVuY29kaW5nUGFyYW1ldGVyc1swXS5zc3JjICsgMVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gQ2FsY3VsYXRlIGludGVyc2VjdGlvbiBvZiBjYXBhYmlsaXRpZXMuXG4gICAgICB2YXIgY29tbW9uQ2FwYWJpbGl0aWVzID0gZ2V0Q29tbW9uQ2FwYWJpbGl0aWVzKFxuICAgICAgICAgIHRyYW5zY2VpdmVyLmxvY2FsQ2FwYWJpbGl0aWVzLFxuICAgICAgICAgIHRyYW5zY2VpdmVyLnJlbW90ZUNhcGFiaWxpdGllcyk7XG5cbiAgICAgIHZhciBoYXNSdHggPSBjb21tb25DYXBhYmlsaXRpZXMuY29kZWNzLmZpbHRlcihmdW5jdGlvbihjKSB7XG4gICAgICAgIHJldHVybiBjLm5hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ3J0eCc7XG4gICAgICB9KS5sZW5ndGg7XG4gICAgICBpZiAoIWhhc1J0eCAmJiB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzWzBdLnJ0eCkge1xuICAgICAgICBkZWxldGUgdHJhbnNjZWl2ZXIuc2VuZEVuY29kaW5nUGFyYW1ldGVyc1swXS5ydHg7XG4gICAgICB9XG5cbiAgICAgIHNkcCArPSB3cml0ZU1lZGlhU2VjdGlvbih0cmFuc2NlaXZlciwgY29tbW9uQ2FwYWJpbGl0aWVzLFxuICAgICAgICAgICdhbnN3ZXInLCB0cmFuc2NlaXZlci5zdHJlYW0sIHBjLl9kdGxzUm9sZSk7XG4gICAgICBpZiAodHJhbnNjZWl2ZXIucnRjcFBhcmFtZXRlcnMgJiZcbiAgICAgICAgICB0cmFuc2NlaXZlci5ydGNwUGFyYW1ldGVycy5yZWR1Y2VkU2l6ZSkge1xuICAgICAgICBzZHAgKz0gJ2E9cnRjcC1yc2l6ZVxcclxcbic7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB2YXIgZGVzYyA9IG5ldyB3aW5kb3cuUlRDU2Vzc2lvbkRlc2NyaXB0aW9uKHtcbiAgICAgIHR5cGU6ICdhbnN3ZXInLFxuICAgICAgc2RwOiBzZHBcbiAgICB9KTtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGRlc2MpO1xuICB9O1xuXG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5hZGRJY2VDYW5kaWRhdGUgPSBmdW5jdGlvbihjYW5kaWRhdGUpIHtcbiAgICB2YXIgcGMgPSB0aGlzO1xuICAgIHZhciBzZWN0aW9ucztcbiAgICBpZiAoY2FuZGlkYXRlICYmICEoY2FuZGlkYXRlLnNkcE1MaW5lSW5kZXggIT09IHVuZGVmaW5lZCB8fFxuICAgICAgICBjYW5kaWRhdGUuc2RwTWlkKSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBUeXBlRXJyb3IoJ3NkcE1MaW5lSW5kZXggb3Igc2RwTWlkIHJlcXVpcmVkJykpO1xuICAgIH1cblxuICAgIC8vIFRPRE86IG5lZWRzIHRvIGdvIGludG8gb3BzIHF1ZXVlLlxuICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIGlmICghcGMucmVtb3RlRGVzY3JpcHRpb24pIHtcbiAgICAgICAgcmV0dXJuIHJlamVjdChtYWtlRXJyb3IoJ0ludmFsaWRTdGF0ZUVycm9yJyxcbiAgICAgICAgICAgICdDYW4gbm90IGFkZCBJQ0UgY2FuZGlkYXRlIHdpdGhvdXQgYSByZW1vdGUgZGVzY3JpcHRpb24nKSk7XG4gICAgICB9IGVsc2UgaWYgKCFjYW5kaWRhdGUgfHwgY2FuZGlkYXRlLmNhbmRpZGF0ZSA9PT0gJycpIHtcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBwYy50cmFuc2NlaXZlcnMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICBpZiAocGMudHJhbnNjZWl2ZXJzW2pdLnJlamVjdGVkKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcGMudHJhbnNjZWl2ZXJzW2pdLmljZVRyYW5zcG9ydC5hZGRSZW1vdGVDYW5kaWRhdGUoe30pO1xuICAgICAgICAgIHNlY3Rpb25zID0gU0RQVXRpbHMuZ2V0TWVkaWFTZWN0aW9ucyhwYy5yZW1vdGVEZXNjcmlwdGlvbi5zZHApO1xuICAgICAgICAgIHNlY3Rpb25zW2pdICs9ICdhPWVuZC1vZi1jYW5kaWRhdGVzXFxyXFxuJztcbiAgICAgICAgICBwYy5yZW1vdGVEZXNjcmlwdGlvbi5zZHAgPVxuICAgICAgICAgICAgICBTRFBVdGlscy5nZXREZXNjcmlwdGlvbihwYy5yZW1vdGVEZXNjcmlwdGlvbi5zZHApICtcbiAgICAgICAgICAgICAgc2VjdGlvbnMuam9pbignJyk7XG4gICAgICAgICAgaWYgKHBjLnVzaW5nQnVuZGxlKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBzZHBNTGluZUluZGV4ID0gY2FuZGlkYXRlLnNkcE1MaW5lSW5kZXg7XG4gICAgICAgIGlmIChjYW5kaWRhdGUuc2RwTWlkKSB7XG4gICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYy50cmFuc2NlaXZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChwYy50cmFuc2NlaXZlcnNbaV0ubWlkID09PSBjYW5kaWRhdGUuc2RwTWlkKSB7XG4gICAgICAgICAgICAgIHNkcE1MaW5lSW5kZXggPSBpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHRyYW5zY2VpdmVyID0gcGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdO1xuICAgICAgICBpZiAodHJhbnNjZWl2ZXIpIHtcbiAgICAgICAgICBpZiAodHJhbnNjZWl2ZXIucmVqZWN0ZWQpIHtcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZlKCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhciBjYW5kID0gT2JqZWN0LmtleXMoY2FuZGlkYXRlLmNhbmRpZGF0ZSkubGVuZ3RoID4gMCA/XG4gICAgICAgICAgICAgIFNEUFV0aWxzLnBhcnNlQ2FuZGlkYXRlKGNhbmRpZGF0ZS5jYW5kaWRhdGUpIDoge307XG4gICAgICAgICAgLy8gSWdub3JlIENocm9tZSdzIGludmFsaWQgY2FuZGlkYXRlcyBzaW5jZSBFZGdlIGRvZXMgbm90IGxpa2UgdGhlbS5cbiAgICAgICAgICBpZiAoY2FuZC5wcm90b2NvbCA9PT0gJ3RjcCcgJiYgKGNhbmQucG9ydCA9PT0gMCB8fCBjYW5kLnBvcnQgPT09IDkpKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBJZ25vcmUgUlRDUCBjYW5kaWRhdGVzLCB3ZSBhc3N1bWUgUlRDUC1NVVguXG4gICAgICAgICAgaWYgKGNhbmQuY29tcG9uZW50ICYmIGNhbmQuY29tcG9uZW50ICE9PSAxKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyB3aGVuIHVzaW5nIGJ1bmRsZSwgYXZvaWQgYWRkaW5nIGNhbmRpZGF0ZXMgdG8gdGhlIHdyb25nXG4gICAgICAgICAgLy8gaWNlIHRyYW5zcG9ydC4gQW5kIGF2b2lkIGFkZGluZyBjYW5kaWRhdGVzIGFkZGVkIGluIHRoZSBTRFAuXG4gICAgICAgICAgaWYgKHNkcE1MaW5lSW5kZXggPT09IDAgfHwgKHNkcE1MaW5lSW5kZXggPiAwICYmXG4gICAgICAgICAgICAgIHRyYW5zY2VpdmVyLmljZVRyYW5zcG9ydCAhPT0gcGMudHJhbnNjZWl2ZXJzWzBdLmljZVRyYW5zcG9ydCkpIHtcbiAgICAgICAgICAgIGlmICghbWF5YmVBZGRDYW5kaWRhdGUodHJhbnNjZWl2ZXIuaWNlVHJhbnNwb3J0LCBjYW5kKSkge1xuICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KG1ha2VFcnJvcignT3BlcmF0aW9uRXJyb3InLFxuICAgICAgICAgICAgICAgICAgJ0NhbiBub3QgYWRkIElDRSBjYW5kaWRhdGUnKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gdXBkYXRlIHRoZSByZW1vdGVEZXNjcmlwdGlvbi5cbiAgICAgICAgICB2YXIgY2FuZGlkYXRlU3RyaW5nID0gY2FuZGlkYXRlLmNhbmRpZGF0ZS50cmltKCk7XG4gICAgICAgICAgaWYgKGNhbmRpZGF0ZVN0cmluZy5pbmRleE9mKCdhPScpID09PSAwKSB7XG4gICAgICAgICAgICBjYW5kaWRhdGVTdHJpbmcgPSBjYW5kaWRhdGVTdHJpbmcuc3Vic3RyKDIpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzZWN0aW9ucyA9IFNEUFV0aWxzLmdldE1lZGlhU2VjdGlvbnMocGMucmVtb3RlRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICBzZWN0aW9uc1tzZHBNTGluZUluZGV4XSArPSAnYT0nICtcbiAgICAgICAgICAgICAgKGNhbmQudHlwZSA/IGNhbmRpZGF0ZVN0cmluZyA6ICdlbmQtb2YtY2FuZGlkYXRlcycpXG4gICAgICAgICAgICAgICsgJ1xcclxcbic7XG4gICAgICAgICAgcGMucmVtb3RlRGVzY3JpcHRpb24uc2RwID0gc2VjdGlvbnMuam9pbignJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChtYWtlRXJyb3IoJ09wZXJhdGlvbkVycm9yJyxcbiAgICAgICAgICAgICAgJ0NhbiBub3QgYWRkIElDRSBjYW5kaWRhdGUnKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJlc29sdmUoKTtcbiAgICB9KTtcbiAgfTtcblxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuZ2V0U3RhdHMgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgcHJvbWlzZXMgPSBbXTtcbiAgICB0aGlzLnRyYW5zY2VpdmVycy5mb3JFYWNoKGZ1bmN0aW9uKHRyYW5zY2VpdmVyKSB7XG4gICAgICBbJ3J0cFNlbmRlcicsICdydHBSZWNlaXZlcicsICdpY2VHYXRoZXJlcicsICdpY2VUcmFuc3BvcnQnLFxuICAgICAgICAgICdkdGxzVHJhbnNwb3J0J10uZm9yRWFjaChmdW5jdGlvbihtZXRob2QpIHtcbiAgICAgICAgICAgIGlmICh0cmFuc2NlaXZlclttZXRob2RdKSB7XG4gICAgICAgICAgICAgIHByb21pc2VzLnB1c2godHJhbnNjZWl2ZXJbbWV0aG9kXS5nZXRTdGF0cygpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICB9KTtcbiAgICB2YXIgZml4U3RhdHNUeXBlID0gZnVuY3Rpb24oc3RhdCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaW5ib3VuZHJ0cDogJ2luYm91bmQtcnRwJyxcbiAgICAgICAgb3V0Ym91bmRydHA6ICdvdXRib3VuZC1ydHAnLFxuICAgICAgICBjYW5kaWRhdGVwYWlyOiAnY2FuZGlkYXRlLXBhaXInLFxuICAgICAgICBsb2NhbGNhbmRpZGF0ZTogJ2xvY2FsLWNhbmRpZGF0ZScsXG4gICAgICAgIHJlbW90ZWNhbmRpZGF0ZTogJ3JlbW90ZS1jYW5kaWRhdGUnXG4gICAgICB9W3N0YXQudHlwZV0gfHwgc3RhdC50eXBlO1xuICAgIH07XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUpIHtcbiAgICAgIC8vIHNoaW0gZ2V0U3RhdHMgd2l0aCBtYXBsaWtlIHN1cHBvcnRcbiAgICAgIHZhciByZXN1bHRzID0gbmV3IE1hcCgpO1xuICAgICAgUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24ocmVzKSB7XG4gICAgICAgIHJlcy5mb3JFYWNoKGZ1bmN0aW9uKHJlc3VsdCkge1xuICAgICAgICAgIE9iamVjdC5rZXlzKHJlc3VsdCkuZm9yRWFjaChmdW5jdGlvbihpZCkge1xuICAgICAgICAgICAgcmVzdWx0W2lkXS50eXBlID0gZml4U3RhdHNUeXBlKHJlc3VsdFtpZF0pO1xuICAgICAgICAgICAgcmVzdWx0cy5zZXQoaWQsIHJlc3VsdFtpZF0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmVzb2x2ZShyZXN1bHRzKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9O1xuXG4gIC8vIGxlZ2FjeSBjYWxsYmFjayBzaGltcy4gU2hvdWxkIGJlIG1vdmVkIHRvIGFkYXB0ZXIuanMgc29tZSBkYXlzLlxuICB2YXIgbWV0aG9kcyA9IFsnY3JlYXRlT2ZmZXInLCAnY3JlYXRlQW5zd2VyJ107XG4gIG1ldGhvZHMuZm9yRWFjaChmdW5jdGlvbihtZXRob2QpIHtcbiAgICB2YXIgbmF0aXZlTWV0aG9kID0gUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlW21ldGhvZF07XG4gICAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlW21ldGhvZF0gPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgaWYgKHR5cGVvZiBhcmdzWzBdID09PSAnZnVuY3Rpb24nIHx8XG4gICAgICAgICAgdHlwZW9mIGFyZ3NbMV0gPT09ICdmdW5jdGlvbicpIHsgLy8gbGVnYWN5XG4gICAgICAgIHJldHVybiBuYXRpdmVNZXRob2QuYXBwbHkodGhpcywgW2FyZ3VtZW50c1syXV0pXG4gICAgICAgIC50aGVuKGZ1bmN0aW9uKGRlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBhcmdzWzBdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBhcmdzWzBdLmFwcGx5KG51bGwsIFtkZXNjcmlwdGlvbl0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSwgZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGFyZ3NbMV0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGFyZ3NbMV0uYXBwbHkobnVsbCwgW2Vycm9yXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuYXRpdmVNZXRob2QuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9O1xuICB9KTtcblxuICBtZXRob2RzID0gWydzZXRMb2NhbERlc2NyaXB0aW9uJywgJ3NldFJlbW90ZURlc2NyaXB0aW9uJywgJ2FkZEljZUNhbmRpZGF0ZSddO1xuICBtZXRob2RzLmZvckVhY2goZnVuY3Rpb24obWV0aG9kKSB7XG4gICAgdmFyIG5hdGl2ZU1ldGhvZCA9IFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZVttZXRob2RdO1xuICAgIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZVttZXRob2RdID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgIGlmICh0eXBlb2YgYXJnc1sxXSA9PT0gJ2Z1bmN0aW9uJyB8fFxuICAgICAgICAgIHR5cGVvZiBhcmdzWzJdID09PSAnZnVuY3Rpb24nKSB7IC8vIGxlZ2FjeVxuICAgICAgICByZXR1cm4gbmF0aXZlTWV0aG9kLmFwcGx5KHRoaXMsIGFyZ3VtZW50cylcbiAgICAgICAgLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBhcmdzWzFdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBhcmdzWzFdLmFwcGx5KG51bGwpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSwgZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGFyZ3NbMl0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGFyZ3NbMl0uYXBwbHkobnVsbCwgW2Vycm9yXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuYXRpdmVNZXRob2QuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9O1xuICB9KTtcblxuICAvLyBnZXRTdGF0cyBpcyBzcGVjaWFsLiBJdCBkb2Vzbid0IGhhdmUgYSBzcGVjIGxlZ2FjeSBtZXRob2QgeWV0IHdlIHN1cHBvcnRcbiAgLy8gZ2V0U3RhdHMoc29tZXRoaW5nLCBjYikgd2l0aG91dCBlcnJvciBjYWxsYmFja3MuXG4gIFsnZ2V0U3RhdHMnXS5mb3JFYWNoKGZ1bmN0aW9uKG1ldGhvZCkge1xuICAgIHZhciBuYXRpdmVNZXRob2QgPSBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGVbbWV0aG9kXTtcbiAgICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGVbbWV0aG9kXSA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICBpZiAodHlwZW9mIGFyZ3NbMV0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIG5hdGl2ZU1ldGhvZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpXG4gICAgICAgIC50aGVuKGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGlmICh0eXBlb2YgYXJnc1sxXSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgYXJnc1sxXS5hcHBseShudWxsKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG5hdGl2ZU1ldGhvZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG4gIH0pO1xuXG4gIHJldHVybiBSVENQZWVyQ29ubmVjdGlvbjtcbn07XG4iLCJ2YXIgZ3JhbW1hciA9IG1vZHVsZS5leHBvcnRzID0ge1xuICB2OiBbe1xuICAgICAgbmFtZTogJ3ZlcnNpb24nLFxuICAgICAgcmVnOiAvXihcXGQqKSQvXG4gIH1dLFxuICBvOiBbeyAvL289LSAyMDUxOCAwIElOIElQNCAyMDMuMC4xMTMuMVxuICAgIC8vIE5COiBzZXNzaW9uSWQgd2lsbCBiZSBhIFN0cmluZyBpbiBtb3N0IGNhc2VzIGJlY2F1c2UgaXQgaXMgaHVnZVxuICAgIG5hbWU6ICdvcmlnaW4nLFxuICAgIHJlZzogL14oXFxTKikgKFxcZCopIChcXGQqKSAoXFxTKikgSVAoXFxkKSAoXFxTKikvLFxuICAgIG5hbWVzOiBbJ3VzZXJuYW1lJywgJ3Nlc3Npb25JZCcsICdzZXNzaW9uVmVyc2lvbicsICduZXRUeXBlJywgJ2lwVmVyJywgJ2FkZHJlc3MnXSxcbiAgICBmb3JtYXQ6IFwiJXMgJXMgJWQgJXMgSVAlZCAlc1wiXG4gIH1dLFxuICAvLyBkZWZhdWx0IHBhcnNpbmcgb2YgdGhlc2Ugb25seSAodGhvdWdoIHNvbWUgb2YgdGhlc2UgZmVlbCBvdXRkYXRlZClcbiAgczogW3sgbmFtZTogJ25hbWUnIH1dLFxuICBpOiBbeyBuYW1lOiAnZGVzY3JpcHRpb24nIH1dLFxuICB1OiBbeyBuYW1lOiAndXJpJyB9XSxcbiAgZTogW3sgbmFtZTogJ2VtYWlsJyB9XSxcbiAgcDogW3sgbmFtZTogJ3Bob25lJyB9XSxcbiAgejogW3sgbmFtZTogJ3RpbWV6b25lcycgfV0sIC8vIFRPRE86IHRoaXMgb25lIGNhbiBhY3R1YWxseSBiZSBwYXJzZWQgcHJvcGVybHkuLlxuICByOiBbeyBuYW1lOiAncmVwZWF0cycgfV0sICAgLy8gVE9ETzogdGhpcyBvbmUgY2FuIGFsc28gYmUgcGFyc2VkIHByb3Blcmx5XG4gIC8vazogW3t9XSwgLy8gb3V0ZGF0ZWQgdGhpbmcgaWdub3JlZFxuICB0OiBbeyAvL3Q9MCAwXG4gICAgbmFtZTogJ3RpbWluZycsXG4gICAgcmVnOiAvXihcXGQqKSAoXFxkKikvLFxuICAgIG5hbWVzOiBbJ3N0YXJ0JywgJ3N0b3AnXSxcbiAgICBmb3JtYXQ6IFwiJWQgJWRcIlxuICB9XSxcbiAgYzogW3sgLy9jPUlOIElQNCAxMC40Ny4xOTcuMjZcbiAgICAgIG5hbWU6ICdjb25uZWN0aW9uJyxcbiAgICAgIHJlZzogL15JTiBJUChcXGQpIChcXFMqKS8sXG4gICAgICBuYW1lczogWyd2ZXJzaW9uJywgJ2lwJ10sXG4gICAgICBmb3JtYXQ6IFwiSU4gSVAlZCAlc1wiXG4gIH1dLFxuICBiOiBbeyAvL2I9QVM6NDAwMFxuICAgICAgcHVzaDogJ2JhbmR3aWR0aCcsXG4gICAgICByZWc6IC9eKFRJQVN8QVN8Q1R8UlJ8UlMpOihcXGQqKS8sXG4gICAgICBuYW1lczogWyd0eXBlJywgJ2xpbWl0J10sXG4gICAgICBmb3JtYXQ6IFwiJXM6JXNcIlxuICB9XSxcbiAgbTogW3sgLy9tPXZpZGVvIDUxNzQ0IFJUUC9BVlAgMTI2IDk3IDk4IDM0IDMxXG4gICAgICAvLyBOQjogc3BlY2lhbCAtIHB1c2hlcyB0byBzZXNzaW9uXG4gICAgICAvLyBUT0RPOiBydHAvZm10cCBzaG91bGQgYmUgZmlsdGVyZWQgYnkgdGhlIHBheWxvYWRzIGZvdW5kIGhlcmU/XG4gICAgICByZWc6IC9eKFxcdyopIChcXGQqKSAoW1xcd1xcL10qKSg/OiAoLiopKT8vLFxuICAgICAgbmFtZXM6IFsndHlwZScsICdwb3J0JywgJ3Byb3RvY29sJywgJ3BheWxvYWRzJ10sXG4gICAgICBmb3JtYXQ6IFwiJXMgJWQgJXMgJXNcIlxuICB9XSxcbiAgYTogW1xuICAgIHsgLy9hPXJ0cG1hcDoxMTAgb3B1cy80ODAwMC8yXG4gICAgICBwdXNoOiAncnRwJyxcbiAgICAgIHJlZzogL15ydHBtYXA6KFxcZCopIChbXFx3XFwtXSopKD86XFxzKlxcLyhcXGQqKSg/OlxccypcXC8oXFxTKikpPyk/LyxcbiAgICAgIG5hbWVzOiBbJ3BheWxvYWQnLCAnY29kZWMnLCAncmF0ZScsICdlbmNvZGluZyddLFxuICAgICAgZm9ybWF0OiBmdW5jdGlvbiAobykge1xuICAgICAgICByZXR1cm4gKG8uZW5jb2RpbmcpID9cbiAgICAgICAgICBcInJ0cG1hcDolZCAlcy8lcy8lc1wiOlxuICAgICAgICAgIG8ucmF0ZSA/XG4gICAgICAgICAgXCJydHBtYXA6JWQgJXMvJXNcIjpcbiAgICAgICAgICBcInJ0cG1hcDolZCAlc1wiO1xuICAgICAgfVxuICAgIH0sXG4gICAge1xuICAgICAgLy9hPWZtdHA6MTA4IHByb2ZpbGUtbGV2ZWwtaWQ9MjQ7b2JqZWN0PTIzO2JpdHJhdGU9NjQwMDBcbiAgICAgIC8vYT1mbXRwOjExMSBtaW5wdGltZT0xMDsgdXNlaW5iYW5kZmVjPTFcbiAgICAgIHB1c2g6ICdmbXRwJyxcbiAgICAgIHJlZzogL15mbXRwOihcXGQqKSAoW1xcU3wgXSopLyxcbiAgICAgIG5hbWVzOiBbJ3BheWxvYWQnLCAnY29uZmlnJ10sXG4gICAgICBmb3JtYXQ6IFwiZm10cDolZCAlc1wiXG4gICAgfSxcbiAgICB7IC8vYT1jb250cm9sOnN0cmVhbWlkPTBcbiAgICAgICAgbmFtZTogJ2NvbnRyb2wnLFxuICAgICAgICByZWc6IC9eY29udHJvbDooLiopLyxcbiAgICAgICAgZm9ybWF0OiBcImNvbnRyb2w6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9cnRjcDo2NTE3OSBJTiBJUDQgMTkzLjg0Ljc3LjE5NFxuICAgICAgbmFtZTogJ3J0Y3AnLFxuICAgICAgcmVnOiAvXnJ0Y3A6KFxcZCopKD86IChcXFMqKSBJUChcXGQpIChcXFMqKSk/LyxcbiAgICAgIG5hbWVzOiBbJ3BvcnQnLCAnbmV0VHlwZScsICdpcFZlcicsICdhZGRyZXNzJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAoby5hZGRyZXNzICE9IG51bGwpID9cbiAgICAgICAgICBcInJ0Y3A6JWQgJXMgSVAlZCAlc1wiOlxuICAgICAgICAgIFwicnRjcDolZFwiO1xuICAgICAgfVxuICAgIH0sXG4gICAgeyAvL2E9cnRjcC1mYjo5OCB0cnItaW50IDEwMFxuICAgICAgcHVzaDogJ3J0Y3BGYlRyckludCcsXG4gICAgICByZWc6IC9ecnRjcC1mYjooXFwqfFxcZCopIHRyci1pbnQgKFxcZCopLyxcbiAgICAgIG5hbWVzOiBbJ3BheWxvYWQnLCAndmFsdWUnXSxcbiAgICAgIGZvcm1hdDogXCJydGNwLWZiOiVkIHRyci1pbnQgJWRcIlxuICAgIH0sXG4gICAgeyAvL2E9cnRjcC1mYjo5OCBuYWNrIHJwc2lcbiAgICAgIHB1c2g6ICdydGNwRmInLFxuICAgICAgcmVnOiAvXnJ0Y3AtZmI6KFxcKnxcXGQqKSAoW1xcdy1fXSopKD86IChbXFx3LV9dKikpPy8sXG4gICAgICBuYW1lczogWydwYXlsb2FkJywgJ3R5cGUnLCAnc3VidHlwZSddLFxuICAgICAgZm9ybWF0OiBmdW5jdGlvbiAobykge1xuICAgICAgICByZXR1cm4gKG8uc3VidHlwZSAhPSBudWxsKSA/XG4gICAgICAgICAgXCJydGNwLWZiOiVzICVzICVzXCI6XG4gICAgICAgICAgXCJydGNwLWZiOiVzICVzXCI7XG4gICAgICB9XG4gICAgfSxcbiAgICB7IC8vYT1leHRtYXA6MiB1cm46aWV0ZjpwYXJhbXM6cnRwLWhkcmV4dDp0b2Zmc2V0XG4gICAgICAvL2E9ZXh0bWFwOjEvcmVjdm9ubHkgVVJJLWdwcy1zdHJpbmdcbiAgICAgIHB1c2g6ICdleHQnLFxuICAgICAgcmVnOiAvXmV4dG1hcDooW1xcd19cXC9dKikgKFxcUyopKD86IChcXFMqKSk/LyxcbiAgICAgIG5hbWVzOiBbJ3ZhbHVlJywgJ3VyaScsICdjb25maWcnXSwgLy8gdmFsdWUgbWF5IGluY2x1ZGUgXCIvZGlyZWN0aW9uXCIgc3VmZml4XG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAoby5jb25maWcgIT0gbnVsbCkgP1xuICAgICAgICAgIFwiZXh0bWFwOiVzICVzICVzXCI6XG4gICAgICAgICAgXCJleHRtYXA6JXMgJXNcIjtcbiAgICAgIH1cbiAgICB9LFxuICAgIHtcbiAgICAgIC8vYT1jcnlwdG86MSBBRVNfQ01fMTI4X0hNQUNfU0hBMV84MCBpbmxpbmU6UFMxdVFDVmVlQ0ZDYW5WbWNqa3BQeXdqTldoY1lEMG1YWHR4YVZCUnwyXjIwfDE6MzJcbiAgICAgIHB1c2g6ICdjcnlwdG8nLFxuICAgICAgcmVnOiAvXmNyeXB0bzooXFxkKikgKFtcXHdfXSopIChcXFMqKSg/OiAoXFxTKikpPy8sXG4gICAgICBuYW1lczogWydpZCcsICdzdWl0ZScsICdjb25maWcnLCAnc2Vzc2lvbkNvbmZpZyddLFxuICAgICAgZm9ybWF0OiBmdW5jdGlvbiAobykge1xuICAgICAgICByZXR1cm4gKG8uc2Vzc2lvbkNvbmZpZyAhPSBudWxsKSA/XG4gICAgICAgICAgXCJjcnlwdG86JWQgJXMgJXMgJXNcIjpcbiAgICAgICAgICBcImNyeXB0bzolZCAlcyAlc1wiO1xuICAgICAgfVxuICAgIH0sXG4gICAgeyAvL2E9c2V0dXA6YWN0cGFzc1xuICAgICAgbmFtZTogJ3NldHVwJyxcbiAgICAgIHJlZzogL15zZXR1cDooXFx3KikvLFxuICAgICAgZm9ybWF0OiBcInNldHVwOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPW1pZDoxXG4gICAgICBuYW1lOiAnbWlkJyxcbiAgICAgIHJlZzogL15taWQ6KFteXFxzXSopLyxcbiAgICAgIGZvcm1hdDogXCJtaWQ6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9bXNpZDowYzhiMDY0ZC1kODA3LTQzYjQtYjQzNC1mOTJhODg5ZDg1ODcgOTgxNzg2ODUtZDQwOS00NmUwLThlMTYtN2VmMGRiMGRiNjRhXG4gICAgICBuYW1lOiAnbXNpZCcsXG4gICAgICByZWc6IC9ebXNpZDooLiopLyxcbiAgICAgIGZvcm1hdDogXCJtc2lkOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPXB0aW1lOjIwXG4gICAgICBuYW1lOiAncHRpbWUnLFxuICAgICAgcmVnOiAvXnB0aW1lOihcXGQqKS8sXG4gICAgICBmb3JtYXQ6IFwicHRpbWU6JWRcIlxuICAgIH0sXG4gICAgeyAvL2E9bWF4cHRpbWU6NjBcbiAgICAgIG5hbWU6ICdtYXhwdGltZScsXG4gICAgICByZWc6IC9ebWF4cHRpbWU6KFxcZCopLyxcbiAgICAgIGZvcm1hdDogXCJtYXhwdGltZTolZFwiXG4gICAgfSxcbiAgICB7IC8vYT1zZW5kcmVjdlxuICAgICAgbmFtZTogJ2RpcmVjdGlvbicsXG4gICAgICByZWc6IC9eKHNlbmRyZWN2fHJlY3Zvbmx5fHNlbmRvbmx5fGluYWN0aXZlKS9cbiAgICB9LFxuICAgIHsgLy9hPWljZS1saXRlXG4gICAgICBuYW1lOiAnaWNlbGl0ZScsXG4gICAgICByZWc6IC9eKGljZS1saXRlKS9cbiAgICB9LFxuICAgIHsgLy9hPWljZS11ZnJhZzpGN2dJXG4gICAgICBuYW1lOiAnaWNlVWZyYWcnLFxuICAgICAgcmVnOiAvXmljZS11ZnJhZzooXFxTKikvLFxuICAgICAgZm9ybWF0OiBcImljZS11ZnJhZzolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1pY2UtcHdkOng5Y21sL1l6aWNoVjIrWGxoaU11OGdcbiAgICAgIG5hbWU6ICdpY2VQd2QnLFxuICAgICAgcmVnOiAvXmljZS1wd2Q6KFxcUyopLyxcbiAgICAgIGZvcm1hdDogXCJpY2UtcHdkOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPWZpbmdlcnByaW50OlNIQS0xIDAwOjExOjIyOjMzOjQ0OjU1OjY2Ojc3Ojg4Ojk5OkFBOkJCOkNDOkREOkVFOkZGOjAwOjExOjIyOjMzXG4gICAgICBuYW1lOiAnZmluZ2VycHJpbnQnLFxuICAgICAgcmVnOiAvXmZpbmdlcnByaW50OihcXFMqKSAoXFxTKikvLFxuICAgICAgbmFtZXM6IFsndHlwZScsICdoYXNoJ10sXG4gICAgICBmb3JtYXQ6IFwiZmluZ2VycHJpbnQ6JXMgJXNcIlxuICAgIH0sXG4gICAge1xuICAgICAgLy9hPWNhbmRpZGF0ZTowIDEgVURQIDIxMTM2NjczMjcgMjAzLjAuMTEzLjEgNTQ0MDAgdHlwIGhvc3RcbiAgICAgIC8vYT1jYW5kaWRhdGU6MTE2Mjg3NTA4MSAxIHVkcCAyMTEzOTM3MTUxIDE5Mi4xNjguMzQuNzUgNjAwMTcgdHlwIGhvc3QgZ2VuZXJhdGlvbiAwXG4gICAgICAvL2E9Y2FuZGlkYXRlOjMyODk5MTI5NTcgMiB1ZHAgMTg0NTUwMTY5NSAxOTMuODQuNzcuMTk0IDYwMDE3IHR5cCBzcmZseCByYWRkciAxOTIuMTY4LjM0Ljc1IHJwb3J0IDYwMDE3IGdlbmVyYXRpb24gMFxuICAgICAgLy9hPWNhbmRpZGF0ZToyMjk4MTU2MjAgMSB0Y3AgMTUxODI4MDQ0NyAxOTIuMTY4LjE1MC4xOSA2MDAxNyB0eXAgaG9zdCB0Y3B0eXBlIGFjdGl2ZSBnZW5lcmF0aW9uIDBcbiAgICAgIC8vYT1jYW5kaWRhdGU6MzI4OTkxMjk1NyAyIHRjcCAxODQ1NTAxNjk1IDE5My44NC43Ny4xOTQgNjAwMTcgdHlwIHNyZmx4IHJhZGRyIDE5Mi4xNjguMzQuNzUgcnBvcnQgNjAwMTcgdGNwdHlwZSBwYXNzaXZlIGdlbmVyYXRpb24gMFxuICAgICAgcHVzaDonY2FuZGlkYXRlcycsXG4gICAgICByZWc6IC9eY2FuZGlkYXRlOihcXFMqKSAoXFxkKikgKFxcUyopIChcXGQqKSAoXFxTKikgKFxcZCopIHR5cCAoXFxTKikoPzogcmFkZHIgKFxcUyopIHJwb3J0IChcXGQqKSk/KD86IHRjcHR5cGUgKFxcUyopKT8oPzogZ2VuZXJhdGlvbiAoXFxkKikpPy8sXG4gICAgICBuYW1lczogWydmb3VuZGF0aW9uJywgJ2NvbXBvbmVudCcsICd0cmFuc3BvcnQnLCAncHJpb3JpdHknLCAnaXAnLCAncG9ydCcsICd0eXBlJywgJ3JhZGRyJywgJ3Jwb3J0JywgJ3RjcHR5cGUnLCAnZ2VuZXJhdGlvbiddLFxuICAgICAgZm9ybWF0OiBmdW5jdGlvbiAobykge1xuICAgICAgICB2YXIgc3RyID0gXCJjYW5kaWRhdGU6JXMgJWQgJXMgJWQgJXMgJWQgdHlwICVzXCI7XG5cbiAgICAgICAgc3RyICs9IChvLnJhZGRyICE9IG51bGwpID8gXCIgcmFkZHIgJXMgcnBvcnQgJWRcIiA6IFwiJXYldlwiO1xuXG4gICAgICAgIC8vIE5COiBjYW5kaWRhdGUgaGFzIHRocmVlIG9wdGlvbmFsIGNodW5rcywgc28gJXZvaWQgbWlkZGxlcyBvbmUgaWYgaXQncyBtaXNzaW5nXG4gICAgICAgIHN0ciArPSAoby50Y3B0eXBlICE9IG51bGwpID8gXCIgdGNwdHlwZSAlc1wiIDogXCIldlwiO1xuXG4gICAgICAgIGlmIChvLmdlbmVyYXRpb24gIT0gbnVsbCkge1xuICAgICAgICAgIHN0ciArPSBcIiBnZW5lcmF0aW9uICVkXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICAgIH1cbiAgICB9LFxuICAgIHsgLy9hPWVuZC1vZi1jYW5kaWRhdGVzIChrZWVwIGFmdGVyIHRoZSBjYW5kaWRhdGVzIGxpbmUgZm9yIHJlYWRhYmlsaXR5KVxuICAgICAgbmFtZTogJ2VuZE9mQ2FuZGlkYXRlcycsXG4gICAgICByZWc6IC9eKGVuZC1vZi1jYW5kaWRhdGVzKS9cbiAgICB9LFxuICAgIHsgLy9hPXJlbW90ZS1jYW5kaWRhdGVzOjEgMjAzLjAuMTEzLjEgNTQ0MDAgMiAyMDMuMC4xMTMuMSA1NDQwMSAuLi5cbiAgICAgIG5hbWU6ICdyZW1vdGVDYW5kaWRhdGVzJyxcbiAgICAgIHJlZzogL15yZW1vdGUtY2FuZGlkYXRlczooLiopLyxcbiAgICAgIGZvcm1hdDogXCJyZW1vdGUtY2FuZGlkYXRlczolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1pY2Utb3B0aW9uczpnb29nbGUtaWNlXG4gICAgICBuYW1lOiAnaWNlT3B0aW9ucycsXG4gICAgICByZWc6IC9eaWNlLW9wdGlvbnM6KFxcUyopLyxcbiAgICAgIGZvcm1hdDogXCJpY2Utb3B0aW9uczolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1zc3JjOjI1NjYxMDc1NjkgY25hbWU6dDlZVThNMVV4VEY4WTFBMVxuICAgICAgcHVzaDogXCJzc3Jjc1wiLFxuICAgICAgcmVnOiAvXnNzcmM6KFxcZCopIChbXFx3X10qKTooLiopLyxcbiAgICAgIG5hbWVzOiBbJ2lkJywgJ2F0dHJpYnV0ZScsICd2YWx1ZSddLFxuICAgICAgZm9ybWF0OiBcInNzcmM6JWQgJXM6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9c3NyYy1ncm91cDpGRUMgMSAyXG4gICAgICBwdXNoOiBcInNzcmNHcm91cHNcIixcbiAgICAgIHJlZzogL15zc3JjLWdyb3VwOihcXHcqKSAoLiopLyxcbiAgICAgIG5hbWVzOiBbJ3NlbWFudGljcycsICdzc3JjcyddLFxuICAgICAgZm9ybWF0OiBcInNzcmMtZ3JvdXA6JXMgJXNcIlxuICAgIH0sXG4gICAgeyAvL2E9bXNpZC1zZW1hbnRpYzogV01TIEp2bGFtNVgzU1gxT1A2cG4yMHpXb2d2YUtKejVIamY5T25sVlxuICAgICAgbmFtZTogXCJtc2lkU2VtYW50aWNcIixcbiAgICAgIHJlZzogL15tc2lkLXNlbWFudGljOlxccz8oXFx3KikgKFxcUyopLyxcbiAgICAgIG5hbWVzOiBbJ3NlbWFudGljJywgJ3Rva2VuJ10sXG4gICAgICBmb3JtYXQ6IFwibXNpZC1zZW1hbnRpYzogJXMgJXNcIiAvLyBzcGFjZSBhZnRlciBcIjpcIiBpcyBub3QgYWNjaWRlbnRhbFxuICAgIH0sXG4gICAgeyAvL2E9Z3JvdXA6QlVORExFIGF1ZGlvIHZpZGVvXG4gICAgICBwdXNoOiAnZ3JvdXBzJyxcbiAgICAgIHJlZzogL15ncm91cDooXFx3KikgKC4qKS8sXG4gICAgICBuYW1lczogWyd0eXBlJywgJ21pZHMnXSxcbiAgICAgIGZvcm1hdDogXCJncm91cDolcyAlc1wiXG4gICAgfSxcbiAgICB7IC8vYT1ydGNwLW11eFxuICAgICAgbmFtZTogJ3J0Y3BNdXgnLFxuICAgICAgcmVnOiAvXihydGNwLW11eCkvXG4gICAgfSxcbiAgICB7IC8vYT1ydGNwLXJzaXplXG4gICAgICBuYW1lOiAncnRjcFJzaXplJyxcbiAgICAgIHJlZzogL14ocnRjcC1yc2l6ZSkvXG4gICAgfSxcbiAgICB7IC8vIGFueSBhPSB0aGF0IHdlIGRvbid0IHVuZGVyc3RhbmQgaXMga2VwdHMgdmVyYmF0aW0gb24gbWVkaWEuaW52YWxpZFxuICAgICAgcHVzaDogJ2ludmFsaWQnLFxuICAgICAgbmFtZXM6IFtcInZhbHVlXCJdXG4gICAgfVxuICBdXG59O1xuXG4vLyBzZXQgc2Vuc2libGUgZGVmYXVsdHMgdG8gYXZvaWQgcG9sbHV0aW5nIHRoZSBncmFtbWFyIHdpdGggYm9yaW5nIGRldGFpbHNcbk9iamVjdC5rZXlzKGdyYW1tYXIpLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICB2YXIgb2JqcyA9IGdyYW1tYXJba2V5XTtcbiAgb2Jqcy5mb3JFYWNoKGZ1bmN0aW9uIChvYmopIHtcbiAgICBpZiAoIW9iai5yZWcpIHtcbiAgICAgIG9iai5yZWcgPSAvKC4qKS87XG4gICAgfVxuICAgIGlmICghb2JqLmZvcm1hdCkge1xuICAgICAgb2JqLmZvcm1hdCA9IFwiJXNcIjtcbiAgICB9XG4gIH0pO1xufSk7XG4iLCJ2YXIgcGFyc2VyID0gcmVxdWlyZSgnLi9wYXJzZXInKTtcbnZhciB3cml0ZXIgPSByZXF1aXJlKCcuL3dyaXRlcicpO1xuXG5leHBvcnRzLndyaXRlID0gd3JpdGVyO1xuZXhwb3J0cy5wYXJzZSA9IHBhcnNlci5wYXJzZTtcbmV4cG9ydHMucGFyc2VGbXRwQ29uZmlnID0gcGFyc2VyLnBhcnNlRm10cENvbmZpZztcbmV4cG9ydHMucGFyc2VQYXlsb2FkcyA9IHBhcnNlci5wYXJzZVBheWxvYWRzO1xuZXhwb3J0cy5wYXJzZVJlbW90ZUNhbmRpZGF0ZXMgPSBwYXJzZXIucGFyc2VSZW1vdGVDYW5kaWRhdGVzO1xuIiwidmFyIHRvSW50SWZJbnQgPSBmdW5jdGlvbiAodikge1xuICByZXR1cm4gU3RyaW5nKE51bWJlcih2KSkgPT09IHYgPyBOdW1iZXIodikgOiB2O1xufTtcblxudmFyIGF0dGFjaFByb3BlcnRpZXMgPSBmdW5jdGlvbiAobWF0Y2gsIGxvY2F0aW9uLCBuYW1lcywgcmF3TmFtZSkge1xuICBpZiAocmF3TmFtZSAmJiAhbmFtZXMpIHtcbiAgICBsb2NhdGlvbltyYXdOYW1lXSA9IHRvSW50SWZJbnQobWF0Y2hbMV0pO1xuICB9XG4gIGVsc2Uge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbmFtZXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgIGlmIChtYXRjaFtpKzFdICE9IG51bGwpIHtcbiAgICAgICAgbG9jYXRpb25bbmFtZXNbaV1dID0gdG9JbnRJZkludChtYXRjaFtpKzFdKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn07XG5cbnZhciBwYXJzZVJlZyA9IGZ1bmN0aW9uIChvYmosIGxvY2F0aW9uLCBjb250ZW50KSB7XG4gIHZhciBuZWVkc0JsYW5rID0gb2JqLm5hbWUgJiYgb2JqLm5hbWVzO1xuICBpZiAob2JqLnB1c2ggJiYgIWxvY2F0aW9uW29iai5wdXNoXSkge1xuICAgIGxvY2F0aW9uW29iai5wdXNoXSA9IFtdO1xuICB9XG4gIGVsc2UgaWYgKG5lZWRzQmxhbmsgJiYgIWxvY2F0aW9uW29iai5uYW1lXSkge1xuICAgIGxvY2F0aW9uW29iai5uYW1lXSA9IHt9O1xuICB9XG4gIHZhciBrZXlMb2NhdGlvbiA9IG9iai5wdXNoID9cbiAgICB7fSA6ICAvLyBibGFuayBvYmplY3QgdGhhdCB3aWxsIGJlIHB1c2hlZFxuICAgIG5lZWRzQmxhbmsgPyBsb2NhdGlvbltvYmoubmFtZV0gOiBsb2NhdGlvbjsgLy8gb3RoZXJ3aXNlLCBuYW1lZCBsb2NhdGlvbiBvciByb290XG5cbiAgYXR0YWNoUHJvcGVydGllcyhjb250ZW50Lm1hdGNoKG9iai5yZWcpLCBrZXlMb2NhdGlvbiwgb2JqLm5hbWVzLCBvYmoubmFtZSk7XG5cbiAgaWYgKG9iai5wdXNoKSB7XG4gICAgbG9jYXRpb25bb2JqLnB1c2hdLnB1c2goa2V5TG9jYXRpb24pO1xuICB9XG59O1xuXG52YXIgZ3JhbW1hciA9IHJlcXVpcmUoJy4vZ3JhbW1hcicpO1xudmFyIHZhbGlkTGluZSA9IFJlZ0V4cC5wcm90b3R5cGUudGVzdC5iaW5kKC9eKFthLXpdKT0oLiopLyk7XG5cbmV4cG9ydHMucGFyc2UgPSBmdW5jdGlvbiAoc2RwKSB7XG4gIHZhciBzZXNzaW9uID0ge31cbiAgICAsIG1lZGlhID0gW11cbiAgICAsIGxvY2F0aW9uID0gc2Vzc2lvbjsgLy8gcG9pbnRzIGF0IHdoZXJlIHByb3BlcnRpZXMgZ28gdW5kZXIgKG9uZSBvZiB0aGUgYWJvdmUpXG5cbiAgLy8gcGFyc2UgbGluZXMgd2UgdW5kZXJzdGFuZFxuICBzZHAuc3BsaXQoLyhcXHJcXG58XFxyfFxcbikvKS5maWx0ZXIodmFsaWRMaW5lKS5mb3JFYWNoKGZ1bmN0aW9uIChsKSB7XG4gICAgdmFyIHR5cGUgPSBsWzBdO1xuICAgIHZhciBjb250ZW50ID0gbC5zbGljZSgyKTtcbiAgICBpZiAodHlwZSA9PT0gJ20nKSB7XG4gICAgICBtZWRpYS5wdXNoKHtydHA6IFtdLCBmbXRwOiBbXX0pO1xuICAgICAgbG9jYXRpb24gPSBtZWRpYVttZWRpYS5sZW5ndGgtMV07IC8vIHBvaW50IGF0IGxhdGVzdCBtZWRpYSBsaW5lXG4gICAgfVxuXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCAoZ3JhbW1hclt0eXBlXSB8fCBbXSkubGVuZ3RoOyBqICs9IDEpIHtcbiAgICAgIHZhciBvYmogPSBncmFtbWFyW3R5cGVdW2pdO1xuICAgICAgaWYgKG9iai5yZWcudGVzdChjb250ZW50KSkge1xuICAgICAgICByZXR1cm4gcGFyc2VSZWcob2JqLCBsb2NhdGlvbiwgY29udGVudCk7XG4gICAgICB9XG4gICAgfVxuICB9KTtcblxuICBzZXNzaW9uLm1lZGlhID0gbWVkaWE7IC8vIGxpbmsgaXQgdXBcbiAgcmV0dXJuIHNlc3Npb247XG59O1xuXG52YXIgZm10cFJlZHVjZXIgPSBmdW5jdGlvbiAoYWNjLCBleHByKSB7XG4gIHZhciBzID0gZXhwci5zcGxpdCgnPScpO1xuICBpZiAocy5sZW5ndGggPT09IDIpIHtcbiAgICBhY2Nbc1swXV0gPSB0b0ludElmSW50KHNbMV0pO1xuICB9XG4gIHJldHVybiBhY2M7XG59O1xuXG5leHBvcnRzLnBhcnNlRm10cENvbmZpZyA9IGZ1bmN0aW9uIChzdHIpIHtcbiAgcmV0dXJuIHN0ci5zcGxpdCgvXFw7XFxzPy8pLnJlZHVjZShmbXRwUmVkdWNlciwge30pO1xufTtcblxuZXhwb3J0cy5wYXJzZVBheWxvYWRzID0gZnVuY3Rpb24gKHN0cikge1xuICByZXR1cm4gc3RyLnNwbGl0KCcgJykubWFwKE51bWJlcik7XG59O1xuXG5leHBvcnRzLnBhcnNlUmVtb3RlQ2FuZGlkYXRlcyA9IGZ1bmN0aW9uIChzdHIpIHtcbiAgdmFyIGNhbmRpZGF0ZXMgPSBbXTtcbiAgdmFyIHBhcnRzID0gc3RyLnNwbGl0KCcgJykubWFwKHRvSW50SWZJbnQpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHBhcnRzLmxlbmd0aDsgaSArPSAzKSB7XG4gICAgY2FuZGlkYXRlcy5wdXNoKHtcbiAgICAgIGNvbXBvbmVudDogcGFydHNbaV0sXG4gICAgICBpcDogcGFydHNbaSArIDFdLFxuICAgICAgcG9ydDogcGFydHNbaSArIDJdXG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIGNhbmRpZGF0ZXM7XG59O1xuIiwidmFyIGdyYW1tYXIgPSByZXF1aXJlKCcuL2dyYW1tYXInKTtcblxuLy8gY3VzdG9taXplZCB1dGlsLmZvcm1hdCAtIGRpc2NhcmRzIGV4Y2VzcyBhcmd1bWVudHMgYW5kIGNhbiB2b2lkIG1pZGRsZSBvbmVzXG52YXIgZm9ybWF0UmVnRXhwID0gLyVbc2R2JV0vZztcbnZhciBmb3JtYXQgPSBmdW5jdGlvbiAoZm9ybWF0U3RyKSB7XG4gIHZhciBpID0gMTtcbiAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gIHZhciBsZW4gPSBhcmdzLmxlbmd0aDtcbiAgcmV0dXJuIGZvcm1hdFN0ci5yZXBsYWNlKGZvcm1hdFJlZ0V4cCwgZnVuY3Rpb24gKHgpIHtcbiAgICBpZiAoaSA+PSBsZW4pIHtcbiAgICAgIHJldHVybiB4OyAvLyBtaXNzaW5nIGFyZ3VtZW50XG4gICAgfVxuICAgIHZhciBhcmcgPSBhcmdzW2ldO1xuICAgIGkgKz0gMTtcbiAgICBzd2l0Y2ggKHgpIHtcbiAgICAgIGNhc2UgJyUlJzpcbiAgICAgICAgcmV0dXJuICclJztcbiAgICAgIGNhc2UgJyVzJzpcbiAgICAgICAgcmV0dXJuIFN0cmluZyhhcmcpO1xuICAgICAgY2FzZSAnJWQnOlxuICAgICAgICByZXR1cm4gTnVtYmVyKGFyZyk7XG4gICAgICBjYXNlICcldic6XG4gICAgICAgIHJldHVybiAnJztcbiAgICB9XG4gIH0pO1xuICAvLyBOQjogd2UgZGlzY2FyZCBleGNlc3MgYXJndW1lbnRzIC0gdGhleSBhcmUgdHlwaWNhbGx5IHVuZGVmaW5lZCBmcm9tIG1ha2VMaW5lXG59O1xuXG52YXIgbWFrZUxpbmUgPSBmdW5jdGlvbiAodHlwZSwgb2JqLCBsb2NhdGlvbikge1xuICB2YXIgc3RyID0gb2JqLmZvcm1hdCBpbnN0YW5jZW9mIEZ1bmN0aW9uID9cbiAgICAob2JqLmZvcm1hdChvYmoucHVzaCA/IGxvY2F0aW9uIDogbG9jYXRpb25bb2JqLm5hbWVdKSkgOlxuICAgIG9iai5mb3JtYXQ7XG5cbiAgdmFyIGFyZ3MgPSBbdHlwZSArICc9JyArIHN0cl07XG4gIGlmIChvYmoubmFtZXMpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iai5uYW1lcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgdmFyIG4gPSBvYmoubmFtZXNbaV07XG4gICAgICBpZiAob2JqLm5hbWUpIHtcbiAgICAgICAgYXJncy5wdXNoKGxvY2F0aW9uW29iai5uYW1lXVtuXSk7XG4gICAgICB9XG4gICAgICBlbHNlIHsgLy8gZm9yIG1MaW5lIGFuZCBwdXNoIGF0dHJpYnV0ZXNcbiAgICAgICAgYXJncy5wdXNoKGxvY2F0aW9uW29iai5uYW1lc1tpXV0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBlbHNlIHtcbiAgICBhcmdzLnB1c2gobG9jYXRpb25bb2JqLm5hbWVdKTtcbiAgfVxuICByZXR1cm4gZm9ybWF0LmFwcGx5KG51bGwsIGFyZ3MpO1xufTtcblxuLy8gUkZDIHNwZWNpZmllZCBvcmRlclxuLy8gVE9ETzogZXh0ZW5kIHRoaXMgd2l0aCBhbGwgdGhlIHJlc3RcbnZhciBkZWZhdWx0T3V0ZXJPcmRlciA9IFtcbiAgJ3YnLCAnbycsICdzJywgJ2knLFxuICAndScsICdlJywgJ3AnLCAnYycsXG4gICdiJywgJ3QnLCAncicsICd6JywgJ2EnXG5dO1xudmFyIGRlZmF1bHRJbm5lck9yZGVyID0gWydpJywgJ2MnLCAnYicsICdhJ107XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoc2Vzc2lvbiwgb3B0cykge1xuICBvcHRzID0gb3B0cyB8fCB7fTtcbiAgLy8gZW5zdXJlIGNlcnRhaW4gcHJvcGVydGllcyBleGlzdFxuICBpZiAoc2Vzc2lvbi52ZXJzaW9uID09IG51bGwpIHtcbiAgICBzZXNzaW9uLnZlcnNpb24gPSAwOyAvLyBcInY9MFwiIG11c3QgYmUgdGhlcmUgKG9ubHkgZGVmaW5lZCB2ZXJzaW9uIGF0bSlcbiAgfVxuICBpZiAoc2Vzc2lvbi5uYW1lID09IG51bGwpIHtcbiAgICBzZXNzaW9uLm5hbWUgPSBcIiBcIjsgLy8gXCJzPSBcIiBtdXN0IGJlIHRoZXJlIGlmIG5vIG1lYW5pbmdmdWwgbmFtZSBzZXRcbiAgfVxuICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24gKG1MaW5lKSB7XG4gICAgaWYgKG1MaW5lLnBheWxvYWRzID09IG51bGwpIHtcbiAgICAgIG1MaW5lLnBheWxvYWRzID0gXCJcIjtcbiAgICB9XG4gIH0pO1xuXG4gIHZhciBvdXRlck9yZGVyID0gb3B0cy5vdXRlck9yZGVyIHx8IGRlZmF1bHRPdXRlck9yZGVyO1xuICB2YXIgaW5uZXJPcmRlciA9IG9wdHMuaW5uZXJPcmRlciB8fCBkZWZhdWx0SW5uZXJPcmRlcjtcbiAgdmFyIHNkcCA9IFtdO1xuXG4gIC8vIGxvb3AgdGhyb3VnaCBvdXRlck9yZGVyIGZvciBtYXRjaGluZyBwcm9wZXJ0aWVzIG9uIHNlc3Npb25cbiAgb3V0ZXJPcmRlci5mb3JFYWNoKGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgZ3JhbW1hclt0eXBlXS5mb3JFYWNoKGZ1bmN0aW9uIChvYmopIHtcbiAgICAgIGlmIChvYmoubmFtZSBpbiBzZXNzaW9uICYmIHNlc3Npb25bb2JqLm5hbWVdICE9IG51bGwpIHtcbiAgICAgICAgc2RwLnB1c2gobWFrZUxpbmUodHlwZSwgb2JqLCBzZXNzaW9uKSk7XG4gICAgICB9XG4gICAgICBlbHNlIGlmIChvYmoucHVzaCBpbiBzZXNzaW9uICYmIHNlc3Npb25bb2JqLnB1c2hdICE9IG51bGwpIHtcbiAgICAgICAgc2Vzc2lvbltvYmoucHVzaF0uZm9yRWFjaChmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICBzZHAucHVzaChtYWtlTGluZSh0eXBlLCBvYmosIGVsKSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICAvLyB0aGVuIGZvciBlYWNoIG1lZGlhIGxpbmUsIGZvbGxvdyB0aGUgaW5uZXJPcmRlclxuICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24gKG1MaW5lKSB7XG4gICAgc2RwLnB1c2gobWFrZUxpbmUoJ20nLCBncmFtbWFyLm1bMF0sIG1MaW5lKSk7XG5cbiAgICBpbm5lck9yZGVyLmZvckVhY2goZnVuY3Rpb24gKHR5cGUpIHtcbiAgICAgIGdyYW1tYXJbdHlwZV0uZm9yRWFjaChmdW5jdGlvbiAob2JqKSB7XG4gICAgICAgIGlmIChvYmoubmFtZSBpbiBtTGluZSAmJiBtTGluZVtvYmoubmFtZV0gIT0gbnVsbCkge1xuICAgICAgICAgIHNkcC5wdXNoKG1ha2VMaW5lKHR5cGUsIG9iaiwgbUxpbmUpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChvYmoucHVzaCBpbiBtTGluZSAmJiBtTGluZVtvYmoucHVzaF0gIT0gbnVsbCkge1xuICAgICAgICAgIG1MaW5lW29iai5wdXNoXS5mb3JFYWNoKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgICAgc2RwLnB1c2gobWFrZUxpbmUodHlwZSwgb2JqLCBlbCkpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgcmV0dXJuIHNkcC5qb2luKCdcXHJcXG4nKSArICdcXHJcXG4nO1xufTtcbiIsIi8qIENvcHlyaWdodCBAIDIwMTUgQXRsYXNzaWFuIFB0eSBMdGRcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBhcnJheUVxdWFscyhhcnJheSkge1xuICAgIC8vIGlmIHRoZSBvdGhlciBhcnJheSBpcyBhIGZhbHN5IHZhbHVlLCByZXR1cm5cbiAgICBpZiAoIWFycmF5KVxuICAgICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICAvLyBjb21wYXJlIGxlbmd0aHMgLSBjYW4gc2F2ZSBhIGxvdCBvZiB0aW1lXG4gICAgaWYgKHRoaXMubGVuZ3RoICE9IGFycmF5Lmxlbmd0aClcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIGwgPSB0aGlzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICAvLyBDaGVjayBpZiB3ZSBoYXZlIG5lc3RlZCBhcnJheXNcbiAgICAgICAgaWYgKHRoaXNbaV0gaW5zdGFuY2VvZiBBcnJheSAmJiBhcnJheVtpXSBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICAgICAgICAvLyByZWN1cnNlIGludG8gdGhlIG5lc3RlZCBhcnJheXNcbiAgICAgICAgICAgIGlmICghYXJyYXlFcXVhbHMuYXBwbHkodGhpc1tpXSwgW2FycmF5W2ldXSkpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXNbaV0gIT0gYXJyYXlbaV0pIHtcbiAgICAgICAgICAgIC8vIFdhcm5pbmcgLSB0d28gZGlmZmVyZW50IG9iamVjdCBpbnN0YW5jZXMgd2lsbCBuZXZlciBiZSBlcXVhbDpcbiAgICAgICAgICAgIC8vIHt4OjIwfSAhPSB7eDoyMH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn07XG5cbiIsIi8qIENvcHlyaWdodCBAIDIwMTUgQXRsYXNzaWFuIFB0eSBMdGRcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuZXhwb3J0cy5JbnRlcm9wID0gcmVxdWlyZSgnLi9pbnRlcm9wJyk7XG4iLCIvKiBDb3B5cmlnaHQgQCAyMDE1IEF0bGFzc2lhbiBQdHkgTHRkXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qIGdsb2JhbCBSVENTZXNzaW9uRGVzY3JpcHRpb24gKi9cbi8qIGdsb2JhbCBSVENJY2VDYW5kaWRhdGUgKi9cbi8qIGpzaGludCAtVzA5NyAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciB0cmFuc2Zvcm0gPSByZXF1aXJlKCcuL3RyYW5zZm9ybScpO1xudmFyIGFycmF5RXF1YWxzID0gcmVxdWlyZSgnLi9hcnJheS1lcXVhbHMnKTtcblxuZnVuY3Rpb24gSW50ZXJvcCgpIHtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWFwIGhvbGRzIHRoZSBtb3N0IHJlY2VudCBVbmlmaWVkIFBsYW4gb2ZmZXIvYW5zd2VyIFNEUCB0aGF0IHdhc1xuICAgICAqIGNvbnZlcnRlZCB0byBQbGFuIEIsIHdpdGggdGhlIFNEUCB0eXBlICgnb2ZmZXInIG9yICdhbnN3ZXInKSBhcyBrZXlzIGFuZFxuICAgICAqIHRoZSBTRFAgc3RyaW5nIGFzIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEB0eXBlIHt7fX1cbiAgICAgKi9cbiAgICB0aGlzLmNhY2hlID0ge1xuICAgICAgICBtbEIyVU1hcCA6IHt9LFxuICAgICAgICBtbFUyQk1hcCA6IHt9XG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBJbnRlcm9wO1xuXG4vKipcbiAqIENoYW5nZXMgdGhlIGNhbmRpZGF0ZSBhcmdzIHRvIG1hdGNoIHdpdGggdGhlIHJlbGF0ZWQgVW5pZmllZCBQbGFuXG4gKi9cbkludGVyb3AucHJvdG90eXBlLmNhbmRpZGF0ZVRvVW5pZmllZFBsYW4gPSBmdW5jdGlvbihjYW5kaWRhdGUpIHtcbiAgICB2YXIgY2FuZCA9IG5ldyBSVENJY2VDYW5kaWRhdGUoY2FuZGlkYXRlKTtcblxuICAgIGNhbmQuc2RwTUxpbmVJbmRleCA9IHRoaXMuY2FjaGUubWxCMlVNYXBbY2FuZC5zZHBNTGluZUluZGV4XTtcbiAgICAvKiBUT0RPOiBjaGFuZ2Ugc2RwTWlkIHRvIChhdWRpb3x2aWRlbyktU1NSQyAqL1xuXG4gICAgcmV0dXJuIGNhbmQ7XG59O1xuXG4vKipcbiAqIENoYW5nZXMgdGhlIGNhbmRpZGF0ZSBhcmdzIHRvIG1hdGNoIHdpdGggdGhlIHJlbGF0ZWQgUGxhbiBCXG4gKi9cbkludGVyb3AucHJvdG90eXBlLmNhbmRpZGF0ZVRvUGxhbkIgPSBmdW5jdGlvbihjYW5kaWRhdGUpIHtcbiAgICB2YXIgY2FuZCA9IG5ldyBSVENJY2VDYW5kaWRhdGUoY2FuZGlkYXRlKTtcblxuICAgIGlmIChjYW5kLnNkcE1pZC5pbmRleE9mKCdhdWRpbycpID09PSAwKSB7XG4gICAgICBjYW5kLnNkcE1pZCA9ICdhdWRpbyc7XG4gICAgfSBlbHNlIGlmIChjYW5kLnNkcE1pZC5pbmRleE9mKCd2aWRlbycpID09PSAwKSB7XG4gICAgICBjYW5kLnNkcE1pZCA9ICd2aWRlbyc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY2FuZGlkYXRlIHdpdGggJyArIGNhbmQuc2RwTWlkICsgJyBub3QgYWxsb3dlZCcpO1xuICAgIH1cblxuICAgIGNhbmQuc2RwTUxpbmVJbmRleCA9IHRoaXMuY2FjaGUubWxVMkJNYXBbY2FuZC5zZHBNTGluZUluZGV4XTtcblxuICAgIHJldHVybiBjYW5kO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgZmlyc3QgbS1saW5lIHdpdGggdGhlIGdpdmVuIG1lZGlhIHR5cGUgYW5kIHdpdGggYVxuICogZGlyZWN0aW9uIHdoaWNoIGFsbG93cyBzZW5kaW5nLCBpbiB0aGUgbGFzdCBVbmlmaWVkIFBsYW4gZGVzY3JpcHRpb24gd2l0aFxuICogdHlwZSBcImFuc3dlclwiIGNvbnZlcnRlZCB0byBQbGFuIEIuIFJldHVybnMge251bGx9IGlmIHRoZXJlIGlzIG5vIHNhdmVkXG4gKiBhbnN3ZXIsIG9yIGlmIG5vbmUgb2YgaXRzIG0tbGluZXMgd2l0aCB0aGUgZ2l2ZW4gdHlwZSBhbGxvdyBzZW5kaW5nLlxuICogQHBhcmFtIHR5cGUgdGhlIG1lZGlhIHR5cGUgKFwiYXVkaW9cIiBvciBcInZpZGVvXCIpLlxuICogQHJldHVybnMgeyp9XG4gKi9cbkludGVyb3AucHJvdG90eXBlLmdldEZpcnN0U2VuZGluZ0luZGV4RnJvbUFuc3dlciA9IGZ1bmN0aW9uKHR5cGUpIHtcbiAgICBpZiAoIXRoaXMuY2FjaGUuYW5zd2VyKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHZhciBzZXNzaW9uID0gdHJhbnNmb3JtLnBhcnNlKHRoaXMuY2FjaGUuYW5zd2VyKTtcbiAgICBpZiAoc2Vzc2lvbiAmJiBzZXNzaW9uLm1lZGlhICYmIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkpe1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNlc3Npb24ubWVkaWEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChzZXNzaW9uLm1lZGlhW2ldLnR5cGUgPT0gdHlwZSAmJlxuICAgICAgICAgICAgICAgICghc2Vzc2lvbi5tZWRpYVtpXS5kaXJlY3Rpb24gLyogZGVmYXVsdCB0byBzZW5kcmVjdiAqLyB8fFxuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLm1lZGlhW2ldLmRpcmVjdGlvbiA9PT0gJ3NlbmRyZWN2JyB8fFxuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLm1lZGlhW2ldLmRpcmVjdGlvbiA9PT0gJ3NlbmRvbmx5Jykpe1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG59O1xuXG4vKipcbiAqIFRoaXMgbWV0aG9kIHRyYW5zZm9ybXMgYSBVbmlmaWVkIFBsYW4gU0RQIHRvIGFuIGVxdWl2YWxlbnQgUGxhbiBCIFNEUC4gQVxuICogUGVlckNvbm5lY3Rpb24gd3JhcHBlciB0cmFuc2Zvcm1zIHRoZSBTRFAgdG8gUGxhbiBCIGJlZm9yZSBwYXNzaW5nIGl0IHRvIHRoZVxuICogYXBwbGljYXRpb24uXG4gKlxuICogQHBhcmFtIGRlc2NcbiAqIEByZXR1cm5zIHsqfVxuICovXG5JbnRlcm9wLnByb3RvdHlwZS50b1BsYW5CID0gZnVuY3Rpb24oZGVzYykge1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAvLyNyZWdpb24gUHJlbGltaW5hcnkgaW5wdXQgdmFsaWRhdGlvbi5cblxuICAgIGlmICh0eXBlb2YgZGVzYyAhPT0gJ29iamVjdCcgfHwgZGVzYyA9PT0gbnVsbCB8fFxuICAgICAgICB0eXBlb2YgZGVzYy5zZHAgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignQW4gZW1wdHkgZGVzY3JpcHRpb24gd2FzIHBhc3NlZCBhcyBhbiBhcmd1bWVudC4nKTtcbiAgICAgICAgcmV0dXJuIGRlc2M7XG4gICAgfVxuXG4gICAgLy8gT2JqZWN0aWZ5IHRoZSBTRFAgZm9yIGVhc2llciBtYW5pcHVsYXRpb24uXG4gICAgdmFyIHNlc3Npb24gPSB0cmFuc2Zvcm0ucGFyc2UoZGVzYy5zZHApO1xuXG4gICAgLy8gSWYgdGhlIFNEUCBjb250YWlucyBubyBtZWRpYSwgdGhlcmUncyBub3RoaW5nIHRvIHRyYW5zZm9ybS5cbiAgICBpZiAodHlwZW9mIHNlc3Npb24ubWVkaWEgPT09ICd1bmRlZmluZWQnIHx8XG4gICAgICAgICFBcnJheS5pc0FycmF5KHNlc3Npb24ubWVkaWEpIHx8IHNlc3Npb24ubWVkaWEubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignVGhlIGRlc2NyaXB0aW9uIGhhcyBubyBtZWRpYS4nKTtcbiAgICAgICAgcmV0dXJuIGRlc2M7XG4gICAgfVxuXG4gICAgLy8gVHJ5IHNvbWUgaGV1cmlzdGljcyB0byBcIm1ha2Ugc3VyZVwiIHRoaXMgaXMgYSBVbmlmaWVkIFBsYW4gU0RQLiBQbGFuIEJcbiAgICAvLyBTRFAgaGFzIGEgdmlkZW8sIGFuIGF1ZGlvIGFuZCBhIGRhdGEgXCJjaGFubmVsXCIgYXQgbW9zdC5cbiAgICBpZiAoc2Vzc2lvbi5tZWRpYS5sZW5ndGggPD0gMyAmJiBzZXNzaW9uLm1lZGlhLmV2ZXJ5KGZ1bmN0aW9uKG0pIHtcbiAgICAgICAgICAgIHJldHVybiBbJ3ZpZGVvJywgJ2F1ZGlvJywgJ2RhdGEnXS5pbmRleE9mKG0ubWlkKSAhPT0gLTE7XG4gICAgICAgIH0pKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignVGhpcyBkZXNjcmlwdGlvbiBkb2VzIG5vdCBsb29rIGxpa2UgVW5pZmllZCBQbGFuLicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICAvLyNlbmRyZWdpb25cblxuICAgIC8vIEhBQ0sgaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTExMzQ0M1xuICAgIHZhciBzZHAgPSBkZXNjLnNkcDtcbiAgICB2YXIgcmV3cml0ZSA9IGZhbHNlO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2Vzc2lvbi5tZWRpYS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdUxpbmUgPSBzZXNzaW9uLm1lZGlhW2ldO1xuICAgICAgICB1TGluZS5ydHAuZm9yRWFjaChmdW5jdGlvbihydHApIHtcbiAgICAgICAgICAgIGlmIChydHAuY29kZWMgPT09ICdOVUxMJylcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICByZXdyaXRlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB2YXIgb2ZmZXIgPSB0cmFuc2Zvcm0ucGFyc2Uoc2VsZi5jYWNoZS5vZmZlcik7XG4gICAgICAgICAgICAgICAgcnRwLmNvZGVjID0gb2ZmZXIubWVkaWFbaV0ucnRwWzBdLmNvZGVjO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgaWYgKHJld3JpdGUpIHtcbiAgICAgICAgc2RwID0gdHJhbnNmb3JtLndyaXRlKHNlc3Npb24pO1xuICAgIH1cblxuICAgIC8vIFVuaWZpZWQgUGxhbiBTRFAgaXMgb3VyIFwicHJlY2lvdXNcIi4gQ2FjaGUgaXQgZm9yIGxhdGVyIHVzZSBpbiB0aGUgUGxhbiBCXG4gICAgLy8gLT4gVW5pZmllZCBQbGFuIHRyYW5zZm9ybWF0aW9uLlxuICAgIHRoaXMuY2FjaGVbZGVzYy50eXBlXSA9IHNkcDtcblxuICAgIC8vI3JlZ2lvbiBDb252ZXJ0IGZyb20gVW5pZmllZCBQbGFuIHRvIFBsYW4gQi5cblxuICAgIC8vIFdlIHJlYnVpbGQgdGhlIHNlc3Npb24ubWVkaWEgYXJyYXkuXG4gICAgdmFyIG1lZGlhID0gc2Vzc2lvbi5tZWRpYTtcbiAgICBzZXNzaW9uLm1lZGlhID0gW107XG5cbiAgICAvLyBBc3NvY2lhdGl2ZSBhcnJheSB0aGF0IG1hcHMgY2hhbm5lbCB0eXBlcyB0byBjaGFubmVsIG9iamVjdHMgZm9yIGZhc3RcbiAgICAvLyBhY2Nlc3MgdG8gY2hhbm5lbCBvYmplY3RzIGJ5IHRoZWlyIHR5cGUsIGUuZy4gdHlwZTJibFsnYXVkaW8nXS0+Y2hhbm5lbFxuICAgIC8vIG9iai5cbiAgICB2YXIgdHlwZTJibCA9IHt9O1xuXG4gICAgLy8gVXNlZCB0byBidWlsZCB0aGUgZ3JvdXA6QlVORExFIHZhbHVlIGFmdGVyIHRoZSBjaGFubmVscyBjb25zdHJ1Y3Rpb25cbiAgICAvLyBsb29wLlxuICAgIHZhciB0eXBlcyA9IFtdO1xuXG4gICAgbWVkaWEuZm9yRWFjaChmdW5jdGlvbih1TGluZSkge1xuICAgICAgICAvLyBydGNwLW11eCBpcyByZXF1aXJlZCBpbiB0aGUgUGxhbiBCIFNEUC5cbiAgICAgICAgaWYgKCh0eXBlb2YgdUxpbmUucnRjcE11eCAhPT0gJ3N0cmluZycgfHxcbiAgICAgICAgICAgIHVMaW5lLnJ0Y3BNdXggIT09ICdydGNwLW11eCcpICYmXG4gICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gIT09ICdpbmFjdGl2ZScpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGNvbnZlcnQgdG8gUGxhbiBCIGJlY2F1c2UgbS1saW5lcyAnICtcbiAgICAgICAgICAgICAgICAnd2l0aG91dCB0aGUgcnRjcC1tdXggYXR0cmlidXRlIHdlcmUgZm91bmQuJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB3ZSBkb24ndCBoYXZlIGEgY2hhbm5lbCBmb3IgdGhpcyB1TGluZS50eXBlIE9SIHRoZSBzZWxlY3RlZCBpc1xuICAgICAgICAvLyBpbmFjdGl2ZSwgdGhlbiBzZWxlY3QgdGhpcyB1TGluZSBhcyB0aGUgY2hhbm5lbCBiYXNpcy5cbiAgICAgICAgaWYgKHR5cGVvZiB0eXBlMmJsW3VMaW5lLnR5cGVdID09PSAndW5kZWZpbmVkJyB8fFxuICAgICAgICAgICAgdHlwZTJibFt1TGluZS50eXBlXS5kaXJlY3Rpb24gPT09ICdpbmFjdGl2ZScpIHtcbiAgICAgICAgICAgIHR5cGUyYmxbdUxpbmUudHlwZV0gPSB1TGluZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh1TGluZS5wcm90b2NvbCAhPSB0eXBlMmJsW3VMaW5lLnR5cGVdLnByb3RvY29sKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgY29udmVydCB0byBQbGFuIEIgYmVjYXVzZSBtLWxpbmVzICcgK1xuICAgICAgICAgICAgICAnaGF2ZSBkaWZmZXJlbnQgcHJvdG9jb2xzIGFuZCB0aGlzIGxpYnJhcnkgZG9lcyBub3QgaGF2ZSAnICtcbiAgICAgICAgICAgICAgJ3N1cHBvcnQgZm9yIHRoYXQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh1TGluZS5wYXlsb2FkcyAhPSB0eXBlMmJsW3VMaW5lLnR5cGVdLnBheWxvYWRzKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgY29udmVydCB0byBQbGFuIEIgYmVjYXVzZSBtLWxpbmVzICcgK1xuICAgICAgICAgICAgICAnaGF2ZSBkaWZmZXJlbnQgcGF5bG9hZHMgYW5kIHRoaXMgbGlicmFyeSBkb2VzIG5vdCBoYXZlICcgK1xuICAgICAgICAgICAgICAnc3VwcG9ydCBmb3IgdGhhdCcpO1xuICAgICAgICB9XG5cbiAgICB9KTtcblxuICAgIC8vIEltcGxvZGUgdGhlIFVuaWZpZWQgUGxhbiBtLWxpbmVzL3RyYWNrcyBpbnRvIFBsYW4gQiBjaGFubmVscy5cbiAgICBtZWRpYS5mb3JFYWNoKGZ1bmN0aW9uKHVMaW5lKSB7XG4gICAgICAgIGlmICh1TGluZS50eXBlID09PSAnYXBwbGljYXRpb24nKSB7XG4gICAgICAgICAgICBzZXNzaW9uLm1lZGlhLnB1c2godUxpbmUpO1xuICAgICAgICAgICAgdHlwZXMucHVzaCh1TGluZS5taWQpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkIHNvdXJjZXMgdG8gdGhlIGNoYW5uZWwgYW5kIGhhbmRsZSBhPW1zaWQuXG4gICAgICAgIGlmICh0eXBlb2YgdUxpbmUuc291cmNlcyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHVMaW5lLnNvdXJjZXMpLmZvckVhY2goZnVuY3Rpb24oc3NyYykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdHlwZTJibFt1TGluZS50eXBlXS5zb3VyY2VzICE9PSAnb2JqZWN0JylcbiAgICAgICAgICAgICAgICAgICAgdHlwZTJibFt1TGluZS50eXBlXS5zb3VyY2VzID0ge307XG5cbiAgICAgICAgICAgICAgICAvLyBBc3NpZ24gdGhlIHNvdXJjZXMgdG8gdGhlIGNoYW5uZWwuXG4gICAgICAgICAgICAgICAgdHlwZTJibFt1TGluZS50eXBlXS5zb3VyY2VzW3NzcmNdID1cbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuc291cmNlc1tzc3JjXTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdUxpbmUubXNpZCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSW4gUGxhbiBCIHRoZSBtc2lkIGlzIGFuIFNTUkMgYXR0cmlidXRlLiBBbHNvLCB3ZSBkb24ndFxuICAgICAgICAgICAgICAgICAgICAvLyBjYXJlIGFib3V0IHRoZSBvYnNvbGV0ZSBsYWJlbCBhbmQgbXNsYWJlbCBhdHRyaWJ1dGVzLlxuICAgICAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgICAgICAvLyBOb3RlIHRoYXQgaXQgaXMgbm90IGd1YXJhbnRlZWQgdGhhdCB0aGUgdUxpbmUgd2lsbFxuICAgICAgICAgICAgICAgICAgICAvLyBoYXZlIGFuIG1zaWQuIHJlY3Zvbmx5IGNoYW5uZWxzIGluIHBhcnRpY3VsYXIgZG9uJ3QgaGF2ZVxuICAgICAgICAgICAgICAgICAgICAvLyBvbmUuXG4gICAgICAgICAgICAgICAgICAgIHR5cGUyYmxbdUxpbmUudHlwZV0uc291cmNlc1tzc3JjXS5tc2lkID1cbiAgICAgICAgICAgICAgICAgICAgICAgIHVMaW5lLm1zaWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIE5PVEUgc3NyY3MgaW4gc3NyYyBncm91cHMgd2lsbCBzaGFyZSBtc2lkcywgYXNcbiAgICAgICAgICAgICAgICAvLyBkcmFmdC11YmVydGktcnRjd2ViLXBsYW4tMDAgbWFuZGF0ZXMuXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEFkZCBzc3JjIGdyb3VwcyB0byB0aGUgY2hhbm5lbC5cbiAgICAgICAgaWYgKHR5cGVvZiB1TGluZS5zc3JjR3JvdXBzICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgICAgIEFycmF5LmlzQXJyYXkodUxpbmUuc3NyY0dyb3VwcykpIHtcblxuICAgICAgICAgICAgLy8gQ3JlYXRlIHRoZSBzc3JjR3JvdXBzIGFycmF5LCBpZiBpdCdzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgICAgaWYgKHR5cGVvZiB0eXBlMmJsW3VMaW5lLnR5cGVdLnNzcmNHcm91cHMgPT09ICd1bmRlZmluZWQnIHx8XG4gICAgICAgICAgICAgICAgICAgICFBcnJheS5pc0FycmF5KHR5cGUyYmxbdUxpbmUudHlwZV0uc3NyY0dyb3VwcykpIHtcbiAgICAgICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLnNzcmNHcm91cHMgPSBbXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdHlwZTJibFt1TGluZS50eXBlXS5zc3JjR3JvdXBzID1cbiAgICAgICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLnNzcmNHcm91cHMuY29uY2F0KFxuICAgICAgICAgICAgICAgICAgICB1TGluZS5zc3JjR3JvdXBzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlMmJsW3VMaW5lLnR5cGVdID09PSB1TGluZSkge1xuICAgICAgICAgICAgLy8gUGxhbiBCIG1pZHMgYXJlIGluIFsnYXVkaW8nLCAndmlkZW8nLCAnZGF0YSddXG4gICAgICAgICAgICB1TGluZS5taWQgPSB1TGluZS50eXBlO1xuXG4gICAgICAgICAgICAvLyBQbGFuIEIgZG9lc24ndCBzdXBwb3J0L25lZWQgdGhlIGJ1bmRsZS1vbmx5IGF0dHJpYnV0ZS5cbiAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5idW5kbGVPbmx5O1xuXG4gICAgICAgICAgICAvLyBJbiBQbGFuIEIgdGhlIG1zaWQgaXMgYW4gU1NSQyBhdHRyaWJ1dGUuXG4gICAgICAgICAgICBkZWxldGUgdUxpbmUubXNpZDtcblxuXHQgICAgaWYgKHVMaW5lLnR5cGUgPT0gbWVkaWFbMF0udHlwZSkge1xuXHQgICAgICB0eXBlcy51bnNoaWZ0KHVMaW5lLnR5cGUpO1xuXHQgICAgICAvLyBBZGQgdGhlIGNoYW5uZWwgdG8gdGhlIG5ldyBtZWRpYSBhcnJheS5cblx0ICAgICAgc2Vzc2lvbi5tZWRpYS51bnNoaWZ0KHVMaW5lKTtcblx0ICAgIH0gZWxzZSB7XG5cdCAgICAgIHR5cGVzLnB1c2godUxpbmUudHlwZSk7XG5cdCAgICAgIC8vIEFkZCB0aGUgY2hhbm5lbCB0byB0aGUgbmV3IG1lZGlhIGFycmF5LlxuXHQgICAgICBzZXNzaW9uLm1lZGlhLnB1c2godUxpbmUpO1xuXHQgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICBpZiAodHlwZW9mIHNlc3Npb24uZ3JvdXBzICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgLy8gV2UgcmVnZW5lcmF0ZSB0aGUgQlVORExFIGdyb3VwIHdpdGggdGhlIG5ldyBtaWRzLlxuICAgICAgc2Vzc2lvbi5ncm91cHMuc29tZShmdW5jdGlvbihncm91cCkge1xuXHQgIGlmIChncm91cC50eXBlID09PSAnQlVORExFJykge1xuXHQgICAgICBncm91cC5taWRzID0gdHlwZXMuam9pbignICcpO1xuXHQgICAgICByZXR1cm4gdHJ1ZTtcblx0ICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBtc2lkIHNlbWFudGljXG4gICAgc2Vzc2lvbi5tc2lkU2VtYW50aWMgPSB7XG4gICAgICAgIHNlbWFudGljOiAnV01TJyxcbiAgICAgICAgdG9rZW46ICcqJ1xuICAgIH07XG5cbiAgICB2YXIgcmVzU3RyID0gdHJhbnNmb3JtLndyaXRlKHNlc3Npb24pO1xuXG4gICAgcmV0dXJuIG5ldyBSVENTZXNzaW9uRGVzY3JpcHRpb24oe1xuICAgICAgICB0eXBlOiBkZXNjLnR5cGUsXG4gICAgICAgIHNkcDogcmVzU3RyXG4gICAgfSk7XG5cbiAgICAvLyNlbmRyZWdpb25cbn07XG5cbi8qIGZvbGxvdyBydWxlcyBkZWZpbmVkIGluIFJGQzQxNDUgKi9cbmZ1bmN0aW9uIGFkZFNldHVwQXR0cih1TGluZSkge1xuICAgIGlmICh0eXBlb2YgdUxpbmUuc2V0dXAgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodUxpbmUuc2V0dXAgPT09IFwiYWN0aXZlXCIpIHtcbiAgICAgICAgICAgIHVMaW5lLnNldHVwID0gXCJwYXNzaXZlXCI7XG4gICAgfSBlbHNlIGlmICh1TGluZS5zZXR1cCA9PT0gXCJwYXNzaXZlXCIpIHtcbiAgICAgICAgdUxpbmUuc2V0dXAgPSBcImFjdGl2ZVwiO1xuICAgIH1cbn1cblxuLyoqXG4gKiBUaGlzIG1ldGhvZCB0cmFuc2Zvcm1zIGEgUGxhbiBCIFNEUCB0byBhbiBlcXVpdmFsZW50IFVuaWZpZWQgUGxhbiBTRFAuIEFcbiAqIFBlZXJDb25uZWN0aW9uIHdyYXBwZXIgdHJhbnNmb3JtcyB0aGUgU0RQIHRvIFVuaWZpZWQgUGxhbiBiZWZvcmUgcGFzc2luZyBpdFxuICogdG8gRkYuXG4gKlxuICogQHBhcmFtIGRlc2NcbiAqIEByZXR1cm5zIHsqfVxuICovXG5JbnRlcm9wLnByb3RvdHlwZS50b1VuaWZpZWRQbGFuID0gZnVuY3Rpb24oZGVzYykge1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAvLyNyZWdpb24gUHJlbGltaW5hcnkgaW5wdXQgdmFsaWRhdGlvbi5cblxuICAgIGlmICh0eXBlb2YgZGVzYyAhPT0gJ29iamVjdCcgfHwgZGVzYyA9PT0gbnVsbCB8fFxuICAgICAgICB0eXBlb2YgZGVzYy5zZHAgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignQW4gZW1wdHkgZGVzY3JpcHRpb24gd2FzIHBhc3NlZCBhcyBhbiBhcmd1bWVudC4nKTtcbiAgICAgICAgcmV0dXJuIGRlc2M7XG4gICAgfVxuXG4gICAgdmFyIHNlc3Npb24gPSB0cmFuc2Zvcm0ucGFyc2UoZGVzYy5zZHApO1xuXG4gICAgLy8gSWYgdGhlIFNEUCBjb250YWlucyBubyBtZWRpYSwgdGhlcmUncyBub3RoaW5nIHRvIHRyYW5zZm9ybS5cbiAgICBpZiAodHlwZW9mIHNlc3Npb24ubWVkaWEgPT09ICd1bmRlZmluZWQnIHx8XG4gICAgICAgICFBcnJheS5pc0FycmF5KHNlc3Npb24ubWVkaWEpIHx8IHNlc3Npb24ubWVkaWEubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignVGhlIGRlc2NyaXB0aW9uIGhhcyBubyBtZWRpYS4nKTtcbiAgICAgICAgcmV0dXJuIGRlc2M7XG4gICAgfVxuXG4gICAgLy8gVHJ5IHNvbWUgaGV1cmlzdGljcyB0byBcIm1ha2Ugc3VyZVwiIHRoaXMgaXMgYSBQbGFuIEIgU0RQLiBQbGFuIEIgU0RQIGhhc1xuICAgIC8vIGEgdmlkZW8sIGFuIGF1ZGlvIGFuZCBhIGRhdGEgXCJjaGFubmVsXCIgYXQgbW9zdC5cbiAgICBpZiAoc2Vzc2lvbi5tZWRpYS5sZW5ndGggPiAzIHx8ICFzZXNzaW9uLm1lZGlhLmV2ZXJ5KGZ1bmN0aW9uKG0pIHtcbiAgICAgICAgICAgIHJldHVybiBbJ3ZpZGVvJywgJ2F1ZGlvJywgJ2RhdGEnXS5pbmRleE9mKG0ubWlkKSAhPT0gLTE7XG4gICAgICAgIH0pKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignVGhpcyBkZXNjcmlwdGlvbiBkb2VzIG5vdCBsb29rIGxpa2UgUGxhbiBCLicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICAvLyBNYWtlIHN1cmUgdGhpcyBQbGFuIEIgU0RQIGNhbiBiZSBjb252ZXJ0ZWQgdG8gYSBVbmlmaWVkIFBsYW4gU0RQLlxuICAgIHZhciBtaWRzID0gW107XG4gICAgc2Vzc2lvbi5tZWRpYS5mb3JFYWNoKGZ1bmN0aW9uKG0pIHtcbiAgICAgICAgbWlkcy5wdXNoKG0ubWlkKTtcbiAgICB9KTtcblxuICAgIHZhciBoYXNCdW5kbGUgPSBmYWxzZTtcbiAgICBpZiAodHlwZW9mIHNlc3Npb24uZ3JvdXBzICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICBBcnJheS5pc0FycmF5KHNlc3Npb24uZ3JvdXBzKSkge1xuICAgICAgICBoYXNCdW5kbGUgPSBzZXNzaW9uLmdyb3Vwcy5ldmVyeShmdW5jdGlvbihnKSB7XG4gICAgICAgICAgICByZXR1cm4gZy50eXBlICE9PSAnQlVORExFJyB8fFxuICAgICAgICAgICAgICAgIGFycmF5RXF1YWxzLmFwcGx5KGcubWlkcy5zb3J0KCksIFttaWRzLnNvcnQoKV0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAoIWhhc0J1bmRsZSkge1xuICAgICAgICB2YXIgbXVzdEJlQnVuZGxlID0gZmFsc2U7XG5cbiAgICAgICAgc2Vzc2lvbi5tZWRpYS5mb3JFYWNoKGZ1bmN0aW9uKG0pIHtcbiAgICAgICAgICAgIGlmIChtLmRpcmVjdGlvbiAhPT0gJ2luYWN0aXZlJykge1xuICAgICAgICAgICAgICAgIG11c3RCZUJ1bmRsZSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChtdXN0QmVCdW5kbGUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBjb252ZXJ0IHRvIFVuaWZpZWQgUGxhbiBiZWNhdXNlIG0tbGluZXMgdGhhdFwiICtcbiAgICAgICAgICAgICAgXCIgYXJlIG5vdCBidW5kbGVkIHdlcmUgZm91bmQuXCIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8jZW5kcmVnaW9uXG5cblxuICAgIC8vI3JlZ2lvbiBDb252ZXJ0IGZyb20gUGxhbiBCIHRvIFVuaWZpZWQgUGxhbi5cblxuICAgIC8vIFVuZm9ydHVuYXRlbHksIGEgUGxhbiBCIG9mZmVyL2Fuc3dlciBkb2Vzbid0IGhhdmUgZW5vdWdoIGluZm9ybWF0aW9uIHRvXG4gICAgLy8gcmVidWlsZCBhbiBlcXVpdmFsZW50IFVuaWZpZWQgUGxhbiBvZmZlci9hbnN3ZXIuXG4gICAgLy9cbiAgICAvLyBGb3IgZXhhbXBsZSwgaWYgdGhpcyBpcyBhIGxvY2FsIGFuc3dlciAoaW4gVW5pZmllZCBQbGFuIHN0eWxlKSB0aGF0IHdlXG4gICAgLy8gY29udmVydCB0byBQbGFuIEIgcHJpb3IgdG8gaGFuZGluZyBpdCBvdmVyIHRvIHRoZSBhcHBsaWNhdGlvbiAodGhlXG4gICAgLy8gUGVlckNvbm5lY3Rpb24gd3JhcHBlciBjYWxsZWQgdXMsIGZvciBpbnN0YW5jZSwgYWZ0ZXIgYSBzdWNjZXNzZnVsXG4gICAgLy8gY3JlYXRlQW5zd2VyKSwgd2Ugd2FudCB0byByZW1lbWJlciB0aGUgbS1saW5lIGF0IHdoaWNoIHdlJ3ZlIHNlZW4gdGhlXG4gICAgLy8gKGxvY2FsKSBTU1JDLiBUaGF0J3MgYmVjYXVzZSB3aGVuIHRoZSBhcHBsaWNhdGlvbiB3YW50cyB0byBkbyBjYWxsIHRoZVxuICAgIC8vIFNMRCBtZXRob2QsIGZvcmNpbmcgdXMgdG8gZG8gdGhlIGludmVyc2UgdHJhbnNmb3JtYXRpb24gKGZyb20gUGxhbiBCIHRvXG4gICAgLy8gVW5pZmllZCBQbGFuKSwgd2UgbmVlZCB0byBrbm93IHRvIHdoaWNoIG0tbGluZSB0byBhc3NpZ24gdGhlIChsb2NhbClcbiAgICAvLyBTU1JDLiBXZSBhbHNvIG5lZWQgdG8ga25vdyBhbGwgdGhlIG90aGVyIG0tbGluZXMgdGhhdCB0aGUgb3JpZ2luYWxcbiAgICAvLyBhbnN3ZXIgaGFkIGFuZCBpbmNsdWRlIHRoZW0gaW4gdGhlIHRyYW5zZm9ybWVkIGFuc3dlciBhcyB3ZWxsLlxuICAgIC8vXG4gICAgLy8gQW5vdGhlciBleGFtcGxlIGlzIGlmIHRoaXMgaXMgYSByZW1vdGUgb2ZmZXIgdGhhdCB3ZSBjb252ZXJ0IHRvIFBsYW4gQlxuICAgIC8vIHByaW9yIHRvIGdpdmluZyBpdCB0byB0aGUgYXBwbGljYXRpb24sIHdlIHdhbnQgdG8gcmVtZW1iZXIgdGhlIG1pZCBhdFxuICAgIC8vIHdoaWNoIHdlJ3ZlIHNlZW4gdGhlIChyZW1vdGUpIFNTUkMuXG4gICAgLy9cbiAgICAvLyBJbiB0aGUgaXRlcmF0aW9uIHRoYXQgZm9sbG93cywgd2UgdXNlIHRoZSBjYWNoZWQgVW5pZmllZCBQbGFuIChpZiBpdFxuICAgIC8vIGV4aXN0cykgdG8gYXNzaWduIG1pZHMgdG8gc3NyY3MuXG5cbiAgICB2YXIgdHlwZTtcbiAgICBpZiAoZGVzYy50eXBlID09PSAnYW5zd2VyJykge1xuICAgICAgICB0eXBlID0gJ29mZmVyJztcbiAgICB9IGVsc2UgaWYgKGRlc2MudHlwZSA9PT0gJ29mZmVyJykge1xuICAgICAgICB0eXBlID0gJ2Fuc3dlcic7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVHlwZSAnXCIgKyBkZXNjLnR5cGUgKyBcIicgbm90IHN1cHBvcnRlZC5cIik7XG4gICAgfVxuXG4gICAgdmFyIGNhY2hlZDtcbiAgICBpZiAodHlwZW9mIHRoaXMuY2FjaGVbdHlwZV0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGNhY2hlZCA9IHRyYW5zZm9ybS5wYXJzZSh0aGlzLmNhY2hlW3R5cGVdKTtcbiAgICB9XG5cbiAgICB2YXIgcmVjdm9ubHlTc3JjcyA9IHtcbiAgICAgICAgYXVkaW86IHt9LFxuICAgICAgICB2aWRlbzoge31cbiAgICB9O1xuXG4gICAgLy8gQSBoZWxwZXIgbWFwIHRoYXQgc2VuZHMgbWlkcyB0byBtLWxpbmUgb2JqZWN0cy4gV2UgdXNlIGl0IGxhdGVyIHRvXG4gICAgLy8gcmVidWlsZCB0aGUgVW5pZmllZCBQbGFuIHN0eWxlIHNlc3Npb24ubWVkaWEgYXJyYXkuXG4gICAgdmFyIG1pZDJ1bCA9IHt9O1xuICAgIHZhciBiSWR4ID0gMDtcbiAgICB2YXIgdUlkeCA9IDA7XG5cbiAgICB2YXIgc291cmNlczJ1bCA9IHt9O1xuXG4gICAgdmFyIGNhbmRpZGF0ZXM7XG4gICAgdmFyIGljZVVmcmFnO1xuICAgIHZhciBpY2VQd2Q7XG4gICAgdmFyIGZpbmdlcnByaW50O1xuICAgIHZhciBwYXlsb2FkcyA9IHt9O1xuICAgIHZhciBydGNwRmIgPSB7fTtcbiAgICB2YXIgcnRwID0ge307XG5cbiAgICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24oYkxpbmUpIHtcbiAgICAgICAgaWYgKCh0eXBlb2YgYkxpbmUucnRjcE11eCAhPT0gJ3N0cmluZycgfHxcbiAgICAgICAgICAgIGJMaW5lLnJ0Y3BNdXggIT09ICdydGNwLW11eCcpICYmXG4gICAgICAgICAgICBiTGluZS5kaXJlY3Rpb24gIT09ICdpbmFjdGl2ZScpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBjb252ZXJ0IHRvIFVuaWZpZWQgUGxhbiBiZWNhdXNlIG0tbGluZXMgXCIgK1xuICAgICAgICAgICAgICAgIFwid2l0aG91dCB0aGUgcnRjcC1tdXggYXR0cmlidXRlIHdlcmUgZm91bmQuXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGJMaW5lLnR5cGUgPT09ICdhcHBsaWNhdGlvbicpIHtcbiAgICAgICAgICAgIG1pZDJ1bFtiTGluZS5taWRdID0gYkxpbmU7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBXaXRoIHJ0Y3AtbXV4IGFuZCBidW5kbGUgYWxsIHRoZSBjaGFubmVscyBzaG91bGQgaGF2ZSB0aGUgc2FtZSBJQ0VcbiAgICAgICAgLy8gc3R1ZmYuXG4gICAgICAgIHZhciBzb3VyY2VzID0gYkxpbmUuc291cmNlcztcbiAgICAgICAgdmFyIHNzcmNHcm91cHMgPSBiTGluZS5zc3JjR3JvdXBzO1xuICAgICAgICB2YXIgcG9ydCA9IGJMaW5lLnBvcnQ7XG5cbiAgICAgICAgLyogQ2hyb21lIGFkZHMgZGlmZmVyZW50IGNhbmRpZGF0ZXMgZXZlbiB1c2luZyBidW5kbGUsIHNvIHdlIGNvbmNhdCB0aGUgY2FuZGlkYXRlcyBsaXN0ICovXG4gICAgICAgIGlmICh0eXBlb2YgYkxpbmUuY2FuZGlkYXRlcyAhPSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBjYW5kaWRhdGVzICE9ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgY2FuZGlkYXRlcyA9IGNhbmRpZGF0ZXMuY29uY2F0KGJMaW5lLmNhbmRpZGF0ZXMpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjYW5kaWRhdGVzID0gYkxpbmUuY2FuZGlkYXRlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgodHlwZW9mIGljZVVmcmFnICE9ICd1bmRlZmluZWQnKSAmJiAodHlwZW9mIGJMaW5lLmljZVVmcmFnICE9ICd1bmRlZmluZWQnKSAmJiAoaWNlVWZyYWcgIT0gYkxpbmUuaWNlVWZyYWcpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJPbmx5IEJVTkRMRSBzdXBwb3J0ZWQsIGljZVVmcmFnIG11c3QgYmUgdGhlIHNhbWUgZm9yIGFsbCBtLWxpbmVzLlxcblwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlxcdExhc3QgaWNlVWZyYWc6IFwiICsgaWNlVWZyYWcgKyBcIlxcblwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlxcdE5ldyBpY2VVZnJhZzogXCIgKyBiTGluZS5pY2VVZnJhZ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgYkxpbmUuaWNlVWZyYWcgIT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICBpY2VVZnJhZyA9IGJMaW5lLmljZVVmcmFnO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCh0eXBlb2YgaWNlUHdkICE9ICd1bmRlZmluZWQnKSAmJiAodHlwZW9mIGJMaW5lLmljZVB3ZCAhPSAndW5kZWZpbmVkJykgJiYgKGljZVB3ZCAhPSBiTGluZS5pY2VQd2QpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJPbmx5IEJVTkRMRSBzdXBwb3J0ZWQsIGljZVB3ZCBtdXN0IGJlIHRoZSBzYW1lIGZvciBhbGwgbS1saW5lcy5cXG5cIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJcXHRMYXN0IGljZVB3ZDogXCIgKyBpY2VQd2QgKyBcIlxcblwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlxcdE5ldyBpY2VQd2Q6IFwiICsgYkxpbmUuaWNlUHdkXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBiTGluZS5pY2VQd2QgIT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICBpY2VQd2QgPSBiTGluZS5pY2VQd2Q7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoKHR5cGVvZiBmaW5nZXJwcmludCAhPSAndW5kZWZpbmVkJykgJiYgKHR5cGVvZiBiTGluZS5maW5nZXJwcmludCAhPSAndW5kZWZpbmVkJykgJiZcbiAgICAgICAgICAgIChmaW5nZXJwcmludC50eXBlICE9IGJMaW5lLmZpbmdlcnByaW50LnR5cGUgfHwgZmluZ2VycHJpbnQuaGFzaCAhPSBiTGluZS5maW5nZXJwcmludC5oYXNoKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiT25seSBCVU5ETEUgc3VwcG9ydGVkLCBmaW5nZXJwcmludCBtdXN0IGJlIHRoZSBzYW1lIGZvciBhbGwgbS1saW5lcy5cXG5cIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJcXHRMYXN0IGZpbmdlcnByaW50OiBcIiArIEpTT04uc3RyaW5naWZ5KGZpbmdlcnByaW50KSArIFwiXFxuXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXFx0TmV3IGZpbmdlcnByaW50OiBcIiArIEpTT04uc3RyaW5naWZ5KGJMaW5lLmZpbmdlcnByaW50KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgYkxpbmUuZmluZ2VycHJpbnQgIT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICBmaW5nZXJwcmludCA9IGJMaW5lLmZpbmdlcnByaW50O1xuICAgICAgICB9XG5cbiAgICAgICAgcGF5bG9hZHNbYkxpbmUudHlwZV0gPSBiTGluZS5wYXlsb2FkcztcbiAgICAgICAgcnRjcEZiW2JMaW5lLnR5cGVdID0gYkxpbmUucnRjcEZiO1xuICAgICAgICBydHBbYkxpbmUudHlwZV0gPSBiTGluZS5ydHA7XG5cbiAgICAgICAgLy8gaW52ZXJ0ZWQgc3NyYyBncm91cCBtYXBcbiAgICAgICAgdmFyIHNzcmMyZ3JvdXAgPSB7fTtcbiAgICAgICAgaWYgKHR5cGVvZiBzc3JjR3JvdXBzICE9PSAndW5kZWZpbmVkJyAmJiBBcnJheS5pc0FycmF5KHNzcmNHcm91cHMpKSB7XG4gICAgICAgICAgICBzc3JjR3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKHNzcmNHcm91cCkge1xuICAgICAgICAgICAgICAgIC8vIFhYWCBUaGlzIG1pZ2h0IGJyYWtlIGlmIGFuIFNTUkMgaXMgaW4gbW9yZSB0aGFuIG9uZSBncm91cFxuICAgICAgICAgICAgICAgIC8vIGZvciBzb21lIHJlYXNvbi5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHNzcmNHcm91cC5zc3JjcyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgICAgICAgICAgICAgQXJyYXkuaXNBcnJheShzc3JjR3JvdXAuc3NyY3MpKSB7XG4gICAgICAgICAgICAgICAgICAgIHNzcmNHcm91cC5zc3Jjcy5mb3JFYWNoKGZ1bmN0aW9uIChzc3JjKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHNzcmMyZ3JvdXBbc3NyY10gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3NyYzJncm91cFtzc3JjXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBzc3JjMmdyb3VwW3NzcmNdLnB1c2goc3NyY0dyb3VwKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzc3JjIHRvIG0tbGluZSBpbmRleC5cbiAgICAgICAgdmFyIHNzcmMybWwgPSB7fTtcblxuICAgICAgICBpZiAodHlwZW9mIHNvdXJjZXMgPT09ICdvYmplY3QnKSB7XG5cbiAgICAgICAgICAgIC8vIFdlJ2xsIHVzZSB0aGUgXCJiTGluZVwiIG9iamVjdCBhcyBhIHByb3RvdHlwZSBmb3IgZWFjaCBuZXcgXCJtTGluZVwiXG4gICAgICAgICAgICAvLyB0aGF0IHdlIGNyZWF0ZSwgYnV0IGZpcnN0IHdlIG5lZWQgdG8gY2xlYW4gaXQgdXAgYSBiaXQuXG4gICAgICAgICAgICBkZWxldGUgYkxpbmUuc291cmNlcztcbiAgICAgICAgICAgIGRlbGV0ZSBiTGluZS5zc3JjR3JvdXBzO1xuICAgICAgICAgICAgZGVsZXRlIGJMaW5lLmNhbmRpZGF0ZXM7XG4gICAgICAgICAgICBkZWxldGUgYkxpbmUuaWNlVWZyYWc7XG4gICAgICAgICAgICBkZWxldGUgYkxpbmUuaWNlUHdkO1xuICAgICAgICAgICAgZGVsZXRlIGJMaW5lLmZpbmdlcnByaW50O1xuICAgICAgICAgICAgZGVsZXRlIGJMaW5lLnBvcnQ7XG4gICAgICAgICAgICBkZWxldGUgYkxpbmUubWlkO1xuXG4gICAgICAgICAgICAvLyBFeHBsb2RlIHRoZSBQbGFuIEIgY2hhbm5lbCBzb3VyY2VzIHdpdGggb25lIG0tbGluZSBwZXIgc291cmNlLlxuICAgICAgICAgICAgT2JqZWN0LmtleXMoc291cmNlcykuZm9yRWFjaChmdW5jdGlvbihzc3JjKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBUaGUgKHVuaWZpZWQpIG0tbGluZSBmb3IgdGhpcyBTU1JDLiBXZSBlaXRoZXIgY3JlYXRlIGl0IGZyb21cbiAgICAgICAgICAgICAgICAvLyBzY3JhdGNoIG9yLCBpZiBpdCdzIGEgZ3JvdXBlZCBTU1JDLCB3ZSByZS11c2UgYSByZWxhdGVkXG4gICAgICAgICAgICAgICAgLy8gbWxpbmUuIEluIG90aGVyIHdvcmRzLCBpZiB0aGUgc291cmNlIGlzIGdyb3VwZWQgd2l0aCBhbm90aGVyXG4gICAgICAgICAgICAgICAgLy8gc291cmNlLCBwdXQgdGhlIHR3byB0b2dldGhlciBpbiB0aGUgc2FtZSBtLWxpbmUuXG4gICAgICAgICAgICAgICAgdmFyIHVMaW5lO1xuXG4gICAgICAgICAgICAgICAgLy8gV2UgYXNzdW1lIGhlcmUgdGhhdCB3ZSBhcmUgdGhlIGFuc3dlcmVyIGluIHRoZSBPL0EsIHNvIGFueVxuICAgICAgICAgICAgICAgIC8vIG9mZmVycyB3aGljaCB3ZSB0cmFuc2xhdGUgY29tZSBmcm9tIHRoZSByZW1vdGUgc2lkZSwgd2hpbGVcbiAgICAgICAgICAgICAgICAvLyBhbnN3ZXJzIGFyZSBsb2NhbC4gU28gdGhlIGNoZWNrIGJlbG93IGlzIHRvIG1ha2UgdGhhdCB3ZVxuICAgICAgICAgICAgICAgIC8vIGhhbmRsZSByZWNlaXZlLW9ubHkgU1NSQ3MgaW4gYSBzcGVjaWFsIHdheSBvbmx5IGlmIHRoZXkgY29tZVxuICAgICAgICAgICAgICAgIC8vIGZyb20gdGhlIHJlbW90ZSBzaWRlLlxuICAgICAgICAgICAgICAgIGlmIChkZXNjLnR5cGU9PT0nb2ZmZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdlIHdhbnQgdG8gZGV0ZWN0IFNTUkNzIHdoaWNoIGFyZSB1c2VkIGJ5IGEgcmVtb3RlIHBlZXJcbiAgICAgICAgICAgICAgICAgICAgLy8gaW4gYW4gbS1saW5lIHdpdGggZGlyZWN0aW9uPXJlY3Zvbmx5IChpLmUuIHRoZXkgYXJlXG4gICAgICAgICAgICAgICAgICAgIC8vIGJlaW5nIHVzZWQgZm9yIFJUQ1Agb25seSkuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgaW5mb3JtYXRpb24gd291bGQgaGF2ZSBnb3R0ZW4gbG9zdCBpZiB0aGUgcmVtb3RlXG4gICAgICAgICAgICAgICAgICAgIC8vIHBlZXIgdXNlZCBVbmlmaWVkIFBsYW4gYW5kIHRoZWlyIGxvY2FsIGRlc2NyaXB0aW9uIHdhc1xuICAgICAgICAgICAgICAgICAgICAvLyB0cmFuc2xhdGVkIHRvIFBsYW4gQi4gU28gd2UgdXNlIHRoZSBsYWNrIG9mIGFuIE1TSURcbiAgICAgICAgICAgICAgICAgICAgLy8gYXR0cmlidXRlIHRvIGRlZHVjZSBhIFwicmVjZWl2ZSBvbmx5XCIgU1NSQy5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzb3VyY2VzW3NzcmNdLm1zaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Zvbmx5U3NyY3NbYkxpbmUudHlwZV1bc3NyY10gPSBzb3VyY2VzW3NzcmNdO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVjZWl2ZS1vbmx5IFNTUkNzIG11c3Qgbm90IGNyZWF0ZSBuZXcgbS1saW5lcy4gV2VcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdpbGwgYXNzaWduIHRoZW0gdG8gYW4gZXhpc3RpbmcgbS1saW5lIGxhdGVyLlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBzc3JjMmdyb3VwW3NzcmNdICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KHNzcmMyZ3JvdXBbc3NyY10pKSB7XG4gICAgICAgICAgICAgICAgICAgIHNzcmMyZ3JvdXBbc3NyY10uc29tZShmdW5jdGlvbiAoc3NyY0dyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzc3JjR3JvdXAuc3NyY3MgKmlzKiBhbiBBcnJheSwgbm8gbmVlZCB0byBjaGVja1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWdhaW4gaGVyZS5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzc3JjR3JvdXAuc3NyY3Muc29tZShmdW5jdGlvbiAocmVsYXRlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc3NyYzJtbFtyZWxhdGVkXSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUgPSBzc3JjMm1sW3JlbGF0ZWRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB1TGluZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhlIG0tbGluZSBhbHJlYWR5IGV4aXN0cy4gSnVzdCBhZGQgdGhlIHNvdXJjZS5cbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuc291cmNlc1tzc3JjXSA9IHNvdXJjZXNbc3NyY107XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBzb3VyY2VzW3NzcmNdLm1zaWQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gVXNlIHRoZSBcImJMaW5lXCIgYXMgYSBwcm90b3R5cGUgZm9yIHRoZSBcInVMaW5lXCIuXG4gICAgICAgICAgICAgICAgICAgIHVMaW5lID0gT2JqZWN0LmNyZWF0ZShiTGluZSk7XG4gICAgICAgICAgICAgICAgICAgIHNzcmMybWxbc3NyY10gPSB1TGluZTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHNvdXJjZXNbc3NyY10ubXNpZCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFzc2lnbiB0aGUgbXNpZCBvZiB0aGUgc291cmNlIHRvIHRoZSBtLWxpbmUuIE5vdGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoYXQgaXQgaXMgbm90IGd1YXJhbnRlZWQgdGhhdCB0aGUgc291cmNlIHdpbGwgaGF2ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbXNpZC4gSW4gcGFydGljdWxhciBcInJlY3Zvbmx5XCIgc291cmNlcyBkb24ndCBoYXZlIGFuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBtc2lkLiBOb3RlIHRoYXQgXCJyZWN2b25seVwiIGlzIGEgdGVybSBvbmx5IGRlZmluZWRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZvciBtLWxpbmVzLlxuICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUubXNpZCA9IHNvdXJjZXNbc3NyY10ubXNpZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBzb3VyY2VzW3NzcmNdLm1zaWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBXZSBhc3NpZ24gb25lIFNTUkMgcGVyIG1lZGlhIGxpbmUuXG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLnNvdXJjZXMgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuc291cmNlc1tzc3JjXSA9IHNvdXJjZXNbc3NyY107XG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLnNzcmNHcm91cHMgPSBzc3JjMmdyb3VwW3NzcmNdO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFVzZSB0aGUgY2FjaGVkIFVuaWZpZWQgUGxhbiBTRFAgKGlmIGl0IGV4aXN0cykgdG8gYXNzaWduXG4gICAgICAgICAgICAgICAgICAgIC8vIFNTUkNzIHRvIG1pZHMuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2FjaGVkICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZW9mIGNhY2hlZC5tZWRpYSAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LmlzQXJyYXkoY2FjaGVkLm1lZGlhKSkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjYWNoZWQubWVkaWEuZm9yRWFjaChmdW5jdGlvbiAobSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbS5zb3VyY2VzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPYmplY3Qua2V5cyhtLnNvdXJjZXMpLmZvckVhY2goZnVuY3Rpb24gKHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzID09PSBzc3JjKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUubWlkID0gbS5taWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB1TGluZS5taWQgPT09ICd1bmRlZmluZWQnKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHRoaXMgaXMgYW4gU1NSQyB0aGF0IHdlIHNlZSBmb3IgdGhlIGZpcnN0IHRpbWVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFzc2lnbiBpdCBhIG5ldyBtaWQuIFRoaXMgaXMgdHlwaWNhbGx5IHRoZSBjYXNlIHdoZW5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoaXMgbWV0aG9kIGlzIGNhbGxlZCB0byB0cmFuc2Zvcm0gYSByZW1vdGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRlc2NyaXB0aW9uIGZvciB0aGUgZmlyc3QgdGltZSBvciB3aGVuIHRoZXJlIGlzIGFcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5ldyBTU1JDIGluIHRoZSByZW1vdGUgZGVzY3JpcHRpb24gYmVjYXVzZSBhIG5ld1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcGVlciBoYXMgam9pbmVkIHRoZSBjb25mZXJlbmNlLiBMb2NhbCBTU1JDcyBzaG91bGRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGhhdmUgYWxyZWFkeSBiZWVuIGFkZGVkIHRvIHRoZSBtYXAgaW4gdGhlIHRvUGxhbkJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG1ldGhvZC5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBCZWNhdXNlIEZGIGdlbmVyYXRlcyBhbnN3ZXJzIGluIFVuaWZpZWQgUGxhbiBzdHlsZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdlIE1VU1QgYWxyZWFkeSBoYXZlIGEgY2FjaGVkIGFuc3dlciB3aXRoIGFsbCB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGxvY2FsIFNTUkNzIG1hcHBlZCB0byBzb21lIG0tbGluZS9taWQuXG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHVMaW5lLm1pZCA9IFtiTGluZS50eXBlLCAnLScsIHNzcmNdLmpvaW4oJycpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSW5jbHVkZSB0aGUgY2FuZGlkYXRlcyBpbiB0aGUgMXN0IG1lZGlhIGxpbmUuXG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLmNhbmRpZGF0ZXMgPSBjYW5kaWRhdGVzO1xuICAgICAgICAgICAgICAgICAgICB1TGluZS5pY2VVZnJhZyA9IGljZVVmcmFnO1xuICAgICAgICAgICAgICAgICAgICB1TGluZS5pY2VQd2QgPSBpY2VQd2Q7XG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLmZpbmdlcnByaW50ID0gZmluZ2VycHJpbnQ7XG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLnBvcnQgPSBwb3J0O1xuXG4gICAgICAgICAgICAgICAgICAgIG1pZDJ1bFt1TGluZS5taWRdID0gdUxpbmU7XG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZXMydWxbdUlkeF0gPSB1TGluZS5zb3VyY2VzO1xuXG4gICAgICAgICAgICAgICAgICAgIHNlbGYuY2FjaGUubWxVMkJNYXBbdUlkeF0gPSBiSWR4O1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHNlbGYuY2FjaGUubWxCMlVNYXBbYklkeF0gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgc2VsZi5jYWNoZS5tbEIyVU1hcFtiSWR4XSA9IHVJZHg7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdUlkeCsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciB1TGluZSA9IGJMaW5lO1xuXG4gICAgICAgICAgdUxpbmUuY2FuZGlkYXRlcyA9IGNhbmRpZGF0ZXM7XG4gICAgICAgICAgdUxpbmUuaWNlVWZyYWcgPSBpY2VVZnJhZztcbiAgICAgICAgICB1TGluZS5pY2VQd2QgPSBpY2VQd2Q7XG4gICAgICAgICAgdUxpbmUuZmluZ2VycHJpbnQgPSBmaW5nZXJwcmludDtcbiAgICAgICAgICB1TGluZS5wb3J0ID0gcG9ydDtcblxuICAgICAgICAgIG1pZDJ1bFt1TGluZS5taWRdID0gdUxpbmU7XG5cbiAgICAgICAgICBzZWxmLmNhY2hlLm1sVTJCTWFwW3VJZHhdID0gYklkeDtcbiAgICAgICAgICBpZiAodHlwZW9mIHNlbGYuY2FjaGUubWxCMlVNYXBbYklkeF0gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBzZWxmLmNhY2hlLm1sQjJVTWFwW2JJZHhdID0gdUlkeDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBiSWR4Kys7XG4gICAgfSk7XG5cbiAgICAvLyBSZWJ1aWxkIHRoZSBtZWRpYSBhcnJheSBpbiB0aGUgcmlnaHQgb3JkZXIgYW5kIGFkZCB0aGUgbWlzc2luZyBtTGluZXNcbiAgICAvLyAobWlzc2luZyBmcm9tIHRoZSBQbGFuIEIgU0RQKS5cbiAgICBzZXNzaW9uLm1lZGlhID0gW107XG4gICAgbWlkcyA9IFtdOyAvLyByZXVzZVxuXG4gICAgaWYgKGRlc2MudHlwZSA9PT0gJ2Fuc3dlcicpIHtcblxuICAgICAgICAvLyBUaGUgbWVkaWEgbGluZXMgaW4gdGhlIGFuc3dlciBtdXN0IG1hdGNoIHRoZSBtZWRpYSBsaW5lcyBpbiB0aGVcbiAgICAgICAgLy8gb2ZmZXIuIFRoZSBvcmRlciBpcyBpbXBvcnRhbnQgdG9vLiBIZXJlIHdlIGFzc3VtZSB0aGF0IEZpcmVmb3ggaXNcbiAgICAgICAgLy8gdGhlIGFuc3dlcmVyLCBzbyB3ZSBtZXJlbHkgaGF2ZSB0byB1c2UgdGhlIHJlY29uc3RydWN0ZWQgKHVuaWZpZWQpXG4gICAgICAgIC8vIGFuc3dlciB0byB1cGRhdGUgdGhlIGNhY2hlZCAodW5pZmllZCkgYW5zd2VyIGFjY29yZGluZ2x5LlxuICAgICAgICAvL1xuICAgICAgICAvLyBJbiB0aGUgZ2VuZXJhbCBjYXNlLCBvbmUgd291bGQgaGF2ZSB0byB1c2UgdGhlIGNhY2hlZCAodW5pZmllZClcbiAgICAgICAgLy8gb2ZmZXIgdG8gZmluZCB0aGUgbS1saW5lcyB0aGF0IGFyZSBtaXNzaW5nIGZyb20gdGhlIHJlY29uc3RydWN0ZWRcbiAgICAgICAgLy8gYW5zd2VyLCBwb3RlbnRpYWxseSBncmFiYmluZyB0aGVtIGZyb20gdGhlIGNhY2hlZCAodW5pZmllZCkgYW5zd2VyLlxuICAgICAgICAvLyBPbmUgaGFzIHRvIGJlIGNhcmVmdWwgd2l0aCB0aGlzIGFwcHJvYWNoIGJlY2F1c2UgaW5hY3RpdmUgbS1saW5lcyBkb1xuICAgICAgICAvLyBub3QgYWx3YXlzIGhhdmUgYW4gbWlkLCBtYWtpbmcgaXQgdHJpY2t5IChpbXBvc3NpYmxlPykgdG8gZmluZCB3aGVyZVxuICAgICAgICAvLyBleGFjdGx5IGFuZCB3aGljaCBtLWxpbmVzIGFyZSBtaXNzaW5nIGZyb20gdGhlIHJlY29uc3RydWN0ZWQgYW5zd2VyLlxuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2FjaGVkLm1lZGlhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgdUxpbmUgPSBjYWNoZWQubWVkaWFbaV07XG5cbiAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5tc2lkO1xuICAgICAgICAgICAgZGVsZXRlIHVMaW5lLnNvdXJjZXM7XG4gICAgICAgICAgICBkZWxldGUgdUxpbmUuc3NyY0dyb3VwcztcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBzb3VyY2VzMnVsW2ldID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICBpZiAoIXVMaW5lLmRpcmVjdGlvblxuICAgICAgICAgICAgICAgICAgfHwgdUxpbmUuZGlyZWN0aW9uID09PSAnc2VuZHJlY3YnKVxuICAgICAgICAgICAgICAgICAgdUxpbmUuZGlyZWN0aW9uID0gJ3JlY3Zvbmx5JztcbiAgICAgICAgICAgICAgZWxzZSBpZiAodUxpbmUuZGlyZWN0aW9uID09PSAnc2VuZG9ubHknKVxuICAgICAgICAgICAgICAgICAgdUxpbmUuZGlyZWN0aW9uID0gJ2luYWN0aXZlJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGlmICghdUxpbmUuZGlyZWN0aW9uXG4gICAgICAgICAgICAgICAgICB8fCB1TGluZS5kaXJlY3Rpb24gPT09ICdzZW5kcmVjdicpXG4gICAgICAgICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gPSAnc2VuZHJlY3YnO1xuICAgICAgICAgICAgICBlbHNlIGlmICh1TGluZS5kaXJlY3Rpb24gPT09ICdyZWN2b25seScpXG4gICAgICAgICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gPSAnc2VuZG9ubHknO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB1TGluZS5zb3VyY2VzID0gc291cmNlczJ1bFtpXTtcbiAgICAgICAgICAgIHVMaW5lLmNhbmRpZGF0ZXMgPSBjYW5kaWRhdGVzO1xuICAgICAgICAgICAgdUxpbmUuaWNlVWZyYWcgPSBpY2VVZnJhZztcbiAgICAgICAgICAgIHVMaW5lLmljZVB3ZCA9IGljZVB3ZDtcbiAgICAgICAgICAgIHVMaW5lLmZpbmdlcnByaW50ID0gZmluZ2VycHJpbnQ7XG5cbiAgICAgICAgICAgIHVMaW5lLnJ0cCA9IHJ0cFt1TGluZS50eXBlXTtcbiAgICAgICAgICAgIHVMaW5lLnBheWxvYWRzID0gcGF5bG9hZHNbdUxpbmUudHlwZV07XG4gICAgICAgICAgICB1TGluZS5ydGNwRmIgPSBydGNwRmJbdUxpbmUudHlwZV07XG5cbiAgICAgICAgICAgIHNlc3Npb24ubWVkaWEucHVzaCh1TGluZSk7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdUxpbmUubWlkID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIC8vIGluYWN0aXZlIGxpbmVzIGRvbid0L21heSBub3QgaGF2ZSBhbiBtaWQuXG4gICAgICAgICAgICAgICAgbWlkcy5wdXNoKHVMaW5lLm1pZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuXG4gICAgICAgIC8vIFNEUCBvZmZlci9hbnN3ZXIgKGFuZCB0aGUgSlNFUCBzcGVjKSBmb3JiaWRzIHJlbW92aW5nIGFuIG0tc2VjdGlvblxuICAgICAgICAvLyB1bmRlciBhbnkgY2lyY3Vtc3RhbmNlcy4gSWYgd2UgYXJlIG5vIGxvbmdlciBpbnRlcmVzdGVkIGluIHNlbmRpbmcgYVxuICAgICAgICAvLyB0cmFjaywgd2UganVzdCByZW1vdmUgdGhlIG1zaWQgYW5kIHNzcmMgYXR0cmlidXRlcyBhbmQgc2V0IGl0IHRvXG4gICAgICAgIC8vIGVpdGhlciBhPXJlY3Zvbmx5IChhcyB0aGUgcmVvZmZlcmVyLCB3ZSBtdXN0IHVzZSByZWN2b25seSBpZiB0aGVcbiAgICAgICAgLy8gb3RoZXIgc2lkZSB3YXMgcHJldmlvdXNseSBzZW5kaW5nIG9uIHRoZSBtLXNlY3Rpb24sIGJ1dCB3ZSBjYW4gYWxzb1xuICAgICAgICAvLyBsZWF2ZSB0aGUgcG9zc2liaWxpdHkgb3BlbiBpZiBpdCB3YXNuJ3QgcHJldmlvdXNseSBpbiB1c2UpLCBvclxuICAgICAgICAvLyBhPWluYWN0aXZlLlxuXG4gICAgICAgIGlmICh0eXBlb2YgY2FjaGVkICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgdHlwZW9mIGNhY2hlZC5tZWRpYSAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgICAgIEFycmF5LmlzQXJyYXkoY2FjaGVkLm1lZGlhKSkge1xuICAgICAgICAgICAgY2FjaGVkLm1lZGlhLmZvckVhY2goZnVuY3Rpb24odUxpbmUpIHtcbiAgICAgICAgICAgICAgICBtaWRzLnB1c2godUxpbmUubWlkKTtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG1pZDJ1bFt1TGluZS5taWRdICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLm1lZGlhLnB1c2gobWlkMnVsW3VMaW5lLm1pZF0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5tc2lkO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdUxpbmUuc291cmNlcztcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHVMaW5lLnNzcmNHcm91cHM7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF1TGluZS5kaXJlY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgICAgIHx8IHVMaW5lLmRpcmVjdGlvbiA9PT0gJ3NlbmRyZWN2Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUuZGlyZWN0aW9uID0gJ3NlbmRvbmx5JztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoIXVMaW5lLmRpcmVjdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgfHwgdUxpbmUuZGlyZWN0aW9uID09PSAncmVjdm9ubHknKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gPSAnaW5hY3RpdmUnO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYWRkU2V0dXBBdHRyICh1TGluZSk7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWEucHVzaCh1TGluZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgYWxsIHRoZSByZW1haW5pbmcgKG5ldykgbS1saW5lcyBvZiB0aGUgdHJhbnNmb3JtZWQgU0RQLlxuICAgICAgICBPYmplY3Qua2V5cyhtaWQydWwpLmZvckVhY2goZnVuY3Rpb24obWlkKSB7XG4gICAgICAgICAgICBpZiAobWlkcy5pbmRleE9mKG1pZCkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgbWlkcy5wdXNoKG1pZCk7XG4gICAgICAgICAgICAgICAgaWYgKG1pZDJ1bFttaWRdLmRpcmVjdGlvbiA9PT0gJ3JlY3Zvbmx5Jykge1xuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIGEgcmVtb3RlIHJlY3Zvbmx5IGNoYW5uZWwuIEFkZCBpdHMgU1NSQyB0byB0aGVcbiAgICAgICAgICAgICAgICAgICAgLy8gYXBwcm9wcmlhdGUgc2VuZHJlY3Ygb3Igc2VuZG9ubHkgY2hhbm5lbC5cbiAgICAgICAgICAgICAgICAgICAgLy8gVE9ETyhncCkgd2hhdCBpZiB3ZSBkb24ndCBoYXZlIHNlbmRyZWN2L3NlbmRvbmx5XG4gICAgICAgICAgICAgICAgICAgIC8vIGNoYW5uZWw/XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvbmUgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLm1lZGlhLnNvbWUoZnVuY3Rpb24gKHVMaW5lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoKHVMaW5lLmRpcmVjdGlvbiA9PT0gJ3NlbmRyZWN2JyB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiA9PT0gJ3NlbmRvbmx5JykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1TGluZS50eXBlID09PSBtaWQydWxbbWlkXS50eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbWlkMnVsW21pZF0gc2hvdWxkbid0IGhhdmUgYW55IHNzcmMtZ3JvdXBzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmtleXMobWlkMnVsW21pZF0uc291cmNlcykuZm9yRWFjaChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gKHNzcmMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUuc291cmNlc1tzc3JjXSA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaWQydWxbbWlkXS5zb3VyY2VzW3NzcmNdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9uZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbi5tZWRpYS5wdXNoKG1pZDJ1bFttaWRdKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWEucHVzaChtaWQydWxbbWlkXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBBZnRlciB3ZSBoYXZlIGNvbnN0cnVjdGVkIHRoZSBQbGFuIFVuaWZpZWQgbS1saW5lcyB3ZSBjYW4gZmlndXJlIG91dFxuICAgIC8vIHdoZXJlIChpbiB3aGljaCBtLWxpbmUpIHRvIHBsYWNlIHRoZSAncmVjdm9ubHkgU1NSQ3MnLlxuICAgIC8vIE5vdGU6IHdlIGFzc3VtZSBoZXJlIHRoYXQgd2UgYXJlIHRoZSBhbnN3ZXJlciBpbiB0aGUgTy9BLCBzbyBhbnkgb2ZmZXJzXG4gICAgLy8gd2hpY2ggd2UgdHJhbnNsYXRlIGNvbWUgZnJvbSB0aGUgcmVtb3RlIHNpZGUsIHdoaWxlIGFuc3dlcnMgYXJlIGxvY2FsXG4gICAgLy8gKGFuZCBzbyBvdXIgbGFzdCBsb2NhbCBkZXNjcmlwdGlvbiBpcyBjYWNoZWQgYXMgYW4gJ2Fuc3dlcicpLlxuICAgIFtcImF1ZGlvXCIsIFwidmlkZW9cIl0uZm9yRWFjaChmdW5jdGlvbiAodHlwZSkge1xuICAgICAgICBpZiAoIXNlc3Npb24gfHwgIXNlc3Npb24ubWVkaWEgfHwgIUFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgdmFyIGlkeCA9IG51bGw7XG4gICAgICAgIGlmIChPYmplY3Qua2V5cyhyZWN2b25seVNzcmNzW3R5cGVdKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBpZHggPSBzZWxmLmdldEZpcnN0U2VuZGluZ0luZGV4RnJvbUFuc3dlcih0eXBlKTtcbiAgICAgICAgICAgIGlmIChpZHggPT09IG51bGwpe1xuICAgICAgICAgICAgICAgIC8vIElmIHRoaXMgaXMgdGhlIGZpcnN0IG9mZmVyIHdlIHJlY2VpdmUsIHdlIGRvbid0IGhhdmUgYVxuICAgICAgICAgICAgICAgIC8vIGNhY2hlZCBhbnN3ZXIuIEFzc3VtZSB0aGF0IHdlIHdpbGwgYmUgc2VuZGluZyBtZWRpYSB1c2luZ1xuICAgICAgICAgICAgICAgIC8vIHRoZSBmaXJzdCBtLWxpbmUgZm9yIGVhY2ggbWVkaWEgdHlwZS5cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2Vzc2lvbi5tZWRpYS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbi5tZWRpYVtpXS50eXBlID09PSB0eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZHggPSBpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaWR4ICYmIHNlc3Npb24ubWVkaWEubGVuZ3RoID4gaWR4KSB7XG4gICAgICAgICAgICB2YXIgbUxpbmUgPSBzZXNzaW9uLm1lZGlhW2lkeF07XG4gICAgICAgICAgICBPYmplY3Qua2V5cyhyZWN2b25seVNzcmNzW3R5cGVdKS5mb3JFYWNoKGZ1bmN0aW9uKHNzcmMpIHtcbiAgICAgICAgICAgICAgICBpZiAobUxpbmUuc291cmNlcyAmJiBtTGluZS5zb3VyY2VzW3NzcmNdKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcIlJlcGxhY2luZyBhbiBleGlzdGluZyBTU1JDLlwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCFtTGluZS5zb3VyY2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIG1MaW5lLnNvdXJjZXMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBtTGluZS5zb3VyY2VzW3NzcmNdID0gcmVjdm9ubHlTc3Jjc1t0eXBlXVtzc3JjXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICBpZiAodHlwZW9mIHNlc3Npb24uZ3JvdXBzICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgLy8gV2UgcmVnZW5lcmF0ZSB0aGUgQlVORExFIGdyb3VwIChzaW5jZSB3ZSByZWdlbmVyYXRlZCB0aGUgbWlkcylcbiAgICAgIHNlc3Npb24uZ3JvdXBzLnNvbWUoZnVuY3Rpb24oZ3JvdXApIHtcblx0ICBpZiAoZ3JvdXAudHlwZSA9PT0gJ0JVTkRMRScpIHtcblx0ICAgICAgZ3JvdXAubWlkcyA9IG1pZHMuam9pbignICcpO1xuXHQgICAgICByZXR1cm4gdHJ1ZTtcblx0ICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBtc2lkIHNlbWFudGljXG4gICAgc2Vzc2lvbi5tc2lkU2VtYW50aWMgPSB7XG4gICAgICAgIHNlbWFudGljOiAnV01TJyxcbiAgICAgICAgdG9rZW46ICcqJ1xuICAgIH07XG5cbiAgICB2YXIgcmVzU3RyID0gdHJhbnNmb3JtLndyaXRlKHNlc3Npb24pO1xuXG4gICAgLy8gQ2FjaGUgdGhlIHRyYW5zZm9ybWVkIFNEUCAoVW5pZmllZCBQbGFuKSBmb3IgbGF0ZXIgcmUtdXNlIGluIHRoaXNcbiAgICAvLyBmdW5jdGlvbi5cbiAgICB0aGlzLmNhY2hlW2Rlc2MudHlwZV0gPSByZXNTdHI7XG5cbiAgICByZXR1cm4gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICAgIHR5cGU6IGRlc2MudHlwZSxcbiAgICAgICAgc2RwOiByZXNTdHJcbiAgICB9KTtcblxuICAgIC8vI2VuZHJlZ2lvblxufTtcbiIsIi8qIENvcHlyaWdodCBAIDIwMTUgQXRsYXNzaWFuIFB0eSBMdGRcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxudmFyIHRyYW5zZm9ybSA9IHJlcXVpcmUoJ3NkcC10cmFuc2Zvcm0nKTtcblxuZXhwb3J0cy53cml0ZSA9IGZ1bmN0aW9uKHNlc3Npb24sIG9wdHMpIHtcblxuICBpZiAodHlwZW9mIHNlc3Npb24gIT09ICd1bmRlZmluZWQnICYmXG4gICAgICB0eXBlb2Ygc2Vzc2lvbi5tZWRpYSAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkpIHtcblxuICAgIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbiAobUxpbmUpIHtcbiAgICAgIC8vIGV4cGFuZCBzb3VyY2VzIHRvIHNzcmNzXG4gICAgICBpZiAodHlwZW9mIG1MaW5lLnNvdXJjZXMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIE9iamVjdC5rZXlzKG1MaW5lLnNvdXJjZXMpLmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIG1MaW5lLnNzcmNzID0gW107XG4gICAgICAgICAgT2JqZWN0LmtleXMobUxpbmUuc291cmNlcykuZm9yRWFjaChmdW5jdGlvbiAoc3NyYykge1xuICAgICAgICAgICAgdmFyIHNvdXJjZSA9IG1MaW5lLnNvdXJjZXNbc3NyY107XG4gICAgICAgICAgICBPYmplY3Qua2V5cyhzb3VyY2UpLmZvckVhY2goZnVuY3Rpb24gKGF0dHJpYnV0ZSkge1xuICAgICAgICAgICAgICBtTGluZS5zc3Jjcy5wdXNoKHtcbiAgICAgICAgICAgICAgICBpZDogc3NyYyxcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGU6IGF0dHJpYnV0ZSxcbiAgICAgICAgICAgICAgICB2YWx1ZTogc291cmNlW2F0dHJpYnV0ZV1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBkZWxldGUgbUxpbmUuc291cmNlcztcbiAgICAgICAgfVxuXG4gICAgICAvLyBqb2luIHNzcmNzIGluIHNzcmMgZ3JvdXBzXG4gICAgICBpZiAodHlwZW9mIG1MaW5lLnNzcmNHcm91cHMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIEFycmF5LmlzQXJyYXkobUxpbmUuc3NyY0dyb3VwcykpIHtcbiAgICAgICAgICBtTGluZS5zc3JjR3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKHNzcmNHcm91cCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBzc3JjR3JvdXAuc3NyY3MgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICAgICAgQXJyYXkuaXNBcnJheShzc3JjR3JvdXAuc3NyY3MpKSB7XG4gICAgICAgICAgICAgIHNzcmNHcm91cC5zc3JjcyA9IHNzcmNHcm91cC5zc3Jjcy5qb2luKCcgJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8vIGpvaW4gZ3JvdXAgbWlkc1xuICBpZiAodHlwZW9mIHNlc3Npb24gIT09ICd1bmRlZmluZWQnICYmXG4gICAgICB0eXBlb2Ygc2Vzc2lvbi5ncm91cHMgIT09ICd1bmRlZmluZWQnICYmIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5ncm91cHMpKSB7XG5cbiAgICBzZXNzaW9uLmdyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uIChnKSB7XG4gICAgICBpZiAodHlwZW9mIGcubWlkcyAhPT0gJ3VuZGVmaW5lZCcgJiYgQXJyYXkuaXNBcnJheShnLm1pZHMpKSB7XG4gICAgICAgIGcubWlkcyA9IGcubWlkcy5qb2luKCcgJyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gdHJhbnNmb3JtLndyaXRlKHNlc3Npb24sIG9wdHMpO1xufTtcblxuZXhwb3J0cy5wYXJzZSA9IGZ1bmN0aW9uKHNkcCkge1xuICB2YXIgc2Vzc2lvbiA9IHRyYW5zZm9ybS5wYXJzZShzZHApO1xuXG4gIGlmICh0eXBlb2Ygc2Vzc2lvbiAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHNlc3Npb24ubWVkaWEgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICBBcnJheS5pc0FycmF5KHNlc3Npb24ubWVkaWEpKSB7XG5cbiAgICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24gKG1MaW5lKSB7XG4gICAgICAvLyBncm91cCBzb3VyY2VzIGF0dHJpYnV0ZXMgYnkgc3NyY1xuICAgICAgaWYgKHR5cGVvZiBtTGluZS5zc3JjcyAhPT0gJ3VuZGVmaW5lZCcgJiYgQXJyYXkuaXNBcnJheShtTGluZS5zc3JjcykpIHtcbiAgICAgICAgbUxpbmUuc291cmNlcyA9IHt9O1xuICAgICAgICBtTGluZS5zc3Jjcy5mb3JFYWNoKGZ1bmN0aW9uIChzc3JjKSB7XG4gICAgICAgICAgaWYgKCFtTGluZS5zb3VyY2VzW3NzcmMuaWRdKVxuICAgICAgICAgIG1MaW5lLnNvdXJjZXNbc3NyYy5pZF0gPSB7fTtcbiAgICAgICAgbUxpbmUuc291cmNlc1tzc3JjLmlkXVtzc3JjLmF0dHJpYnV0ZV0gPSBzc3JjLnZhbHVlO1xuICAgICAgICB9KTtcblxuICAgICAgICBkZWxldGUgbUxpbmUuc3NyY3M7XG4gICAgICB9XG5cbiAgICAgIC8vIHNwbGl0IHNzcmNzIGluIHNzcmMgZ3JvdXBzXG4gICAgICBpZiAodHlwZW9mIG1MaW5lLnNzcmNHcm91cHMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIEFycmF5LmlzQXJyYXkobUxpbmUuc3NyY0dyb3VwcykpIHtcbiAgICAgICAgICBtTGluZS5zc3JjR3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKHNzcmNHcm91cCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBzc3JjR3JvdXAuc3NyY3MgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIHNzcmNHcm91cC5zc3JjcyA9IHNzcmNHcm91cC5zc3Jjcy5zcGxpdCgnICcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSk7XG4gIH1cbiAgLy8gc3BsaXQgZ3JvdXAgbWlkc1xuICBpZiAodHlwZW9mIHNlc3Npb24gIT09ICd1bmRlZmluZWQnICYmXG4gICAgICB0eXBlb2Ygc2Vzc2lvbi5ncm91cHMgIT09ICd1bmRlZmluZWQnICYmIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5ncm91cHMpKSB7XG5cbiAgICBzZXNzaW9uLmdyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uIChnKSB7XG4gICAgICBpZiAodHlwZW9mIGcubWlkcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgZy5taWRzID0gZy5taWRzLnNwbGl0KCcgJyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gc2Vzc2lvbjtcbn07XG5cbiIsIiAvKiBlc2xpbnQtZW52IG5vZGUgKi9cbid1c2Ugc3RyaWN0JztcblxuLy8gU0RQIGhlbHBlcnMuXG52YXIgU0RQVXRpbHMgPSB7fTtcblxuLy8gR2VuZXJhdGUgYW4gYWxwaGFudW1lcmljIGlkZW50aWZpZXIgZm9yIGNuYW1lIG9yIG1pZHMuXG4vLyBUT0RPOiB1c2UgVVVJRHMgaW5zdGVhZD8gaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vamVkLzk4Mjg4M1xuU0RQVXRpbHMuZ2VuZXJhdGVJZGVudGlmaWVyID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zdWJzdHIoMiwgMTApO1xufTtcblxuLy8gVGhlIFJUQ1AgQ05BTUUgdXNlZCBieSBhbGwgcGVlcmNvbm5lY3Rpb25zIGZyb20gdGhlIHNhbWUgSlMuXG5TRFBVdGlscy5sb2NhbENOYW1lID0gU0RQVXRpbHMuZ2VuZXJhdGVJZGVudGlmaWVyKCk7XG5cbi8vIFNwbGl0cyBTRFAgaW50byBsaW5lcywgZGVhbGluZyB3aXRoIGJvdGggQ1JMRiBhbmQgTEYuXG5TRFBVdGlscy5zcGxpdExpbmVzID0gZnVuY3Rpb24oYmxvYikge1xuICByZXR1cm4gYmxvYi50cmltKCkuc3BsaXQoJ1xcbicpLm1hcChmdW5jdGlvbihsaW5lKSB7XG4gICAgcmV0dXJuIGxpbmUudHJpbSgpO1xuICB9KTtcbn07XG4vLyBTcGxpdHMgU0RQIGludG8gc2Vzc2lvbnBhcnQgYW5kIG1lZGlhc2VjdGlvbnMuIEVuc3VyZXMgQ1JMRi5cblNEUFV0aWxzLnNwbGl0U2VjdGlvbnMgPSBmdW5jdGlvbihibG9iKSB7XG4gIHZhciBwYXJ0cyA9IGJsb2Iuc3BsaXQoJ1xcbm09Jyk7XG4gIHJldHVybiBwYXJ0cy5tYXAoZnVuY3Rpb24ocGFydCwgaW5kZXgpIHtcbiAgICByZXR1cm4gKGluZGV4ID4gMCA/ICdtPScgKyBwYXJ0IDogcGFydCkudHJpbSgpICsgJ1xcclxcbic7XG4gIH0pO1xufTtcblxuLy8gcmV0dXJucyB0aGUgc2Vzc2lvbiBkZXNjcmlwdGlvbi5cblNEUFV0aWxzLmdldERlc2NyaXB0aW9uID0gZnVuY3Rpb24oYmxvYikge1xuICB2YXIgc2VjdGlvbnMgPSBTRFBVdGlscy5zcGxpdFNlY3Rpb25zKGJsb2IpO1xuICByZXR1cm4gc2VjdGlvbnMgJiYgc2VjdGlvbnNbMF07XG59O1xuXG4vLyByZXR1cm5zIHRoZSBpbmRpdmlkdWFsIG1lZGlhIHNlY3Rpb25zLlxuU0RQVXRpbHMuZ2V0TWVkaWFTZWN0aW9ucyA9IGZ1bmN0aW9uKGJsb2IpIHtcbiAgdmFyIHNlY3Rpb25zID0gU0RQVXRpbHMuc3BsaXRTZWN0aW9ucyhibG9iKTtcbiAgc2VjdGlvbnMuc2hpZnQoKTtcbiAgcmV0dXJuIHNlY3Rpb25zO1xufTtcblxuLy8gUmV0dXJucyBsaW5lcyB0aGF0IHN0YXJ0IHdpdGggYSBjZXJ0YWluIHByZWZpeC5cblNEUFV0aWxzLm1hdGNoUHJlZml4ID0gZnVuY3Rpb24oYmxvYiwgcHJlZml4KSB7XG4gIHJldHVybiBTRFBVdGlscy5zcGxpdExpbmVzKGJsb2IpLmZpbHRlcihmdW5jdGlvbihsaW5lKSB7XG4gICAgcmV0dXJuIGxpbmUuaW5kZXhPZihwcmVmaXgpID09PSAwO1xuICB9KTtcbn07XG5cbi8vIFBhcnNlcyBhbiBJQ0UgY2FuZGlkYXRlIGxpbmUuIFNhbXBsZSBpbnB1dDpcbi8vIGNhbmRpZGF0ZTo3MDI3ODYzNTAgMiB1ZHAgNDE4MTk5MDIgOC44LjguOCA2MDc2OSB0eXAgcmVsYXkgcmFkZHIgOC44LjguOFxuLy8gcnBvcnQgNTU5OTZcIlxuU0RQVXRpbHMucGFyc2VDYW5kaWRhdGUgPSBmdW5jdGlvbihsaW5lKSB7XG4gIHZhciBwYXJ0cztcbiAgLy8gUGFyc2UgYm90aCB2YXJpYW50cy5cbiAgaWYgKGxpbmUuaW5kZXhPZignYT1jYW5kaWRhdGU6JykgPT09IDApIHtcbiAgICBwYXJ0cyA9IGxpbmUuc3Vic3RyaW5nKDEyKS5zcGxpdCgnICcpO1xuICB9IGVsc2Uge1xuICAgIHBhcnRzID0gbGluZS5zdWJzdHJpbmcoMTApLnNwbGl0KCcgJyk7XG4gIH1cblxuICB2YXIgY2FuZGlkYXRlID0ge1xuICAgIGZvdW5kYXRpb246IHBhcnRzWzBdLFxuICAgIGNvbXBvbmVudDogcGFyc2VJbnQocGFydHNbMV0sIDEwKSxcbiAgICBwcm90b2NvbDogcGFydHNbMl0udG9Mb3dlckNhc2UoKSxcbiAgICBwcmlvcml0eTogcGFyc2VJbnQocGFydHNbM10sIDEwKSxcbiAgICBpcDogcGFydHNbNF0sXG4gICAgcG9ydDogcGFyc2VJbnQocGFydHNbNV0sIDEwKSxcbiAgICAvLyBza2lwIHBhcnRzWzZdID09ICd0eXAnXG4gICAgdHlwZTogcGFydHNbN11cbiAgfTtcblxuICBmb3IgKHZhciBpID0gODsgaSA8IHBhcnRzLmxlbmd0aDsgaSArPSAyKSB7XG4gICAgc3dpdGNoIChwYXJ0c1tpXSkge1xuICAgICAgY2FzZSAncmFkZHInOlxuICAgICAgICBjYW5kaWRhdGUucmVsYXRlZEFkZHJlc3MgPSBwYXJ0c1tpICsgMV07XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAncnBvcnQnOlxuICAgICAgICBjYW5kaWRhdGUucmVsYXRlZFBvcnQgPSBwYXJzZUludChwYXJ0c1tpICsgMV0sIDEwKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd0Y3B0eXBlJzpcbiAgICAgICAgY2FuZGlkYXRlLnRjcFR5cGUgPSBwYXJ0c1tpICsgMV07XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAndWZyYWcnOlxuICAgICAgICBjYW5kaWRhdGUudWZyYWcgPSBwYXJ0c1tpICsgMV07IC8vIGZvciBiYWNrd2FyZCBjb21wYWJpbGl0eS5cbiAgICAgICAgY2FuZGlkYXRlLnVzZXJuYW1lRnJhZ21lbnQgPSBwYXJ0c1tpICsgMV07XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDogLy8gZXh0ZW5zaW9uIGhhbmRsaW5nLCBpbiBwYXJ0aWN1bGFyIHVmcmFnXG4gICAgICAgIGNhbmRpZGF0ZVtwYXJ0c1tpXV0gPSBwYXJ0c1tpICsgMV07XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuICByZXR1cm4gY2FuZGlkYXRlO1xufTtcblxuLy8gVHJhbnNsYXRlcyBhIGNhbmRpZGF0ZSBvYmplY3QgaW50byBTRFAgY2FuZGlkYXRlIGF0dHJpYnV0ZS5cblNEUFV0aWxzLndyaXRlQ2FuZGlkYXRlID0gZnVuY3Rpb24oY2FuZGlkYXRlKSB7XG4gIHZhciBzZHAgPSBbXTtcbiAgc2RwLnB1c2goY2FuZGlkYXRlLmZvdW5kYXRpb24pO1xuICBzZHAucHVzaChjYW5kaWRhdGUuY29tcG9uZW50KTtcbiAgc2RwLnB1c2goY2FuZGlkYXRlLnByb3RvY29sLnRvVXBwZXJDYXNlKCkpO1xuICBzZHAucHVzaChjYW5kaWRhdGUucHJpb3JpdHkpO1xuICBzZHAucHVzaChjYW5kaWRhdGUuaXApO1xuICBzZHAucHVzaChjYW5kaWRhdGUucG9ydCk7XG5cbiAgdmFyIHR5cGUgPSBjYW5kaWRhdGUudHlwZTtcbiAgc2RwLnB1c2goJ3R5cCcpO1xuICBzZHAucHVzaCh0eXBlKTtcbiAgaWYgKHR5cGUgIT09ICdob3N0JyAmJiBjYW5kaWRhdGUucmVsYXRlZEFkZHJlc3MgJiZcbiAgICAgIGNhbmRpZGF0ZS5yZWxhdGVkUG9ydCkge1xuICAgIHNkcC5wdXNoKCdyYWRkcicpO1xuICAgIHNkcC5wdXNoKGNhbmRpZGF0ZS5yZWxhdGVkQWRkcmVzcyk7IC8vIHdhczogcmVsQWRkclxuICAgIHNkcC5wdXNoKCdycG9ydCcpO1xuICAgIHNkcC5wdXNoKGNhbmRpZGF0ZS5yZWxhdGVkUG9ydCk7IC8vIHdhczogcmVsUG9ydFxuICB9XG4gIGlmIChjYW5kaWRhdGUudGNwVHlwZSAmJiBjYW5kaWRhdGUucHJvdG9jb2wudG9Mb3dlckNhc2UoKSA9PT0gJ3RjcCcpIHtcbiAgICBzZHAucHVzaCgndGNwdHlwZScpO1xuICAgIHNkcC5wdXNoKGNhbmRpZGF0ZS50Y3BUeXBlKTtcbiAgfVxuICBpZiAoY2FuZGlkYXRlLnVzZXJuYW1lRnJhZ21lbnQgfHwgY2FuZGlkYXRlLnVmcmFnKSB7XG4gICAgc2RwLnB1c2goJ3VmcmFnJyk7XG4gICAgc2RwLnB1c2goY2FuZGlkYXRlLnVzZXJuYW1lRnJhZ21lbnQgfHwgY2FuZGlkYXRlLnVmcmFnKTtcbiAgfVxuICByZXR1cm4gJ2NhbmRpZGF0ZTonICsgc2RwLmpvaW4oJyAnKTtcbn07XG5cbi8vIFBhcnNlcyBhbiBpY2Utb3B0aW9ucyBsaW5lLCByZXR1cm5zIGFuIGFycmF5IG9mIG9wdGlvbiB0YWdzLlxuLy8gYT1pY2Utb3B0aW9uczpmb28gYmFyXG5TRFBVdGlscy5wYXJzZUljZU9wdGlvbnMgPSBmdW5jdGlvbihsaW5lKSB7XG4gIHJldHVybiBsaW5lLnN1YnN0cigxNCkuc3BsaXQoJyAnKTtcbn1cblxuLy8gUGFyc2VzIGFuIHJ0cG1hcCBsaW5lLCByZXR1cm5zIFJUQ1J0cENvZGRlY1BhcmFtZXRlcnMuIFNhbXBsZSBpbnB1dDpcbi8vIGE9cnRwbWFwOjExMSBvcHVzLzQ4MDAwLzJcblNEUFV0aWxzLnBhcnNlUnRwTWFwID0gZnVuY3Rpb24obGluZSkge1xuICB2YXIgcGFydHMgPSBsaW5lLnN1YnN0cig5KS5zcGxpdCgnICcpO1xuICB2YXIgcGFyc2VkID0ge1xuICAgIHBheWxvYWRUeXBlOiBwYXJzZUludChwYXJ0cy5zaGlmdCgpLCAxMCkgLy8gd2FzOiBpZFxuICB9O1xuXG4gIHBhcnRzID0gcGFydHNbMF0uc3BsaXQoJy8nKTtcblxuICBwYXJzZWQubmFtZSA9IHBhcnRzWzBdO1xuICBwYXJzZWQuY2xvY2tSYXRlID0gcGFyc2VJbnQocGFydHNbMV0sIDEwKTsgLy8gd2FzOiBjbG9ja3JhdGVcbiAgLy8gd2FzOiBjaGFubmVsc1xuICBwYXJzZWQubnVtQ2hhbm5lbHMgPSBwYXJ0cy5sZW5ndGggPT09IDMgPyBwYXJzZUludChwYXJ0c1syXSwgMTApIDogMTtcbiAgcmV0dXJuIHBhcnNlZDtcbn07XG5cbi8vIEdlbmVyYXRlIGFuIGE9cnRwbWFwIGxpbmUgZnJvbSBSVENSdHBDb2RlY0NhcGFiaWxpdHkgb3Jcbi8vIFJUQ1J0cENvZGVjUGFyYW1ldGVycy5cblNEUFV0aWxzLndyaXRlUnRwTWFwID0gZnVuY3Rpb24oY29kZWMpIHtcbiAgdmFyIHB0ID0gY29kZWMucGF5bG9hZFR5cGU7XG4gIGlmIChjb2RlYy5wcmVmZXJyZWRQYXlsb2FkVHlwZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcHQgPSBjb2RlYy5wcmVmZXJyZWRQYXlsb2FkVHlwZTtcbiAgfVxuICByZXR1cm4gJ2E9cnRwbWFwOicgKyBwdCArICcgJyArIGNvZGVjLm5hbWUgKyAnLycgKyBjb2RlYy5jbG9ja1JhdGUgK1xuICAgICAgKGNvZGVjLm51bUNoYW5uZWxzICE9PSAxID8gJy8nICsgY29kZWMubnVtQ2hhbm5lbHMgOiAnJykgKyAnXFxyXFxuJztcbn07XG5cbi8vIFBhcnNlcyBhbiBhPWV4dG1hcCBsaW5lIChoZWFkZXJleHRlbnNpb24gZnJvbSBSRkMgNTI4NSkuIFNhbXBsZSBpbnB1dDpcbi8vIGE9ZXh0bWFwOjIgdXJuOmlldGY6cGFyYW1zOnJ0cC1oZHJleHQ6dG9mZnNldFxuLy8gYT1leHRtYXA6Mi9zZW5kb25seSB1cm46aWV0ZjpwYXJhbXM6cnRwLWhkcmV4dDp0b2Zmc2V0XG5TRFBVdGlscy5wYXJzZUV4dG1hcCA9IGZ1bmN0aW9uKGxpbmUpIHtcbiAgdmFyIHBhcnRzID0gbGluZS5zdWJzdHIoOSkuc3BsaXQoJyAnKTtcbiAgcmV0dXJuIHtcbiAgICBpZDogcGFyc2VJbnQocGFydHNbMF0sIDEwKSxcbiAgICBkaXJlY3Rpb246IHBhcnRzWzBdLmluZGV4T2YoJy8nKSA+IDAgPyBwYXJ0c1swXS5zcGxpdCgnLycpWzFdIDogJ3NlbmRyZWN2JyxcbiAgICB1cmk6IHBhcnRzWzFdXG4gIH07XG59O1xuXG4vLyBHZW5lcmF0ZXMgYT1leHRtYXAgbGluZSBmcm9tIFJUQ1J0cEhlYWRlckV4dGVuc2lvblBhcmFtZXRlcnMgb3Jcbi8vIFJUQ1J0cEhlYWRlckV4dGVuc2lvbi5cblNEUFV0aWxzLndyaXRlRXh0bWFwID0gZnVuY3Rpb24oaGVhZGVyRXh0ZW5zaW9uKSB7XG4gIHJldHVybiAnYT1leHRtYXA6JyArIChoZWFkZXJFeHRlbnNpb24uaWQgfHwgaGVhZGVyRXh0ZW5zaW9uLnByZWZlcnJlZElkKSArXG4gICAgICAoaGVhZGVyRXh0ZW5zaW9uLmRpcmVjdGlvbiAmJiBoZWFkZXJFeHRlbnNpb24uZGlyZWN0aW9uICE9PSAnc2VuZHJlY3YnXG4gICAgICAgICAgPyAnLycgKyBoZWFkZXJFeHRlbnNpb24uZGlyZWN0aW9uXG4gICAgICAgICAgOiAnJykgK1xuICAgICAgJyAnICsgaGVhZGVyRXh0ZW5zaW9uLnVyaSArICdcXHJcXG4nO1xufTtcblxuLy8gUGFyc2VzIGFuIGZ0bXAgbGluZSwgcmV0dXJucyBkaWN0aW9uYXJ5LiBTYW1wbGUgaW5wdXQ6XG4vLyBhPWZtdHA6OTYgdmJyPW9uO2NuZz1vblxuLy8gQWxzbyBkZWFscyB3aXRoIHZicj1vbjsgY25nPW9uXG5TRFBVdGlscy5wYXJzZUZtdHAgPSBmdW5jdGlvbihsaW5lKSB7XG4gIHZhciBwYXJzZWQgPSB7fTtcbiAgdmFyIGt2O1xuICB2YXIgcGFydHMgPSBsaW5lLnN1YnN0cihsaW5lLmluZGV4T2YoJyAnKSArIDEpLnNwbGl0KCc7Jyk7XG4gIGZvciAodmFyIGogPSAwOyBqIDwgcGFydHMubGVuZ3RoOyBqKyspIHtcbiAgICBrdiA9IHBhcnRzW2pdLnRyaW0oKS5zcGxpdCgnPScpO1xuICAgIHBhcnNlZFtrdlswXS50cmltKCldID0ga3ZbMV07XG4gIH1cbiAgcmV0dXJuIHBhcnNlZDtcbn07XG5cbi8vIEdlbmVyYXRlcyBhbiBhPWZ0bXAgbGluZSBmcm9tIFJUQ1J0cENvZGVjQ2FwYWJpbGl0eSBvciBSVENSdHBDb2RlY1BhcmFtZXRlcnMuXG5TRFBVdGlscy53cml0ZUZtdHAgPSBmdW5jdGlvbihjb2RlYykge1xuICB2YXIgbGluZSA9ICcnO1xuICB2YXIgcHQgPSBjb2RlYy5wYXlsb2FkVHlwZTtcbiAgaWYgKGNvZGVjLnByZWZlcnJlZFBheWxvYWRUeXBlICE9PSB1bmRlZmluZWQpIHtcbiAgICBwdCA9IGNvZGVjLnByZWZlcnJlZFBheWxvYWRUeXBlO1xuICB9XG4gIGlmIChjb2RlYy5wYXJhbWV0ZXJzICYmIE9iamVjdC5rZXlzKGNvZGVjLnBhcmFtZXRlcnMpLmxlbmd0aCkge1xuICAgIHZhciBwYXJhbXMgPSBbXTtcbiAgICBPYmplY3Qua2V5cyhjb2RlYy5wYXJhbWV0ZXJzKS5mb3JFYWNoKGZ1bmN0aW9uKHBhcmFtKSB7XG4gICAgICBwYXJhbXMucHVzaChwYXJhbSArICc9JyArIGNvZGVjLnBhcmFtZXRlcnNbcGFyYW1dKTtcbiAgICB9KTtcbiAgICBsaW5lICs9ICdhPWZtdHA6JyArIHB0ICsgJyAnICsgcGFyYW1zLmpvaW4oJzsnKSArICdcXHJcXG4nO1xuICB9XG4gIHJldHVybiBsaW5lO1xufTtcblxuLy8gUGFyc2VzIGFuIHJ0Y3AtZmIgbGluZSwgcmV0dXJucyBSVENQUnRjcEZlZWRiYWNrIG9iamVjdC4gU2FtcGxlIGlucHV0OlxuLy8gYT1ydGNwLWZiOjk4IG5hY2sgcnBzaVxuU0RQVXRpbHMucGFyc2VSdGNwRmIgPSBmdW5jdGlvbihsaW5lKSB7XG4gIHZhciBwYXJ0cyA9IGxpbmUuc3Vic3RyKGxpbmUuaW5kZXhPZignICcpICsgMSkuc3BsaXQoJyAnKTtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBwYXJ0cy5zaGlmdCgpLFxuICAgIHBhcmFtZXRlcjogcGFydHMuam9pbignICcpXG4gIH07XG59O1xuLy8gR2VuZXJhdGUgYT1ydGNwLWZiIGxpbmVzIGZyb20gUlRDUnRwQ29kZWNDYXBhYmlsaXR5IG9yIFJUQ1J0cENvZGVjUGFyYW1ldGVycy5cblNEUFV0aWxzLndyaXRlUnRjcEZiID0gZnVuY3Rpb24oY29kZWMpIHtcbiAgdmFyIGxpbmVzID0gJyc7XG4gIHZhciBwdCA9IGNvZGVjLnBheWxvYWRUeXBlO1xuICBpZiAoY29kZWMucHJlZmVycmVkUGF5bG9hZFR5cGUgIT09IHVuZGVmaW5lZCkge1xuICAgIHB0ID0gY29kZWMucHJlZmVycmVkUGF5bG9hZFR5cGU7XG4gIH1cbiAgaWYgKGNvZGVjLnJ0Y3BGZWVkYmFjayAmJiBjb2RlYy5ydGNwRmVlZGJhY2subGVuZ3RoKSB7XG4gICAgLy8gRklYTUU6IHNwZWNpYWwgaGFuZGxpbmcgZm9yIHRyci1pbnQ/XG4gICAgY29kZWMucnRjcEZlZWRiYWNrLmZvckVhY2goZnVuY3Rpb24oZmIpIHtcbiAgICAgIGxpbmVzICs9ICdhPXJ0Y3AtZmI6JyArIHB0ICsgJyAnICsgZmIudHlwZSArXG4gICAgICAoZmIucGFyYW1ldGVyICYmIGZiLnBhcmFtZXRlci5sZW5ndGggPyAnICcgKyBmYi5wYXJhbWV0ZXIgOiAnJykgK1xuICAgICAgICAgICdcXHJcXG4nO1xuICAgIH0pO1xuICB9XG4gIHJldHVybiBsaW5lcztcbn07XG5cbi8vIFBhcnNlcyBhbiBSRkMgNTU3NiBzc3JjIG1lZGlhIGF0dHJpYnV0ZS4gU2FtcGxlIGlucHV0OlxuLy8gYT1zc3JjOjM3MzU5Mjg1NTkgY25hbWU6c29tZXRoaW5nXG5TRFBVdGlscy5wYXJzZVNzcmNNZWRpYSA9IGZ1bmN0aW9uKGxpbmUpIHtcbiAgdmFyIHNwID0gbGluZS5pbmRleE9mKCcgJyk7XG4gIHZhciBwYXJ0cyA9IHtcbiAgICBzc3JjOiBwYXJzZUludChsaW5lLnN1YnN0cig3LCBzcCAtIDcpLCAxMClcbiAgfTtcbiAgdmFyIGNvbG9uID0gbGluZS5pbmRleE9mKCc6Jywgc3ApO1xuICBpZiAoY29sb24gPiAtMSkge1xuICAgIHBhcnRzLmF0dHJpYnV0ZSA9IGxpbmUuc3Vic3RyKHNwICsgMSwgY29sb24gLSBzcCAtIDEpO1xuICAgIHBhcnRzLnZhbHVlID0gbGluZS5zdWJzdHIoY29sb24gKyAxKTtcbiAgfSBlbHNlIHtcbiAgICBwYXJ0cy5hdHRyaWJ1dGUgPSBsaW5lLnN1YnN0cihzcCArIDEpO1xuICB9XG4gIHJldHVybiBwYXJ0cztcbn07XG5cbi8vIEV4dHJhY3RzIHRoZSBNSUQgKFJGQyA1ODg4KSBmcm9tIGEgbWVkaWEgc2VjdGlvbi5cbi8vIHJldHVybnMgdGhlIE1JRCBvciB1bmRlZmluZWQgaWYgbm8gbWlkIGxpbmUgd2FzIGZvdW5kLlxuU0RQVXRpbHMuZ2V0TWlkID0gZnVuY3Rpb24obWVkaWFTZWN0aW9uKSB7XG4gIHZhciBtaWQgPSBTRFBVdGlscy5tYXRjaFByZWZpeChtZWRpYVNlY3Rpb24sICdhPW1pZDonKVswXTtcbiAgaWYgKG1pZCkge1xuICAgIHJldHVybiBtaWQuc3Vic3RyKDYpO1xuICB9XG59XG5cblNEUFV0aWxzLnBhcnNlRmluZ2VycHJpbnQgPSBmdW5jdGlvbihsaW5lKSB7XG4gIHZhciBwYXJ0cyA9IGxpbmUuc3Vic3RyKDE0KS5zcGxpdCgnICcpO1xuICByZXR1cm4ge1xuICAgIGFsZ29yaXRobTogcGFydHNbMF0udG9Mb3dlckNhc2UoKSwgLy8gYWxnb3JpdGhtIGlzIGNhc2Utc2Vuc2l0aXZlIGluIEVkZ2UuXG4gICAgdmFsdWU6IHBhcnRzWzFdXG4gIH07XG59O1xuXG4vLyBFeHRyYWN0cyBEVExTIHBhcmFtZXRlcnMgZnJvbSBTRFAgbWVkaWEgc2VjdGlvbiBvciBzZXNzaW9ucGFydC5cbi8vIEZJWE1FOiBmb3IgY29uc2lzdGVuY3kgd2l0aCBvdGhlciBmdW5jdGlvbnMgdGhpcyBzaG91bGQgb25seVxuLy8gICBnZXQgdGhlIGZpbmdlcnByaW50IGxpbmUgYXMgaW5wdXQuIFNlZSBhbHNvIGdldEljZVBhcmFtZXRlcnMuXG5TRFBVdGlscy5nZXREdGxzUGFyYW1ldGVycyA9IGZ1bmN0aW9uKG1lZGlhU2VjdGlvbiwgc2Vzc2lvbnBhcnQpIHtcbiAgdmFyIGxpbmVzID0gU0RQVXRpbHMubWF0Y2hQcmVmaXgobWVkaWFTZWN0aW9uICsgc2Vzc2lvbnBhcnQsXG4gICAgICAnYT1maW5nZXJwcmludDonKTtcbiAgLy8gTm90ZTogYT1zZXR1cCBsaW5lIGlzIGlnbm9yZWQgc2luY2Ugd2UgdXNlIHRoZSAnYXV0bycgcm9sZS5cbiAgLy8gTm90ZTI6ICdhbGdvcml0aG0nIGlzIG5vdCBjYXNlIHNlbnNpdGl2ZSBleGNlcHQgaW4gRWRnZS5cbiAgcmV0dXJuIHtcbiAgICByb2xlOiAnYXV0bycsXG4gICAgZmluZ2VycHJpbnRzOiBsaW5lcy5tYXAoU0RQVXRpbHMucGFyc2VGaW5nZXJwcmludClcbiAgfTtcbn07XG5cbi8vIFNlcmlhbGl6ZXMgRFRMUyBwYXJhbWV0ZXJzIHRvIFNEUC5cblNEUFV0aWxzLndyaXRlRHRsc1BhcmFtZXRlcnMgPSBmdW5jdGlvbihwYXJhbXMsIHNldHVwVHlwZSkge1xuICB2YXIgc2RwID0gJ2E9c2V0dXA6JyArIHNldHVwVHlwZSArICdcXHJcXG4nO1xuICBwYXJhbXMuZmluZ2VycHJpbnRzLmZvckVhY2goZnVuY3Rpb24oZnApIHtcbiAgICBzZHAgKz0gJ2E9ZmluZ2VycHJpbnQ6JyArIGZwLmFsZ29yaXRobSArICcgJyArIGZwLnZhbHVlICsgJ1xcclxcbic7XG4gIH0pO1xuICByZXR1cm4gc2RwO1xufTtcbi8vIFBhcnNlcyBJQ0UgaW5mb3JtYXRpb24gZnJvbSBTRFAgbWVkaWEgc2VjdGlvbiBvciBzZXNzaW9ucGFydC5cbi8vIEZJWE1FOiBmb3IgY29uc2lzdGVuY3kgd2l0aCBvdGhlciBmdW5jdGlvbnMgdGhpcyBzaG91bGQgb25seVxuLy8gICBnZXQgdGhlIGljZS11ZnJhZyBhbmQgaWNlLXB3ZCBsaW5lcyBhcyBpbnB1dC5cblNEUFV0aWxzLmdldEljZVBhcmFtZXRlcnMgPSBmdW5jdGlvbihtZWRpYVNlY3Rpb24sIHNlc3Npb25wYXJ0KSB7XG4gIHZhciBsaW5lcyA9IFNEUFV0aWxzLnNwbGl0TGluZXMobWVkaWFTZWN0aW9uKTtcbiAgLy8gU2VhcmNoIGluIHNlc3Npb24gcGFydCwgdG9vLlxuICBsaW5lcyA9IGxpbmVzLmNvbmNhdChTRFBVdGlscy5zcGxpdExpbmVzKHNlc3Npb25wYXJ0KSk7XG4gIHZhciBpY2VQYXJhbWV0ZXJzID0ge1xuICAgIHVzZXJuYW1lRnJhZ21lbnQ6IGxpbmVzLmZpbHRlcihmdW5jdGlvbihsaW5lKSB7XG4gICAgICByZXR1cm4gbGluZS5pbmRleE9mKCdhPWljZS11ZnJhZzonKSA9PT0gMDtcbiAgICB9KVswXS5zdWJzdHIoMTIpLFxuICAgIHBhc3N3b3JkOiBsaW5lcy5maWx0ZXIoZnVuY3Rpb24obGluZSkge1xuICAgICAgcmV0dXJuIGxpbmUuaW5kZXhPZignYT1pY2UtcHdkOicpID09PSAwO1xuICAgIH0pWzBdLnN1YnN0cigxMClcbiAgfTtcbiAgcmV0dXJuIGljZVBhcmFtZXRlcnM7XG59O1xuXG4vLyBTZXJpYWxpemVzIElDRSBwYXJhbWV0ZXJzIHRvIFNEUC5cblNEUFV0aWxzLndyaXRlSWNlUGFyYW1ldGVycyA9IGZ1bmN0aW9uKHBhcmFtcykge1xuICByZXR1cm4gJ2E9aWNlLXVmcmFnOicgKyBwYXJhbXMudXNlcm5hbWVGcmFnbWVudCArICdcXHJcXG4nICtcbiAgICAgICdhPWljZS1wd2Q6JyArIHBhcmFtcy5wYXNzd29yZCArICdcXHJcXG4nO1xufTtcblxuLy8gUGFyc2VzIHRoZSBTRFAgbWVkaWEgc2VjdGlvbiBhbmQgcmV0dXJucyBSVENSdHBQYXJhbWV0ZXJzLlxuU0RQVXRpbHMucGFyc2VSdHBQYXJhbWV0ZXJzID0gZnVuY3Rpb24obWVkaWFTZWN0aW9uKSB7XG4gIHZhciBkZXNjcmlwdGlvbiA9IHtcbiAgICBjb2RlY3M6IFtdLFxuICAgIGhlYWRlckV4dGVuc2lvbnM6IFtdLFxuICAgIGZlY01lY2hhbmlzbXM6IFtdLFxuICAgIHJ0Y3A6IFtdXG4gIH07XG4gIHZhciBsaW5lcyA9IFNEUFV0aWxzLnNwbGl0TGluZXMobWVkaWFTZWN0aW9uKTtcbiAgdmFyIG1saW5lID0gbGluZXNbMF0uc3BsaXQoJyAnKTtcbiAgZm9yICh2YXIgaSA9IDM7IGkgPCBtbGluZS5sZW5ndGg7IGkrKykgeyAvLyBmaW5kIGFsbCBjb2RlY3MgZnJvbSBtbGluZVszLi5dXG4gICAgdmFyIHB0ID0gbWxpbmVbaV07XG4gICAgdmFyIHJ0cG1hcGxpbmUgPSBTRFBVdGlscy5tYXRjaFByZWZpeChcbiAgICAgICAgbWVkaWFTZWN0aW9uLCAnYT1ydHBtYXA6JyArIHB0ICsgJyAnKVswXTtcbiAgICBpZiAocnRwbWFwbGluZSkge1xuICAgICAgdmFyIGNvZGVjID0gU0RQVXRpbHMucGFyc2VSdHBNYXAocnRwbWFwbGluZSk7XG4gICAgICB2YXIgZm10cHMgPSBTRFBVdGlscy5tYXRjaFByZWZpeChcbiAgICAgICAgICBtZWRpYVNlY3Rpb24sICdhPWZtdHA6JyArIHB0ICsgJyAnKTtcbiAgICAgIC8vIE9ubHkgdGhlIGZpcnN0IGE9Zm10cDo8cHQ+IGlzIGNvbnNpZGVyZWQuXG4gICAgICBjb2RlYy5wYXJhbWV0ZXJzID0gZm10cHMubGVuZ3RoID8gU0RQVXRpbHMucGFyc2VGbXRwKGZtdHBzWzBdKSA6IHt9O1xuICAgICAgY29kZWMucnRjcEZlZWRiYWNrID0gU0RQVXRpbHMubWF0Y2hQcmVmaXgoXG4gICAgICAgICAgbWVkaWFTZWN0aW9uLCAnYT1ydGNwLWZiOicgKyBwdCArICcgJylcbiAgICAgICAgLm1hcChTRFBVdGlscy5wYXJzZVJ0Y3BGYik7XG4gICAgICBkZXNjcmlwdGlvbi5jb2RlY3MucHVzaChjb2RlYyk7XG4gICAgICAvLyBwYXJzZSBGRUMgbWVjaGFuaXNtcyBmcm9tIHJ0cG1hcCBsaW5lcy5cbiAgICAgIHN3aXRjaCAoY29kZWMubmFtZS50b1VwcGVyQ2FzZSgpKSB7XG4gICAgICAgIGNhc2UgJ1JFRCc6XG4gICAgICAgIGNhc2UgJ1VMUEZFQyc6XG4gICAgICAgICAgZGVzY3JpcHRpb24uZmVjTWVjaGFuaXNtcy5wdXNoKGNvZGVjLm5hbWUudG9VcHBlckNhc2UoKSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6IC8vIG9ubHkgUkVEIGFuZCBVTFBGRUMgYXJlIHJlY29nbml6ZWQgYXMgRkVDIG1lY2hhbmlzbXMuXG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIFNEUFV0aWxzLm1hdGNoUHJlZml4KG1lZGlhU2VjdGlvbiwgJ2E9ZXh0bWFwOicpLmZvckVhY2goZnVuY3Rpb24obGluZSkge1xuICAgIGRlc2NyaXB0aW9uLmhlYWRlckV4dGVuc2lvbnMucHVzaChTRFBVdGlscy5wYXJzZUV4dG1hcChsaW5lKSk7XG4gIH0pO1xuICAvLyBGSVhNRTogcGFyc2UgcnRjcC5cbiAgcmV0dXJuIGRlc2NyaXB0aW9uO1xufTtcblxuLy8gR2VuZXJhdGVzIHBhcnRzIG9mIHRoZSBTRFAgbWVkaWEgc2VjdGlvbiBkZXNjcmliaW5nIHRoZSBjYXBhYmlsaXRpZXMgL1xuLy8gcGFyYW1ldGVycy5cblNEUFV0aWxzLndyaXRlUnRwRGVzY3JpcHRpb24gPSBmdW5jdGlvbihraW5kLCBjYXBzKSB7XG4gIHZhciBzZHAgPSAnJztcblxuICAvLyBCdWlsZCB0aGUgbWxpbmUuXG4gIHNkcCArPSAnbT0nICsga2luZCArICcgJztcbiAgc2RwICs9IGNhcHMuY29kZWNzLmxlbmd0aCA+IDAgPyAnOScgOiAnMCc7IC8vIHJlamVjdCBpZiBubyBjb2RlY3MuXG4gIHNkcCArPSAnIFVEUC9UTFMvUlRQL1NBVlBGICc7XG4gIHNkcCArPSBjYXBzLmNvZGVjcy5tYXAoZnVuY3Rpb24oY29kZWMpIHtcbiAgICBpZiAoY29kZWMucHJlZmVycmVkUGF5bG9hZFR5cGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIGNvZGVjLnByZWZlcnJlZFBheWxvYWRUeXBlO1xuICAgIH1cbiAgICByZXR1cm4gY29kZWMucGF5bG9hZFR5cGU7XG4gIH0pLmpvaW4oJyAnKSArICdcXHJcXG4nO1xuXG4gIHNkcCArPSAnYz1JTiBJUDQgMC4wLjAuMFxcclxcbic7XG4gIHNkcCArPSAnYT1ydGNwOjkgSU4gSVA0IDAuMC4wLjBcXHJcXG4nO1xuXG4gIC8vIEFkZCBhPXJ0cG1hcCBsaW5lcyBmb3IgZWFjaCBjb2RlYy4gQWxzbyBmbXRwIGFuZCBydGNwLWZiLlxuICBjYXBzLmNvZGVjcy5mb3JFYWNoKGZ1bmN0aW9uKGNvZGVjKSB7XG4gICAgc2RwICs9IFNEUFV0aWxzLndyaXRlUnRwTWFwKGNvZGVjKTtcbiAgICBzZHAgKz0gU0RQVXRpbHMud3JpdGVGbXRwKGNvZGVjKTtcbiAgICBzZHAgKz0gU0RQVXRpbHMud3JpdGVSdGNwRmIoY29kZWMpO1xuICB9KTtcbiAgdmFyIG1heHB0aW1lID0gMDtcbiAgY2Fwcy5jb2RlY3MuZm9yRWFjaChmdW5jdGlvbihjb2RlYykge1xuICAgIGlmIChjb2RlYy5tYXhwdGltZSA+IG1heHB0aW1lKSB7XG4gICAgICBtYXhwdGltZSA9IGNvZGVjLm1heHB0aW1lO1xuICAgIH1cbiAgfSk7XG4gIGlmIChtYXhwdGltZSA+IDApIHtcbiAgICBzZHAgKz0gJ2E9bWF4cHRpbWU6JyArIG1heHB0aW1lICsgJ1xcclxcbic7XG4gIH1cbiAgc2RwICs9ICdhPXJ0Y3AtbXV4XFxyXFxuJztcblxuICBjYXBzLmhlYWRlckV4dGVuc2lvbnMuZm9yRWFjaChmdW5jdGlvbihleHRlbnNpb24pIHtcbiAgICBzZHAgKz0gU0RQVXRpbHMud3JpdGVFeHRtYXAoZXh0ZW5zaW9uKTtcbiAgfSk7XG4gIC8vIEZJWE1FOiB3cml0ZSBmZWNNZWNoYW5pc21zLlxuICByZXR1cm4gc2RwO1xufTtcblxuLy8gUGFyc2VzIHRoZSBTRFAgbWVkaWEgc2VjdGlvbiBhbmQgcmV0dXJucyBhbiBhcnJheSBvZlxuLy8gUlRDUnRwRW5jb2RpbmdQYXJhbWV0ZXJzLlxuU0RQVXRpbHMucGFyc2VSdHBFbmNvZGluZ1BhcmFtZXRlcnMgPSBmdW5jdGlvbihtZWRpYVNlY3Rpb24pIHtcbiAgdmFyIGVuY29kaW5nUGFyYW1ldGVycyA9IFtdO1xuICB2YXIgZGVzY3JpcHRpb24gPSBTRFBVdGlscy5wYXJzZVJ0cFBhcmFtZXRlcnMobWVkaWFTZWN0aW9uKTtcbiAgdmFyIGhhc1JlZCA9IGRlc2NyaXB0aW9uLmZlY01lY2hhbmlzbXMuaW5kZXhPZignUkVEJykgIT09IC0xO1xuICB2YXIgaGFzVWxwZmVjID0gZGVzY3JpcHRpb24uZmVjTWVjaGFuaXNtcy5pbmRleE9mKCdVTFBGRUMnKSAhPT0gLTE7XG5cbiAgLy8gZmlsdGVyIGE9c3NyYzouLi4gY25hbWU6LCBpZ25vcmUgUGxhbkItbXNpZFxuICB2YXIgc3NyY3MgPSBTRFBVdGlscy5tYXRjaFByZWZpeChtZWRpYVNlY3Rpb24sICdhPXNzcmM6JylcbiAgLm1hcChmdW5jdGlvbihsaW5lKSB7XG4gICAgcmV0dXJuIFNEUFV0aWxzLnBhcnNlU3NyY01lZGlhKGxpbmUpO1xuICB9KVxuICAuZmlsdGVyKGZ1bmN0aW9uKHBhcnRzKSB7XG4gICAgcmV0dXJuIHBhcnRzLmF0dHJpYnV0ZSA9PT0gJ2NuYW1lJztcbiAgfSk7XG4gIHZhciBwcmltYXJ5U3NyYyA9IHNzcmNzLmxlbmd0aCA+IDAgJiYgc3NyY3NbMF0uc3NyYztcbiAgdmFyIHNlY29uZGFyeVNzcmM7XG5cbiAgdmFyIGZsb3dzID0gU0RQVXRpbHMubWF0Y2hQcmVmaXgobWVkaWFTZWN0aW9uLCAnYT1zc3JjLWdyb3VwOkZJRCcpXG4gIC5tYXAoZnVuY3Rpb24obGluZSkge1xuICAgIHZhciBwYXJ0cyA9IGxpbmUuc3BsaXQoJyAnKTtcbiAgICBwYXJ0cy5zaGlmdCgpO1xuICAgIHJldHVybiBwYXJ0cy5tYXAoZnVuY3Rpb24ocGFydCkge1xuICAgICAgcmV0dXJuIHBhcnNlSW50KHBhcnQsIDEwKTtcbiAgICB9KTtcbiAgfSk7XG4gIGlmIChmbG93cy5sZW5ndGggPiAwICYmIGZsb3dzWzBdLmxlbmd0aCA+IDEgJiYgZmxvd3NbMF1bMF0gPT09IHByaW1hcnlTc3JjKSB7XG4gICAgc2Vjb25kYXJ5U3NyYyA9IGZsb3dzWzBdWzFdO1xuICB9XG5cbiAgZGVzY3JpcHRpb24uY29kZWNzLmZvckVhY2goZnVuY3Rpb24oY29kZWMpIHtcbiAgICBpZiAoY29kZWMubmFtZS50b1VwcGVyQ2FzZSgpID09PSAnUlRYJyAmJiBjb2RlYy5wYXJhbWV0ZXJzLmFwdCkge1xuICAgICAgdmFyIGVuY1BhcmFtID0ge1xuICAgICAgICBzc3JjOiBwcmltYXJ5U3NyYyxcbiAgICAgICAgY29kZWNQYXlsb2FkVHlwZTogcGFyc2VJbnQoY29kZWMucGFyYW1ldGVycy5hcHQsIDEwKSxcbiAgICAgICAgcnR4OiB7XG4gICAgICAgICAgc3NyYzogc2Vjb25kYXJ5U3NyY1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgZW5jb2RpbmdQYXJhbWV0ZXJzLnB1c2goZW5jUGFyYW0pO1xuICAgICAgaWYgKGhhc1JlZCkge1xuICAgICAgICBlbmNQYXJhbSA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoZW5jUGFyYW0pKTtcbiAgICAgICAgZW5jUGFyYW0uZmVjID0ge1xuICAgICAgICAgIHNzcmM6IHNlY29uZGFyeVNzcmMsXG4gICAgICAgICAgbWVjaGFuaXNtOiBoYXNVbHBmZWMgPyAncmVkK3VscGZlYycgOiAncmVkJ1xuICAgICAgICB9O1xuICAgICAgICBlbmNvZGluZ1BhcmFtZXRlcnMucHVzaChlbmNQYXJhbSk7XG4gICAgICB9XG4gICAgfVxuICB9KTtcbiAgaWYgKGVuY29kaW5nUGFyYW1ldGVycy5sZW5ndGggPT09IDAgJiYgcHJpbWFyeVNzcmMpIHtcbiAgICBlbmNvZGluZ1BhcmFtZXRlcnMucHVzaCh7XG4gICAgICBzc3JjOiBwcmltYXJ5U3NyY1xuICAgIH0pO1xuICB9XG5cbiAgLy8gd2Ugc3VwcG9ydCBib3RoIGI9QVMgYW5kIGI9VElBUyBidXQgaW50ZXJwcmV0IEFTIGFzIFRJQVMuXG4gIHZhciBiYW5kd2lkdGggPSBTRFBVdGlscy5tYXRjaFByZWZpeChtZWRpYVNlY3Rpb24sICdiPScpO1xuICBpZiAoYmFuZHdpZHRoLmxlbmd0aCkge1xuICAgIGlmIChiYW5kd2lkdGhbMF0uaW5kZXhPZignYj1USUFTOicpID09PSAwKSB7XG4gICAgICBiYW5kd2lkdGggPSBwYXJzZUludChiYW5kd2lkdGhbMF0uc3Vic3RyKDcpLCAxMCk7XG4gICAgfSBlbHNlIGlmIChiYW5kd2lkdGhbMF0uaW5kZXhPZignYj1BUzonKSA9PT0gMCkge1xuICAgICAgLy8gdXNlIGZvcm11bGEgZnJvbSBKU0VQIHRvIGNvbnZlcnQgYj1BUyB0byBUSUFTIHZhbHVlLlxuICAgICAgYmFuZHdpZHRoID0gcGFyc2VJbnQoYmFuZHdpZHRoWzBdLnN1YnN0cig1KSwgMTApICogMTAwMCAqIDAuOTVcbiAgICAgICAgICAtICg1MCAqIDQwICogOCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGJhbmR3aWR0aCA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgZW5jb2RpbmdQYXJhbWV0ZXJzLmZvckVhY2goZnVuY3Rpb24ocGFyYW1zKSB7XG4gICAgICBwYXJhbXMubWF4Qml0cmF0ZSA9IGJhbmR3aWR0aDtcbiAgICB9KTtcbiAgfVxuICByZXR1cm4gZW5jb2RpbmdQYXJhbWV0ZXJzO1xufTtcblxuLy8gcGFyc2VzIGh0dHA6Ly9kcmFmdC5vcnRjLm9yZy8jcnRjcnRjcHBhcmFtZXRlcnMqXG5TRFBVdGlscy5wYXJzZVJ0Y3BQYXJhbWV0ZXJzID0gZnVuY3Rpb24obWVkaWFTZWN0aW9uKSB7XG4gIHZhciBydGNwUGFyYW1ldGVycyA9IHt9O1xuXG4gIHZhciBjbmFtZTtcbiAgLy8gR2V0cyB0aGUgZmlyc3QgU1NSQy4gTm90ZSB0aGF0IHdpdGggUlRYIHRoZXJlIG1pZ2h0IGJlIG11bHRpcGxlXG4gIC8vIFNTUkNzLlxuICB2YXIgcmVtb3RlU3NyYyA9IFNEUFV0aWxzLm1hdGNoUHJlZml4KG1lZGlhU2VjdGlvbiwgJ2E9c3NyYzonKVxuICAgICAgLm1hcChmdW5jdGlvbihsaW5lKSB7XG4gICAgICAgIHJldHVybiBTRFBVdGlscy5wYXJzZVNzcmNNZWRpYShsaW5lKTtcbiAgICAgIH0pXG4gICAgICAuZmlsdGVyKGZ1bmN0aW9uKG9iaikge1xuICAgICAgICByZXR1cm4gb2JqLmF0dHJpYnV0ZSA9PT0gJ2NuYW1lJztcbiAgICAgIH0pWzBdO1xuICBpZiAocmVtb3RlU3NyYykge1xuICAgIHJ0Y3BQYXJhbWV0ZXJzLmNuYW1lID0gcmVtb3RlU3NyYy52YWx1ZTtcbiAgICBydGNwUGFyYW1ldGVycy5zc3JjID0gcmVtb3RlU3NyYy5zc3JjO1xuICB9XG5cbiAgLy8gRWRnZSB1c2VzIHRoZSBjb21wb3VuZCBhdHRyaWJ1dGUgaW5zdGVhZCBvZiByZWR1Y2VkU2l6ZVxuICAvLyBjb21wb3VuZCBpcyAhcmVkdWNlZFNpemVcbiAgdmFyIHJzaXplID0gU0RQVXRpbHMubWF0Y2hQcmVmaXgobWVkaWFTZWN0aW9uLCAnYT1ydGNwLXJzaXplJyk7XG4gIHJ0Y3BQYXJhbWV0ZXJzLnJlZHVjZWRTaXplID0gcnNpemUubGVuZ3RoID4gMDtcbiAgcnRjcFBhcmFtZXRlcnMuY29tcG91bmQgPSByc2l6ZS5sZW5ndGggPT09IDA7XG5cbiAgLy8gcGFyc2VzIHRoZSBydGNwLW11eCBhdHRy0ZZidXRlLlxuICAvLyBOb3RlIHRoYXQgRWRnZSBkb2VzIG5vdCBzdXBwb3J0IHVubXV4ZWQgUlRDUC5cbiAgdmFyIG11eCA9IFNEUFV0aWxzLm1hdGNoUHJlZml4KG1lZGlhU2VjdGlvbiwgJ2E9cnRjcC1tdXgnKTtcbiAgcnRjcFBhcmFtZXRlcnMubXV4ID0gbXV4Lmxlbmd0aCA+IDA7XG5cbiAgcmV0dXJuIHJ0Y3BQYXJhbWV0ZXJzO1xufTtcblxuLy8gcGFyc2VzIGVpdGhlciBhPW1zaWQ6IG9yIGE9c3NyYzouLi4gbXNpZCBsaW5lcyBhbmQgcmV0dXJuc1xuLy8gdGhlIGlkIG9mIHRoZSBNZWRpYVN0cmVhbSBhbmQgTWVkaWFTdHJlYW1UcmFjay5cblNEUFV0aWxzLnBhcnNlTXNpZCA9IGZ1bmN0aW9uKG1lZGlhU2VjdGlvbikge1xuICB2YXIgcGFydHM7XG4gIHZhciBzcGVjID0gU0RQVXRpbHMubWF0Y2hQcmVmaXgobWVkaWFTZWN0aW9uLCAnYT1tc2lkOicpO1xuICBpZiAoc3BlYy5sZW5ndGggPT09IDEpIHtcbiAgICBwYXJ0cyA9IHNwZWNbMF0uc3Vic3RyKDcpLnNwbGl0KCcgJyk7XG4gICAgcmV0dXJuIHtzdHJlYW06IHBhcnRzWzBdLCB0cmFjazogcGFydHNbMV19O1xuICB9XG4gIHZhciBwbGFuQiA9IFNEUFV0aWxzLm1hdGNoUHJlZml4KG1lZGlhU2VjdGlvbiwgJ2E9c3NyYzonKVxuICAubWFwKGZ1bmN0aW9uKGxpbmUpIHtcbiAgICByZXR1cm4gU0RQVXRpbHMucGFyc2VTc3JjTWVkaWEobGluZSk7XG4gIH0pXG4gIC5maWx0ZXIoZnVuY3Rpb24ocGFydHMpIHtcbiAgICByZXR1cm4gcGFydHMuYXR0cmlidXRlID09PSAnbXNpZCc7XG4gIH0pO1xuICBpZiAocGxhbkIubGVuZ3RoID4gMCkge1xuICAgIHBhcnRzID0gcGxhbkJbMF0udmFsdWUuc3BsaXQoJyAnKTtcbiAgICByZXR1cm4ge3N0cmVhbTogcGFydHNbMF0sIHRyYWNrOiBwYXJ0c1sxXX07XG4gIH1cbn07XG5cbi8vIEdlbmVyYXRlIGEgc2Vzc2lvbiBJRCBmb3IgU0RQLlxuLy8gaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL2RyYWZ0LWlldGYtcnRjd2ViLWpzZXAtMjAjc2VjdGlvbi01LjIuMVxuLy8gcmVjb21tZW5kcyB1c2luZyBhIGNyeXB0b2dyYXBoaWNhbGx5IHJhbmRvbSArdmUgNjQtYml0IHZhbHVlXG4vLyBidXQgcmlnaHQgbm93IHRoaXMgc2hvdWxkIGJlIGFjY2VwdGFibGUgYW5kIHdpdGhpbiB0aGUgcmlnaHQgcmFuZ2VcblNEUFV0aWxzLmdlbmVyYXRlU2Vzc2lvbklkID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKCkuc3Vic3RyKDIsIDIxKTtcbn07XG5cbi8vIFdyaXRlIGJvaWxkZXIgcGxhdGUgZm9yIHN0YXJ0IG9mIFNEUFxuLy8gc2Vzc0lkIGFyZ3VtZW50IGlzIG9wdGlvbmFsIC0gaWYgbm90IHN1cHBsaWVkIGl0IHdpbGxcbi8vIGJlIGdlbmVyYXRlZCByYW5kb21seVxuLy8gc2Vzc1ZlcnNpb24gaXMgb3B0aW9uYWwgYW5kIGRlZmF1bHRzIHRvIDJcblNEUFV0aWxzLndyaXRlU2Vzc2lvbkJvaWxlcnBsYXRlID0gZnVuY3Rpb24oc2Vzc0lkLCBzZXNzVmVyKSB7XG4gIHZhciBzZXNzaW9uSWQ7XG4gIHZhciB2ZXJzaW9uID0gc2Vzc1ZlciAhPT0gdW5kZWZpbmVkID8gc2Vzc1ZlciA6IDI7XG4gIGlmIChzZXNzSWQpIHtcbiAgICBzZXNzaW9uSWQgPSBzZXNzSWQ7XG4gIH0gZWxzZSB7XG4gICAgc2Vzc2lvbklkID0gU0RQVXRpbHMuZ2VuZXJhdGVTZXNzaW9uSWQoKTtcbiAgfVxuICAvLyBGSVhNRTogc2Vzcy1pZCBzaG91bGQgYmUgYW4gTlRQIHRpbWVzdGFtcC5cbiAgcmV0dXJuICd2PTBcXHJcXG4nICtcbiAgICAgICdvPXRoaXNpc2FkYXB0ZXJvcnRjICcgKyBzZXNzaW9uSWQgKyAnICcgKyB2ZXJzaW9uICsgJyBJTiBJUDQgMTI3LjAuMC4xXFxyXFxuJyArXG4gICAgICAncz0tXFxyXFxuJyArXG4gICAgICAndD0wIDBcXHJcXG4nO1xufTtcblxuU0RQVXRpbHMud3JpdGVNZWRpYVNlY3Rpb24gPSBmdW5jdGlvbih0cmFuc2NlaXZlciwgY2FwcywgdHlwZSwgc3RyZWFtKSB7XG4gIHZhciBzZHAgPSBTRFBVdGlscy53cml0ZVJ0cERlc2NyaXB0aW9uKHRyYW5zY2VpdmVyLmtpbmQsIGNhcHMpO1xuXG4gIC8vIE1hcCBJQ0UgcGFyYW1ldGVycyAodWZyYWcsIHB3ZCkgdG8gU0RQLlxuICBzZHAgKz0gU0RQVXRpbHMud3JpdGVJY2VQYXJhbWV0ZXJzKFxuICAgICAgdHJhbnNjZWl2ZXIuaWNlR2F0aGVyZXIuZ2V0TG9jYWxQYXJhbWV0ZXJzKCkpO1xuXG4gIC8vIE1hcCBEVExTIHBhcmFtZXRlcnMgdG8gU0RQLlxuICBzZHAgKz0gU0RQVXRpbHMud3JpdGVEdGxzUGFyYW1ldGVycyhcbiAgICAgIHRyYW5zY2VpdmVyLmR0bHNUcmFuc3BvcnQuZ2V0TG9jYWxQYXJhbWV0ZXJzKCksXG4gICAgICB0eXBlID09PSAnb2ZmZXInID8gJ2FjdHBhc3MnIDogJ2FjdGl2ZScpO1xuXG4gIHNkcCArPSAnYT1taWQ6JyArIHRyYW5zY2VpdmVyLm1pZCArICdcXHJcXG4nO1xuXG4gIGlmICh0cmFuc2NlaXZlci5kaXJlY3Rpb24pIHtcbiAgICBzZHAgKz0gJ2E9JyArIHRyYW5zY2VpdmVyLmRpcmVjdGlvbiArICdcXHJcXG4nO1xuICB9IGVsc2UgaWYgKHRyYW5zY2VpdmVyLnJ0cFNlbmRlciAmJiB0cmFuc2NlaXZlci5ydHBSZWNlaXZlcikge1xuICAgIHNkcCArPSAnYT1zZW5kcmVjdlxcclxcbic7XG4gIH0gZWxzZSBpZiAodHJhbnNjZWl2ZXIucnRwU2VuZGVyKSB7XG4gICAgc2RwICs9ICdhPXNlbmRvbmx5XFxyXFxuJztcbiAgfSBlbHNlIGlmICh0cmFuc2NlaXZlci5ydHBSZWNlaXZlcikge1xuICAgIHNkcCArPSAnYT1yZWN2b25seVxcclxcbic7XG4gIH0gZWxzZSB7XG4gICAgc2RwICs9ICdhPWluYWN0aXZlXFxyXFxuJztcbiAgfVxuXG4gIGlmICh0cmFuc2NlaXZlci5ydHBTZW5kZXIpIHtcbiAgICAvLyBzcGVjLlxuICAgIHZhciBtc2lkID0gJ21zaWQ6JyArIHN0cmVhbS5pZCArICcgJyArXG4gICAgICAgIHRyYW5zY2VpdmVyLnJ0cFNlbmRlci50cmFjay5pZCArICdcXHJcXG4nO1xuICAgIHNkcCArPSAnYT0nICsgbXNpZDtcblxuICAgIC8vIGZvciBDaHJvbWUuXG4gICAgc2RwICs9ICdhPXNzcmM6JyArIHRyYW5zY2VpdmVyLnNlbmRFbmNvZGluZ1BhcmFtZXRlcnNbMF0uc3NyYyArXG4gICAgICAgICcgJyArIG1zaWQ7XG4gICAgaWYgKHRyYW5zY2VpdmVyLnNlbmRFbmNvZGluZ1BhcmFtZXRlcnNbMF0ucnR4KSB7XG4gICAgICBzZHAgKz0gJ2E9c3NyYzonICsgdHJhbnNjZWl2ZXIuc2VuZEVuY29kaW5nUGFyYW1ldGVyc1swXS5ydHguc3NyYyArXG4gICAgICAgICAgJyAnICsgbXNpZDtcbiAgICAgIHNkcCArPSAnYT1zc3JjLWdyb3VwOkZJRCAnICtcbiAgICAgICAgICB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzWzBdLnNzcmMgKyAnICcgK1xuICAgICAgICAgIHRyYW5zY2VpdmVyLnNlbmRFbmNvZGluZ1BhcmFtZXRlcnNbMF0ucnR4LnNzcmMgK1xuICAgICAgICAgICdcXHJcXG4nO1xuICAgIH1cbiAgfVxuICAvLyBGSVhNRTogdGhpcyBzaG91bGQgYmUgd3JpdHRlbiBieSB3cml0ZVJ0cERlc2NyaXB0aW9uLlxuICBzZHAgKz0gJ2E9c3NyYzonICsgdHJhbnNjZWl2ZXIuc2VuZEVuY29kaW5nUGFyYW1ldGVyc1swXS5zc3JjICtcbiAgICAgICcgY25hbWU6JyArIFNEUFV0aWxzLmxvY2FsQ05hbWUgKyAnXFxyXFxuJztcbiAgaWYgKHRyYW5zY2VpdmVyLnJ0cFNlbmRlciAmJiB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzWzBdLnJ0eCkge1xuICAgIHNkcCArPSAnYT1zc3JjOicgKyB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzWzBdLnJ0eC5zc3JjICtcbiAgICAgICAgJyBjbmFtZTonICsgU0RQVXRpbHMubG9jYWxDTmFtZSArICdcXHJcXG4nO1xuICB9XG4gIHJldHVybiBzZHA7XG59O1xuXG4vLyBHZXRzIHRoZSBkaXJlY3Rpb24gZnJvbSB0aGUgbWVkaWFTZWN0aW9uIG9yIHRoZSBzZXNzaW9ucGFydC5cblNEUFV0aWxzLmdldERpcmVjdGlvbiA9IGZ1bmN0aW9uKG1lZGlhU2VjdGlvbiwgc2Vzc2lvbnBhcnQpIHtcbiAgLy8gTG9vayBmb3Igc2VuZHJlY3YsIHNlbmRvbmx5LCByZWN2b25seSwgaW5hY3RpdmUsIGRlZmF1bHQgdG8gc2VuZHJlY3YuXG4gIHZhciBsaW5lcyA9IFNEUFV0aWxzLnNwbGl0TGluZXMobWVkaWFTZWN0aW9uKTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgIHN3aXRjaCAobGluZXNbaV0pIHtcbiAgICAgIGNhc2UgJ2E9c2VuZHJlY3YnOlxuICAgICAgY2FzZSAnYT1zZW5kb25seSc6XG4gICAgICBjYXNlICdhPXJlY3Zvbmx5JzpcbiAgICAgIGNhc2UgJ2E9aW5hY3RpdmUnOlxuICAgICAgICByZXR1cm4gbGluZXNbaV0uc3Vic3RyKDIpO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgLy8gRklYTUU6IFdoYXQgc2hvdWxkIGhhcHBlbiBoZXJlP1xuICAgIH1cbiAgfVxuICBpZiAoc2Vzc2lvbnBhcnQpIHtcbiAgICByZXR1cm4gU0RQVXRpbHMuZ2V0RGlyZWN0aW9uKHNlc3Npb25wYXJ0KTtcbiAgfVxuICByZXR1cm4gJ3NlbmRyZWN2Jztcbn07XG5cblNEUFV0aWxzLmdldEtpbmQgPSBmdW5jdGlvbihtZWRpYVNlY3Rpb24pIHtcbiAgdmFyIGxpbmVzID0gU0RQVXRpbHMuc3BsaXRMaW5lcyhtZWRpYVNlY3Rpb24pO1xuICB2YXIgbWxpbmUgPSBsaW5lc1swXS5zcGxpdCgnICcpO1xuICByZXR1cm4gbWxpbmVbMF0uc3Vic3RyKDIpO1xufTtcblxuU0RQVXRpbHMuaXNSZWplY3RlZCA9IGZ1bmN0aW9uKG1lZGlhU2VjdGlvbikge1xuICByZXR1cm4gbWVkaWFTZWN0aW9uLnNwbGl0KCcgJywgMilbMV0gPT09ICcwJztcbn07XG5cblNEUFV0aWxzLnBhcnNlTUxpbmUgPSBmdW5jdGlvbihtZWRpYVNlY3Rpb24pIHtcbiAgdmFyIGxpbmVzID0gU0RQVXRpbHMuc3BsaXRMaW5lcyhtZWRpYVNlY3Rpb24pO1xuICB2YXIgcGFydHMgPSBsaW5lc1swXS5zdWJzdHIoMikuc3BsaXQoJyAnKTtcbiAgcmV0dXJuIHtcbiAgICBraW5kOiBwYXJ0c1swXSxcbiAgICBwb3J0OiBwYXJzZUludChwYXJ0c1sxXSwgMTApLFxuICAgIHByb3RvY29sOiBwYXJ0c1syXSxcbiAgICBmbXQ6IHBhcnRzLnNsaWNlKDMpLmpvaW4oJyAnKVxuICB9O1xufTtcblxuU0RQVXRpbHMucGFyc2VPTGluZSA9IGZ1bmN0aW9uKG1lZGlhU2VjdGlvbikge1xuICB2YXIgbGluZSA9IFNEUFV0aWxzLm1hdGNoUHJlZml4KG1lZGlhU2VjdGlvbiwgJ289JylbMF07XG4gIHZhciBwYXJ0cyA9IGxpbmUuc3Vic3RyKDIpLnNwbGl0KCcgJyk7XG4gIHJldHVybiB7XG4gICAgdXNlcm5hbWU6IHBhcnRzWzBdLFxuICAgIHNlc3Npb25JZDogcGFydHNbMV0sXG4gICAgc2Vzc2lvblZlcnNpb246IHBhcnNlSW50KHBhcnRzWzJdLCAxMCksXG4gICAgbmV0VHlwZTogcGFydHNbM10sXG4gICAgYWRkcmVzc1R5cGU6IHBhcnRzWzRdLFxuICAgIGFkZHJlc3M6IHBhcnRzWzVdLFxuICB9O1xufVxuXG4vLyBFeHBvc2UgcHVibGljIG1ldGhvZHMuXG5pZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcpIHtcbiAgbW9kdWxlLmV4cG9ydHMgPSBTRFBVdGlscztcbn1cbiIsIi8qKlxuICogVUFQYXJzZXIuanMgdjAuNy4xN1xuICogTGlnaHR3ZWlnaHQgSmF2YVNjcmlwdC1iYXNlZCBVc2VyLUFnZW50IHN0cmluZyBwYXJzZXJcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9mYWlzYWxtYW4vdWEtcGFyc2VyLWpzXG4gKlxuICogQ29weXJpZ2h0IMKpIDIwMTItMjAxNiBGYWlzYWwgU2FsbWFuIDxmeXpsbWFuQGdtYWlsLmNvbT5cbiAqIER1YWwgbGljZW5zZWQgdW5kZXIgR1BMdjIgJiBNSVRcbiAqL1xuXG4oZnVuY3Rpb24gKHdpbmRvdywgdW5kZWZpbmVkKSB7XG5cbiAgICAndXNlIHN0cmljdCc7XG5cbiAgICAvLy8vLy8vLy8vLy8vL1xuICAgIC8vIENvbnN0YW50c1xuICAgIC8vLy8vLy8vLy8vLy9cblxuXG4gICAgdmFyIExJQlZFUlNJT04gID0gJzAuNy4xNycsXG4gICAgICAgIEVNUFRZICAgICAgID0gJycsXG4gICAgICAgIFVOS05PV04gICAgID0gJz8nLFxuICAgICAgICBGVU5DX1RZUEUgICA9ICdmdW5jdGlvbicsXG4gICAgICAgIFVOREVGX1RZUEUgID0gJ3VuZGVmaW5lZCcsXG4gICAgICAgIE9CSl9UWVBFICAgID0gJ29iamVjdCcsXG4gICAgICAgIFNUUl9UWVBFICAgID0gJ3N0cmluZycsXG4gICAgICAgIE1BSk9SICAgICAgID0gJ21ham9yJywgLy8gZGVwcmVjYXRlZFxuICAgICAgICBNT0RFTCAgICAgICA9ICdtb2RlbCcsXG4gICAgICAgIE5BTUUgICAgICAgID0gJ25hbWUnLFxuICAgICAgICBUWVBFICAgICAgICA9ICd0eXBlJyxcbiAgICAgICAgVkVORE9SICAgICAgPSAndmVuZG9yJyxcbiAgICAgICAgVkVSU0lPTiAgICAgPSAndmVyc2lvbicsXG4gICAgICAgIEFSQ0hJVEVDVFVSRT0gJ2FyY2hpdGVjdHVyZScsXG4gICAgICAgIENPTlNPTEUgICAgID0gJ2NvbnNvbGUnLFxuICAgICAgICBNT0JJTEUgICAgICA9ICdtb2JpbGUnLFxuICAgICAgICBUQUJMRVQgICAgICA9ICd0YWJsZXQnLFxuICAgICAgICBTTUFSVFRWICAgICA9ICdzbWFydHR2JyxcbiAgICAgICAgV0VBUkFCTEUgICAgPSAnd2VhcmFibGUnLFxuICAgICAgICBFTUJFRERFRCAgICA9ICdlbWJlZGRlZCc7XG5cblxuICAgIC8vLy8vLy8vLy8vXG4gICAgLy8gSGVscGVyXG4gICAgLy8vLy8vLy8vL1xuXG5cbiAgICB2YXIgdXRpbCA9IHtcbiAgICAgICAgZXh0ZW5kIDogZnVuY3Rpb24gKHJlZ2V4ZXMsIGV4dGVuc2lvbnMpIHtcbiAgICAgICAgICAgIHZhciBtYXJnZWRSZWdleGVzID0ge307XG4gICAgICAgICAgICBmb3IgKHZhciBpIGluIHJlZ2V4ZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXh0ZW5zaW9uc1tpXSAmJiBleHRlbnNpb25zW2ldLmxlbmd0aCAlIDIgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgbWFyZ2VkUmVnZXhlc1tpXSA9IGV4dGVuc2lvbnNbaV0uY29uY2F0KHJlZ2V4ZXNbaV0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG1hcmdlZFJlZ2V4ZXNbaV0gPSByZWdleGVzW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtYXJnZWRSZWdleGVzO1xuICAgICAgICB9LFxuICAgICAgICBoYXMgOiBmdW5jdGlvbiAoc3RyMSwgc3RyMikge1xuICAgICAgICAgIGlmICh0eXBlb2Ygc3RyMSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgcmV0dXJuIHN0cjIudG9Mb3dlckNhc2UoKS5pbmRleE9mKHN0cjEudG9Mb3dlckNhc2UoKSkgIT09IC0xO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBsb3dlcml6ZSA6IGZ1bmN0aW9uIChzdHIpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHIudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgfSxcbiAgICAgICAgbWFqb3IgOiBmdW5jdGlvbiAodmVyc2lvbikge1xuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZih2ZXJzaW9uKSA9PT0gU1RSX1RZUEUgPyB2ZXJzaW9uLnJlcGxhY2UoL1teXFxkXFwuXS9nLCcnKS5zcGxpdChcIi5cIilbMF0gOiB1bmRlZmluZWQ7XG4gICAgICAgIH0sXG4gICAgICAgIHRyaW0gOiBmdW5jdGlvbiAoc3RyKSB7XG4gICAgICAgICAgcmV0dXJuIHN0ci5yZXBsYWNlKC9eW1xcc1xcdUZFRkZcXHhBMF0rfFtcXHNcXHVGRUZGXFx4QTBdKyQvZywgJycpO1xuICAgICAgICB9XG4gICAgfTtcblxuXG4gICAgLy8vLy8vLy8vLy8vLy8vXG4gICAgLy8gTWFwIGhlbHBlclxuICAgIC8vLy8vLy8vLy8vLy8vXG5cblxuICAgIHZhciBtYXBwZXIgPSB7XG5cbiAgICAgICAgcmd4IDogZnVuY3Rpb24gKHVhLCBhcnJheXMpIHtcblxuICAgICAgICAgICAgLy92YXIgcmVzdWx0ID0ge30sXG4gICAgICAgICAgICB2YXIgaSA9IDAsIGosIGssIHAsIHEsIG1hdGNoZXMsIG1hdGNoOy8vLCBhcmdzID0gYXJndW1lbnRzO1xuXG4gICAgICAgICAgICAvKi8vIGNvbnN0cnVjdCBvYmplY3QgYmFyZWJvbmVzXG4gICAgICAgICAgICBmb3IgKHAgPSAwOyBwIDwgYXJnc1sxXS5sZW5ndGg7IHArKykge1xuICAgICAgICAgICAgICAgIHEgPSBhcmdzWzFdW3BdO1xuICAgICAgICAgICAgICAgIHJlc3VsdFt0eXBlb2YgcSA9PT0gT0JKX1RZUEUgPyBxWzBdIDogcV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9Ki9cblxuICAgICAgICAgICAgLy8gbG9vcCB0aHJvdWdoIGFsbCByZWdleGVzIG1hcHNcbiAgICAgICAgICAgIHdoaWxlIChpIDwgYXJyYXlzLmxlbmd0aCAmJiAhbWF0Y2hlcykge1xuXG4gICAgICAgICAgICAgICAgdmFyIHJlZ2V4ID0gYXJyYXlzW2ldLCAgICAgICAvLyBldmVuIHNlcXVlbmNlICgwLDIsNCwuLilcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSBhcnJheXNbaSArIDFdOyAgIC8vIG9kZCBzZXF1ZW5jZSAoMSwzLDUsLi4pXG4gICAgICAgICAgICAgICAgaiA9IGsgPSAwO1xuXG4gICAgICAgICAgICAgICAgLy8gdHJ5IG1hdGNoaW5nIHVhc3RyaW5nIHdpdGggcmVnZXhlc1xuICAgICAgICAgICAgICAgIHdoaWxlIChqIDwgcmVnZXgubGVuZ3RoICYmICFtYXRjaGVzKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcyA9IHJlZ2V4W2orK10uZXhlYyh1YSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhbWF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChwID0gMDsgcCA8IHByb3BzLmxlbmd0aDsgcCsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2ggPSBtYXRjaGVzWysra107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcSA9IHByb3BzW3BdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNoZWNrIGlmIGdpdmVuIHByb3BlcnR5IGlzIGFjdHVhbGx5IGFycmF5XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBxID09PSBPQkpfVFlQRSAmJiBxLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHEubGVuZ3RoID09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgcVsxXSA9PSBGVU5DX1RZUEUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhc3NpZ24gbW9kaWZpZWQgbWF0Y2hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzW3FbMF1dID0gcVsxXS5jYWxsKHRoaXMsIG1hdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXNzaWduIGdpdmVuIHZhbHVlLCBpZ25vcmUgcmVnZXggbWF0Y2hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzW3FbMF1dID0gcVsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChxLmxlbmd0aCA9PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjaGVjayB3aGV0aGVyIGZ1bmN0aW9uIG9yIHJlZ2V4XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHFbMV0gPT09IEZVTkNfVFlQRSAmJiAhKHFbMV0uZXhlYyAmJiBxWzFdLnRlc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY2FsbCBmdW5jdGlvbiAodXN1YWxseSBzdHJpbmcgbWFwcGVyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNbcVswXV0gPSBtYXRjaCA/IHFbMV0uY2FsbCh0aGlzLCBtYXRjaCwgcVsyXSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNhbml0aXplIG1hdGNoIHVzaW5nIGdpdmVuIHJlZ2V4XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1txWzBdXSA9IG1hdGNoID8gbWF0Y2gucmVwbGFjZShxWzFdLCBxWzJdKSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChxLmxlbmd0aCA9PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1txWzBdXSA9IG1hdGNoID8gcVszXS5jYWxsKHRoaXMsIG1hdGNoLnJlcGxhY2UocVsxXSwgcVsyXSkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1txXSA9IG1hdGNoID8gbWF0Y2ggOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGkgKz0gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKHRoaXMpO1xuICAgICAgICAgICAgLy9yZXR1cm4gdGhpcztcbiAgICAgICAgfSxcblxuICAgICAgICBzdHIgOiBmdW5jdGlvbiAoc3RyLCBtYXApIHtcblxuICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBtYXApIHtcbiAgICAgICAgICAgICAgICAvLyBjaGVjayBpZiBhcnJheVxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWFwW2ldID09PSBPQkpfVFlQRSAmJiBtYXBbaV0ubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1hcFtpXS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHV0aWwuaGFzKG1hcFtpXVtqXSwgc3RyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoaSA9PT0gVU5LTk9XTikgPyB1bmRlZmluZWQgOiBpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh1dGlsLmhhcyhtYXBbaV0sIHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChpID09PSBVTktOT1dOKSA/IHVuZGVmaW5lZCA6IGk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHN0cjtcbiAgICAgICAgfVxuICAgIH07XG5cblxuICAgIC8vLy8vLy8vLy8vLy8vL1xuICAgIC8vIFN0cmluZyBtYXBcbiAgICAvLy8vLy8vLy8vLy8vL1xuXG5cbiAgICB2YXIgbWFwcyA9IHtcblxuICAgICAgICBicm93c2VyIDoge1xuICAgICAgICAgICAgb2xkc2FmYXJpIDoge1xuICAgICAgICAgICAgICAgIHZlcnNpb24gOiB7XG4gICAgICAgICAgICAgICAgICAgICcxLjAnICAgOiAnLzgnLFxuICAgICAgICAgICAgICAgICAgICAnMS4yJyAgIDogJy8xJyxcbiAgICAgICAgICAgICAgICAgICAgJzEuMycgICA6ICcvMycsXG4gICAgICAgICAgICAgICAgICAgICcyLjAnICAgOiAnLzQxMicsXG4gICAgICAgICAgICAgICAgICAgICcyLjAuMicgOiAnLzQxNicsXG4gICAgICAgICAgICAgICAgICAgICcyLjAuMycgOiAnLzQxNycsXG4gICAgICAgICAgICAgICAgICAgICcyLjAuNCcgOiAnLzQxOScsXG4gICAgICAgICAgICAgICAgICAgICc/JyAgICAgOiAnLydcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgZGV2aWNlIDoge1xuICAgICAgICAgICAgYW1hem9uIDoge1xuICAgICAgICAgICAgICAgIG1vZGVsIDoge1xuICAgICAgICAgICAgICAgICAgICAnRmlyZSBQaG9uZScgOiBbJ1NEJywgJ0tGJ11cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc3ByaW50IDoge1xuICAgICAgICAgICAgICAgIG1vZGVsIDoge1xuICAgICAgICAgICAgICAgICAgICAnRXZvIFNoaWZ0IDRHJyA6ICc3MzczS1QnXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB2ZW5kb3IgOiB7XG4gICAgICAgICAgICAgICAgICAgICdIVEMnICAgICAgIDogJ0FQQScsXG4gICAgICAgICAgICAgICAgICAgICdTcHJpbnQnICAgIDogJ1NwcmludCdcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgb3MgOiB7XG4gICAgICAgICAgICB3aW5kb3dzIDoge1xuICAgICAgICAgICAgICAgIHZlcnNpb24gOiB7XG4gICAgICAgICAgICAgICAgICAgICdNRScgICAgICAgIDogJzQuOTAnLFxuICAgICAgICAgICAgICAgICAgICAnTlQgMy4xMScgICA6ICdOVDMuNTEnLFxuICAgICAgICAgICAgICAgICAgICAnTlQgNC4wJyAgICA6ICdOVDQuMCcsXG4gICAgICAgICAgICAgICAgICAgICcyMDAwJyAgICAgIDogJ05UIDUuMCcsXG4gICAgICAgICAgICAgICAgICAgICdYUCcgICAgICAgIDogWydOVCA1LjEnLCAnTlQgNS4yJ10sXG4gICAgICAgICAgICAgICAgICAgICdWaXN0YScgICAgIDogJ05UIDYuMCcsXG4gICAgICAgICAgICAgICAgICAgICc3JyAgICAgICAgIDogJ05UIDYuMScsXG4gICAgICAgICAgICAgICAgICAgICc4JyAgICAgICAgIDogJ05UIDYuMicsXG4gICAgICAgICAgICAgICAgICAgICc4LjEnICAgICAgIDogJ05UIDYuMycsXG4gICAgICAgICAgICAgICAgICAgICcxMCcgICAgICAgIDogWydOVCA2LjQnLCAnTlQgMTAuMCddLFxuICAgICAgICAgICAgICAgICAgICAnUlQnICAgICAgICA6ICdBUk0nXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuXG4gICAgLy8vLy8vLy8vLy8vLy9cbiAgICAvLyBSZWdleCBtYXBcbiAgICAvLy8vLy8vLy8vLy8vXG5cblxuICAgIHZhciByZWdleGVzID0ge1xuXG4gICAgICAgIGJyb3dzZXIgOiBbW1xuXG4gICAgICAgICAgICAvLyBQcmVzdG8gYmFzZWRcbiAgICAgICAgICAgIC8ob3BlcmFcXHNtaW5pKVxcLyhbXFx3XFwuLV0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhIE1pbmlcbiAgICAgICAgICAgIC8ob3BlcmFcXHNbbW9iaWxldGFiXSspLit2ZXJzaW9uXFwvKFtcXHdcXC4tXSspL2ksICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhIE1vYmkvVGFibGV0XG4gICAgICAgICAgICAvKG9wZXJhKS4rdmVyc2lvblxcLyhbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhID4gOS44MFxuICAgICAgICAgICAgLyhvcGVyYSlbXFwvXFxzXSsoW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3BlcmEgPCA5LjgwXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhvcGlvcylbXFwvXFxzXSsoW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3BlcmEgbWluaSBvbiBpcGhvbmUgPj0gOC4wXG4gICAgICAgICAgICBdLCBbW05BTUUsICdPcGVyYSBNaW5pJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC9cXHMob3ByKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhIFdlYmtpdFxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnT3BlcmEnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLy8gTWl4ZWRcbiAgICAgICAgICAgIC8oa2luZGxlKVxcLyhbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gS2luZGxlXG4gICAgICAgICAgICAvKGx1bmFzY2FwZXxtYXh0aG9ufG5ldGZyb250fGphc21pbmV8YmxhemVyKVtcXC9cXHNdPyhbXFx3XFwuXSspKi9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBMdW5hc2NhcGUvTWF4dGhvbi9OZXRmcm9udC9KYXNtaW5lL0JsYXplclxuXG4gICAgICAgICAgICAvLyBUcmlkZW50IGJhc2VkXG4gICAgICAgICAgICAvKGF2YW50XFxzfGllbW9iaWxlfHNsaW18YmFpZHUpKD86YnJvd3Nlcik/W1xcL1xcc10/KFtcXHdcXC5dKikvaSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXZhbnQvSUVNb2JpbGUvU2xpbUJyb3dzZXIvQmFpZHVcbiAgICAgICAgICAgIC8oPzptc3xcXCgpKGllKVxccyhbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEludGVybmV0IEV4cGxvcmVyXG5cbiAgICAgICAgICAgIC8vIFdlYmtpdC9LSFRNTCBiYXNlZFxuICAgICAgICAgICAgLyhyZWtvbnEpXFwvKFtcXHdcXC5dKykqL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZWtvbnFcbiAgICAgICAgICAgIC8oY2hyb21pdW18ZmxvY2t8cm9ja21lbHR8bWlkb3JpfGVwaXBoYW55fHNpbGt8c2t5ZmlyZXxvdmlicm93c2VyfGJvbHR8aXJvbnx2aXZhbGRpfGlyaWRpdW18cGhhbnRvbWpzfGJvd3NlcilcXC8oW1xcd1xcLi1dKykvaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDaHJvbWl1bS9GbG9jay9Sb2NrTWVsdC9NaWRvcmkvRXBpcGhhbnkvU2lsay9Ta3lmaXJlL0JvbHQvSXJvbi9JcmlkaXVtL1BoYW50b21KUy9Cb3dzZXJcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKHRyaWRlbnQpLitydls6XFxzXShbXFx3XFwuXSspLitsaWtlXFxzZ2Vja28vaSAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJRTExXG4gICAgICAgICAgICBdLCBbW05BTUUsICdJRSddLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKGVkZ2UpXFwvKChcXGQrKT9bXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNaWNyb3NvZnQgRWRnZVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oeWFicm93c2VyKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gWWFuZGV4XG4gICAgICAgICAgICBdLCBbW05BTUUsICdZYW5kZXgnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhwdWZmaW4pXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBQdWZmaW5cbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ1B1ZmZpbiddLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKCg/OltcXHNcXC9dKXVjP1xccz9icm93c2VyfCg/Omp1Yy4rKXVjd2ViKVtcXC9cXHNdPyhbXFx3XFwuXSspL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVUNCcm93c2VyXG4gICAgICAgICAgICBdLCBbW05BTUUsICdVQ0Jyb3dzZXInXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhjb21vZG9fZHJhZ29uKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDb21vZG8gRHJhZ29uXG4gICAgICAgICAgICBdLCBbW05BTUUsIC9fL2csICcgJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8obWljcm9tZXNzZW5nZXIpXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2VDaGF0XG4gICAgICAgICAgICBdLCBbW05BTUUsICdXZUNoYXQnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhRUSlcXC8oW1xcZFxcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBRUSwgYWthIFNob3VRXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgL20/KHFxYnJvd3NlcilbXFwvXFxzXT8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUVFCcm93c2VyXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgL3hpYW9taVxcL21pdWlicm93c2VyXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTUlVSSBCcm93c2VyXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgW05BTUUsICdNSVVJIEJyb3dzZXInXV0sIFtcblxuICAgICAgICAgICAgLztmYmF2XFwvKFtcXHdcXC5dKyk7L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGYWNlYm9vayBBcHAgZm9yIGlPUyAmIEFuZHJvaWRcbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBbTkFNRSwgJ0ZhY2Vib29rJ11dLCBbXG5cbiAgICAgICAgICAgIC9oZWFkbGVzc2Nocm9tZSg/OlxcLyhbXFx3XFwuXSspfFxccykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENocm9tZSBIZWFkbGVzc1xuICAgICAgICAgICAgXSwgW1ZFUlNJT04sIFtOQU1FLCAnQ2hyb21lIEhlYWRsZXNzJ11dLCBbXG5cbiAgICAgICAgICAgIC9cXHN3dlxcKS4rKGNocm9tZSlcXC8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDaHJvbWUgV2ViVmlld1xuICAgICAgICAgICAgXSwgW1tOQU1FLCAvKC4rKS8sICckMSBXZWJWaWV3J10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oKD86b2N1bHVzfHNhbXN1bmcpYnJvd3NlcilcXC8oW1xcd1xcLl0rKS9pXG4gICAgICAgICAgICBdLCBbW05BTUUsIC8oLisoPzpnfHVzKSkoLispLywgJyQxICQyJ10sIFZFUlNJT05dLCBbICAgICAgICAgICAgICAgIC8vIE9jdWx1cyAvIFNhbXN1bmcgQnJvd3NlclxuXG4gICAgICAgICAgICAvYW5kcm9pZC4rdmVyc2lvblxcLyhbXFx3XFwuXSspXFxzKyg/Om1vYmlsZVxccz9zYWZhcml8c2FmYXJpKSovaSAgICAgICAgLy8gQW5kcm9pZCBCcm93c2VyXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgW05BTUUsICdBbmRyb2lkIEJyb3dzZXInXV0sIFtcblxuICAgICAgICAgICAgLyhjaHJvbWV8b21uaXdlYnxhcm9yYXxbdGl6ZW5va2FdezV9XFxzP2Jyb3dzZXIpXFwvdj8oW1xcd1xcLl0rKS9pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENocm9tZS9PbW5pV2ViL0Fyb3JhL1RpemVuL05va2lhXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhkb2xmaW4pXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2xwaGluXG4gICAgICAgICAgICBdLCBbW05BTUUsICdEb2xwaGluJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oKD86YW5kcm9pZC4rKWNybW98Y3Jpb3MpXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hyb21lIGZvciBBbmRyb2lkL2lPU1xuICAgICAgICAgICAgXSwgW1tOQU1FLCAnQ2hyb21lJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oY29hc3QpXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3BlcmEgQ29hc3RcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ09wZXJhIENvYXN0J10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC9meGlvc1xcLyhbXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCBmb3IgaU9TXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgW05BTUUsICdGaXJlZm94J11dLCBbXG5cbiAgICAgICAgICAgIC92ZXJzaW9uXFwvKFtcXHdcXC5dKykuKz9tb2JpbGVcXC9cXHcrXFxzKHNhZmFyaSkvaSAgICAgICAgICAgICAgICAgICAgICAgLy8gTW9iaWxlIFNhZmFyaVxuICAgICAgICAgICAgXSwgW1ZFUlNJT04sIFtOQU1FLCAnTW9iaWxlIFNhZmFyaSddXSwgW1xuXG4gICAgICAgICAgICAvdmVyc2lvblxcLyhbXFx3XFwuXSspLis/KG1vYmlsZVxccz9zYWZhcml8c2FmYXJpKS9pICAgICAgICAgICAgICAgICAgICAvLyBTYWZhcmkgJiBTYWZhcmkgTW9iaWxlXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgTkFNRV0sIFtcblxuICAgICAgICAgICAgL3dlYmtpdC4rPyhnc2EpXFwvKFtcXHdcXC5dKykuKz8obW9iaWxlXFxzP3NhZmFyaXxzYWZhcmkpKFxcL1tcXHdcXC5dKykvaSAgLy8gR29vZ2xlIFNlYXJjaCBBcHBsaWFuY2Ugb24gaU9TXG4gICAgICAgICAgICBdLCBbW05BTUUsICdHU0EnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgL3dlYmtpdC4rPyhtb2JpbGVcXHM/c2FmYXJpfHNhZmFyaSkoXFwvW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgLy8gU2FmYXJpIDwgMy4wXG4gICAgICAgICAgICBdLCBbTkFNRSwgW1ZFUlNJT04sIG1hcHBlci5zdHIsIG1hcHMuYnJvd3Nlci5vbGRzYWZhcmkudmVyc2lvbl1dLCBbXG5cbiAgICAgICAgICAgIC8oa29ucXVlcm9yKVxcLyhbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gS29ucXVlcm9yXG4gICAgICAgICAgICAvKHdlYmtpdHxraHRtbClcXC8oW1xcd1xcLl0rKS9pXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLy8gR2Vja28gYmFzZWRcbiAgICAgICAgICAgIC8obmF2aWdhdG9yfG5ldHNjYXBlKVxcLyhbXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTmV0c2NhcGVcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ05ldHNjYXBlJ10sIFZFUlNJT05dLCBbXG4gICAgICAgICAgICAvKHN3aWZ0Zm94KS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN3aWZ0Zm94XG4gICAgICAgICAgICAvKGljZWRyYWdvbnxpY2V3ZWFzZWx8Y2FtaW5vfGNoaW1lcmF8ZmVubmVjfG1hZW1vXFxzYnJvd3NlcnxtaW5pbW98Y29ua2Vyb3IpW1xcL1xcc10/KFtcXHdcXC5cXCtdKykvaSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWNlRHJhZ29uL0ljZXdlYXNlbC9DYW1pbm8vQ2hpbWVyYS9GZW5uZWMvTWFlbW8vTWluaW1vL0Nvbmtlcm9yXG4gICAgICAgICAgICAvKGZpcmVmb3h8c2VhbW9ua2V5fGstbWVsZW9ufGljZWNhdHxpY2VhcGV8ZmlyZWJpcmR8cGhvZW5peClcXC8oW1xcd1xcLi1dKykvaSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveC9TZWFNb25rZXkvSy1NZWxlb24vSWNlQ2F0L0ljZUFwZS9GaXJlYmlyZC9QaG9lbml4XG4gICAgICAgICAgICAvKG1vemlsbGEpXFwvKFtcXHdcXC5dKykuK3J2XFw6LitnZWNrb1xcL1xcZCsvaSwgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1vemlsbGFcblxuICAgICAgICAgICAgLy8gT3RoZXJcbiAgICAgICAgICAgIC8ocG9sYXJpc3xseW54fGRpbGxvfGljYWJ8ZG9yaXN8YW1heWF8dzNtfG5ldHN1cmZ8c2xlaXBuaXIpW1xcL1xcc10/KFtcXHdcXC5dKykvaSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUG9sYXJpcy9MeW54L0RpbGxvL2lDYWIvRG9yaXMvQW1heWEvdzNtL05ldFN1cmYvU2xlaXBuaXJcbiAgICAgICAgICAgIC8obGlua3MpXFxzXFwoKFtcXHdcXC5dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExpbmtzXG4gICAgICAgICAgICAvKGdvYnJvd3NlcilcXC8/KFtcXHdcXC5dKykqL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdvQnJvd3NlclxuICAgICAgICAgICAgLyhpY2VcXHM/YnJvd3NlcilcXC92PyhbXFx3XFwuX10rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSUNFIEJyb3dzZXJcbiAgICAgICAgICAgIC8obW9zYWljKVtcXC9cXHNdKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1vc2FpY1xuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dXG5cbiAgICAgICAgICAgIC8qIC8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgICAgICAgICAgLy8gTWVkaWEgcGxheWVycyBCRUdJTlxuICAgICAgICAgICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG5cbiAgICAgICAgICAgICwgW1xuXG4gICAgICAgICAgICAvKGFwcGxlKD86Y29yZW1lZGlhfCkpXFwvKChcXGQrKVtcXHdcXC5fXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBHZW5lcmljIEFwcGxlIENvcmVNZWRpYVxuICAgICAgICAgICAgLyhjb3JlbWVkaWEpIHYoKFxcZCspW1xcd1xcLl9dKykvaVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oYXF1YWx1bmd8bHlzc25hfGJzcGxheWVyKVxcLygoXFxkKyk/W1xcd1xcLi1dKykvaSAgICAgICAgICAgICAgICAgICAgIC8vIEFxdWFsdW5nL0x5c3NuYS9CU1BsYXllclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oYXJlc3xvc3Nwcm94eSlcXHMoKFxcZCspW1xcd1xcLi1dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFyZXMvT1NTUHJveHlcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKGF1ZGFjaW91c3xhdWRpbXVzaWNzdHJlYW18YW1hcm9rfGJhc3N8Y29yZXxkYWx2aWt8Z25vbWVtcGxheWVyfG11c2ljIG9uIGNvbnNvbGV8bnNwbGF5ZXJ8cHNwLWludGVybmV0cmFkaW9wbGF5ZXJ8dmlkZW9zKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBdWRhY2lvdXMvQXVkaU11c2ljU3RyZWFtL0FtYXJvay9CQVNTL09wZW5DT1JFL0RhbHZpay9Hbm9tZU1wbGF5ZXIvTW9DXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5TUGxheWVyL1BTUC1JbnRlcm5ldFJhZGlvUGxheWVyL1ZpZGVvc1xuICAgICAgICAgICAgLyhjbGVtZW50aW5lfG11c2ljIHBsYXllciBkYWVtb24pXFxzKChcXGQrKVtcXHdcXC4tXSspL2ksICAgICAgICAgICAgICAgLy8gQ2xlbWVudGluZS9NUERcbiAgICAgICAgICAgIC8obGcgcGxheWVyfG5leHBsYXllcilcXHMoKFxcZCspW1xcZFxcLl0rKS9pLFxuICAgICAgICAgICAgL3BsYXllclxcLyhuZXhwbGF5ZXJ8bGcgcGxheWVyKVxccygoXFxkKylbXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgIC8vIE5leFBsYXllci9MRyBQbGF5ZXJcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuICAgICAgICAgICAgLyhuZXhwbGF5ZXIpXFxzKChcXGQrKVtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTmV4cGxheWVyXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhmbHJwKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRmxpcCBQbGF5ZXJcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0ZsaXAgUGxheWVyJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oZnN0cmVhbXxuYXRpdmVob3N0fHF1ZXJ5c2Vla3NwaWRlcnxpYS1hcmNoaXZlcnxmYWNlYm9va2V4dGVybmFsaGl0KS9pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZTdHJlYW0vTmF0aXZlSG9zdC9RdWVyeVNlZWtTcGlkZXIvSUEgQXJjaGl2ZXIvZmFjZWJvb2tleHRlcm5hbGhpdFxuICAgICAgICAgICAgXSwgW05BTUVdLCBbXG5cbiAgICAgICAgICAgIC8oZ3N0cmVhbWVyKSBzb3VwaHR0cHNyYyAoPzpcXChbXlxcKV0rXFwpKXswLDF9IGxpYnNvdXBcXC8oKFxcZCspW1xcd1xcLi1dKykvaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBHc3RyZWFtZXJcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKGh0YyBzdHJlYW1pbmcgcGxheWVyKVxcc1tcXHdfXStcXHNcXC9cXHMoKFxcZCspW1xcZFxcLl0rKS9pLCAgICAgICAgICAgICAgLy8gSFRDIFN0cmVhbWluZyBQbGF5ZXJcbiAgICAgICAgICAgIC8oamF2YXxweXRob24tdXJsbGlifHB5dGhvbi1yZXF1ZXN0c3x3Z2V0fGxpYmN1cmwpXFwvKChcXGQrKVtcXHdcXC4tX10rKS9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBKYXZhL3VybGxpYi9yZXF1ZXN0cy93Z2V0L2NVUkxcbiAgICAgICAgICAgIC8obGF2ZikoKFxcZCspW1xcZFxcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTGF2ZiAoRkZNUEVHKVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oaHRjX29uZV9zKVxcLygoXFxkKylbXFxkXFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEhUQyBPbmUgU1xuICAgICAgICAgICAgXSwgW1tOQU1FLCAvXy9nLCAnICddLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKG1wbGF5ZXIpKD86XFxzfFxcLykoPzooPzpzaGVycHlhLSl7MCwxfXN2bikoPzotfFxccykoclxcZCsoPzotXFxkK1tcXHdcXC4tXSspezAsMX0pL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTVBsYXllciBTVk5cbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKG1wbGF5ZXIpKD86XFxzfFxcL3xbdW5rb3ctXSspKChcXGQrKVtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgICAgLy8gTVBsYXllclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8obXBsYXllcikvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTVBsYXllciAobm8gb3RoZXIgaW5mbylcbiAgICAgICAgICAgIC8oeW91cm11emUpL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gWW91ck11emVcbiAgICAgICAgICAgIC8obWVkaWEgcGxheWVyIGNsYXNzaWN8bmVybyBzaG93dGltZSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWVkaWEgUGxheWVyIENsYXNzaWMvTmVybyBTaG93VGltZVxuICAgICAgICAgICAgXSwgW05BTUVdLCBbXG5cbiAgICAgICAgICAgIC8obmVybyAoPzpob21lfHNjb3V0KSlcXC8oKFxcZCspW1xcd1xcLi1dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5lcm8gSG9tZS9OZXJvIFNjb3V0XG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhub2tpYVxcZCspXFwvKChcXGQrKVtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5va2lhXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgL1xccyhzb25nYmlyZClcXC8oKFxcZCspW1xcd1xcLi1dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvbmdiaXJkL1BoaWxpcHMtU29uZ2JpcmRcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKHdpbmFtcCkzIHZlcnNpb24gKChcXGQrKVtcXHdcXC4tXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpbmFtcFxuICAgICAgICAgICAgLyh3aW5hbXApXFxzKChcXGQrKVtcXHdcXC4tXSspL2ksXG4gICAgICAgICAgICAvKHdpbmFtcCltcGVnXFwvKChcXGQrKVtcXHdcXC4tXSspL2lcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKG9jbXMtYm90fHRhcGlucmFkaW98dHVuZWluIHJhZGlvfHVua25vd258d2luYW1wfGlubGlnaHQgcmFkaW8pL2kgIC8vIE9DTVMtYm90L3RhcCBpbiByYWRpby90dW5laW4vdW5rbm93bi93aW5hbXAgKG5vIG90aGVyIGluZm8pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlubGlnaHQgcmFkaW9cbiAgICAgICAgICAgIF0sIFtOQU1FXSwgW1xuXG4gICAgICAgICAgICAvKHF1aWNrdGltZXxybWF8cmFkaW9hcHB8cmFkaW9jbGllbnRhcHBsaWNhdGlvbnxzb3VuZHRhcHx0b3RlbXxzdGFnZWZyaWdodHxzdHJlYW1pdW0pXFwvKChcXGQrKVtcXHdcXC4tXSspL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUXVpY2tUaW1lL1JlYWxNZWRpYS9SYWRpb0FwcC9SYWRpb0NsaWVudEFwcGxpY2F0aW9uL1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTb3VuZFRhcC9Ub3RlbS9TdGFnZWZyaWdodC9TdHJlYW1pdW1cbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKHNtcCkoKFxcZCspW1xcZFxcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNNUFxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8odmxjKSBtZWRpYSBwbGF5ZXIgLSB2ZXJzaW9uICgoXFxkKylbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgLy8gVkxDIFZpZGVvbGFuXG4gICAgICAgICAgICAvKHZsYylcXC8oKFxcZCspW1xcd1xcLi1dKykvaSxcbiAgICAgICAgICAgIC8oeGJtY3xndmZzfHhpbmV8eG1tc3xpcmFwcClcXC8oKFxcZCspW1xcd1xcLi1dKykvaSwgICAgICAgICAgICAgICAgICAgIC8vIFhCTUMvZ3Zmcy9YaW5lL1hNTVMvaXJhcHBcbiAgICAgICAgICAgIC8oZm9vYmFyMjAwMClcXC8oKFxcZCspW1xcZFxcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZvb2JhcjIwMDBcbiAgICAgICAgICAgIC8oaXR1bmVzKVxcLygoXFxkKylbXFxkXFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlUdW5lc1xuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8od21wbGF5ZXIpXFwvKChcXGQrKVtcXHdcXC4tXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpbmRvd3MgTWVkaWEgUGxheWVyXG4gICAgICAgICAgICAvKHdpbmRvd3MtbWVkaWEtcGxheWVyKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pXG4gICAgICAgICAgICBdLCBbW05BTUUsIC8tL2csICcgJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC93aW5kb3dzXFwvKChcXGQrKVtcXHdcXC4tXSspIHVwbnBcXC9bXFxkXFwuXSsgZGxuYWRvY1xcL1tcXGRcXC5dKyAoaG9tZSBtZWRpYSBzZXJ2ZXIpL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2luZG93cyBNZWRpYSBTZXJ2ZXJcbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBbTkFNRSwgJ1dpbmRvd3MnXV0sIFtcblxuICAgICAgICAgICAgLyhjb21cXC5yaXNldXByYWRpb2FsYXJtKVxcLygoXFxkKylbXFxkXFwuXSopL2kgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJpc2VVUCBSYWRpbyBBbGFybVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8ocmFkLmlvKVxccygoXFxkKylbXFxkXFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJhZC5pb1xuICAgICAgICAgICAgLyhyYWRpby4oPzpkZXxhdHxmcikpXFxzKChcXGQrKVtcXGRcXC5dKykvaVxuICAgICAgICAgICAgXSwgW1tOQU1FLCAncmFkLmlvJ10sIFZFUlNJT05dXG5cbiAgICAgICAgICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgICAgICAgICAgIC8vIE1lZGlhIHBsYXllcnMgRU5EXG4gICAgICAgICAgICAvLy8vLy8vLy8vLy8vLy8vLy8vLyovXG5cbiAgICAgICAgXSxcblxuICAgICAgICBjcHUgOiBbW1xuXG4gICAgICAgICAgICAvKD86KGFtZHx4KD86KD86ODZ8NjQpW18tXSk/fHdvd3x3aW4pNjQpWztcXCldL2kgICAgICAgICAgICAgICAgICAgICAvLyBBTUQ2NFxuICAgICAgICAgICAgXSwgW1tBUkNISVRFQ1RVUkUsICdhbWQ2NCddXSwgW1xuXG4gICAgICAgICAgICAvKGlhMzIoPz07KSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElBMzIgKHF1aWNrdGltZSlcbiAgICAgICAgICAgIF0sIFtbQVJDSElURUNUVVJFLCB1dGlsLmxvd2VyaXplXV0sIFtcblxuICAgICAgICAgICAgLygoPzppWzM0Nl18eCk4NilbO1xcKV0vaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSUEzMlxuICAgICAgICAgICAgXSwgW1tBUkNISVRFQ1RVUkUsICdpYTMyJ11dLCBbXG5cbiAgICAgICAgICAgIC8vIFBvY2tldFBDIG1pc3Rha2VubHkgaWRlbnRpZmllZCBhcyBQb3dlclBDXG4gICAgICAgICAgICAvd2luZG93c1xccyhjZXxtb2JpbGUpO1xcc3BwYzsvaVxuICAgICAgICAgICAgXSwgW1tBUkNISVRFQ1RVUkUsICdhcm0nXV0sIFtcblxuICAgICAgICAgICAgLygoPzpwcGN8cG93ZXJwYykoPzo2NCk/KSg/Olxcc21hY3w7fFxcKSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBvd2VyUENcbiAgICAgICAgICAgIF0sIFtbQVJDSElURUNUVVJFLCAvb3dlci8sICcnLCB1dGlsLmxvd2VyaXplXV0sIFtcblxuICAgICAgICAgICAgLyhzdW40XFx3KVs7XFwpXS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNQQVJDXG4gICAgICAgICAgICBdLCBbW0FSQ0hJVEVDVFVSRSwgJ3NwYXJjJ11dLCBbXG5cbiAgICAgICAgICAgIC8oKD86YXZyMzJ8aWE2NCg/PTspKXw2OGsoPz1cXCkpfGFybSg/OjY0fCg/PXZcXGQrOykpfCg/PWF0bWVsXFxzKWF2cnwoPzppcml4fG1pcHN8c3BhcmMpKD86NjQpPyg/PTspfHBhLXJpc2MpL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSUE2NCwgNjhLLCBBUk0vNjQsIEFWUi8zMiwgSVJJWC82NCwgTUlQUy82NCwgU1BBUkMvNjQsIFBBLVJJU0NcbiAgICAgICAgICAgIF0sIFtbQVJDSElURUNUVVJFLCB1dGlsLmxvd2VyaXplXV1cbiAgICAgICAgXSxcblxuICAgICAgICBkZXZpY2UgOiBbW1xuXG4gICAgICAgICAgICAvXFwoKGlwYWR8cGxheWJvb2spO1tcXHdcXHNcXCk7LV0rKHJpbXxhcHBsZSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpUGFkL1BsYXlCb29rXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFZFTkRPUiwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hcHBsZWNvcmVtZWRpYVxcL1tcXHdcXC5dKyBcXCgoaXBhZCkvICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlQYWRcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0FwcGxlJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvKGFwcGxlXFxzezAsMX10dikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBcHBsZSBUVlxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0FwcGxlIFRWJ10sIFtWRU5ET1IsICdBcHBsZSddXSwgW1xuXG4gICAgICAgICAgICAvKGFyY2hvcylcXHMoZ2FtZXBhZDI/KS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBcmNob3NcbiAgICAgICAgICAgIC8oaHApLisodG91Y2hwYWQpL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSFAgVG91Y2hQYWRcbiAgICAgICAgICAgIC8oaHApLisodGFibGV0KS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSFAgVGFibGV0XG4gICAgICAgICAgICAvKGtpbmRsZSlcXC8oW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEtpbmRsZVxuICAgICAgICAgICAgL1xccyhub29rKVtcXHdcXHNdK2J1aWxkXFwvKFxcdyspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5vb2tcbiAgICAgICAgICAgIC8oZGVsbClcXHMoc3RyZWFba3ByXFxzXFxkXSpbXFxka29dKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIERlbGwgU3RyZWFrXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC8oa2ZbQS16XSspXFxzYnVpbGRcXC9bXFx3XFwuXSsuKnNpbGtcXC8vaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBLaW5kbGUgRmlyZSBIRFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnQW1hem9uJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhzZHxrZilbMDM0OWhpam9yc3R1d10rXFxzYnVpbGRcXC9bXFx3XFwuXSsuKnNpbGtcXC8vaSAgICAgICAgICAgICAgICAgIC8vIEZpcmUgUGhvbmVcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsIG1hcHBlci5zdHIsIG1hcHMuZGV2aWNlLmFtYXpvbi5tb2RlbF0sIFtWRU5ET1IsICdBbWF6b24nXSwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC9cXCgoaXBbaG9uZWR8XFxzXFx3Kl0rKTsuKyhhcHBsZSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaVBvZC9pUGhvbmVcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgVkVORE9SLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC9cXCgoaXBbaG9uZWR8XFxzXFx3Kl0rKTsvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaVBvZC9pUGhvbmVcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0FwcGxlJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKGJsYWNrYmVycnkpW1xccy1dPyhcXHcrKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQmxhY2tCZXJyeVxuICAgICAgICAgICAgLyhibGFja2JlcnJ5fGJlbnF8cGFsbSg/PVxcLSl8c29ueWVyaWNzc29ufGFjZXJ8YXN1c3xkZWxsfG1laXp1fG1vdG9yb2xhfHBvbHl0cm9uKVtcXHNfLV0/KFtcXHctXSspKi9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBCZW5RL1BhbG0vU29ueS1Fcmljc3Nvbi9BY2VyL0FzdXMvRGVsbC9NZWl6dS9Nb3Rvcm9sYS9Qb2x5dHJvblxuICAgICAgICAgICAgLyhocClcXHMoW1xcd1xcc10rXFx3KS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSFAgaVBBUVxuICAgICAgICAgICAgLyhhc3VzKS0/KFxcdyspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXN1c1xuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgL1xcKGJiMTA7XFxzKFxcdyspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBCbGFja0JlcnJ5IDEwXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdCbGFja0JlcnJ5J10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBc3VzIFRhYmxldHNcbiAgICAgICAgICAgIC9hbmRyb2lkLisodHJhbnNmb1twcmltZVxcc117NCwxMH1cXHNcXHcrfGVlZXBjfHNsaWRlclxcc1xcdyt8bmV4dXMgN3xwYWRmb25lKS9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdBc3VzJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvKHNvbnkpXFxzKHRhYmxldFxcc1twc10pXFxzYnVpbGRcXC8vaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29ueVxuICAgICAgICAgICAgLyhzb255KT8oPzpzZ3AuKylcXHNidWlsZFxcLy9pXG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ1NvbnknXSwgW01PREVMLCAnWHBlcmlhIFRhYmxldCddLCBbVFlQRSwgVEFCTEVUXV0sIFtcbiAgICAgICAgICAgIC9hbmRyb2lkLitcXHMoW2MtZ11cXGR7NH18c29bLWxdXFx3KylcXHNidWlsZFxcLy9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTb255J10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvXFxzKG91eWEpXFxzL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3V5YVxuICAgICAgICAgICAgLyhuaW50ZW5kbylcXHMoW3dpZHMzdV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTmludGVuZG9cbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgQ09OU09MRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLis7XFxzKHNoaWVsZClcXHNidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOdmlkaWFcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ052aWRpYSddLCBbVFlQRSwgQ09OU09MRV1dLCBbXG5cbiAgICAgICAgICAgIC8ocGxheXN0YXRpb25cXHNbMzRwb3J0YWJsZXZpXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBsYXlzdGF0aW9uXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTb255J10sIFtUWVBFLCBDT05TT0xFXV0sIFtcblxuICAgICAgICAgICAgLyhzcHJpbnRcXHMoXFx3KykpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNwcmludCBQaG9uZXNcbiAgICAgICAgICAgIF0sIFtbVkVORE9SLCBtYXBwZXIuc3RyLCBtYXBzLmRldmljZS5zcHJpbnQudmVuZG9yXSwgW01PREVMLCBtYXBwZXIuc3RyLCBtYXBzLmRldmljZS5zcHJpbnQubW9kZWxdLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhsZW5vdm8pXFxzPyhTKD86NTAwMHw2MDAwKSsoPzpbLV1bXFx3K10pKS9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExlbm92byB0YWJsZXRzXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC8oaHRjKVs7X1xccy1dKyhbXFx3XFxzXSsoPz1cXCkpfFxcdyspKi9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIVENcbiAgICAgICAgICAgIC8oenRlKS0oXFx3KykqL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFpURVxuICAgICAgICAgICAgLyhhbGNhdGVsfGdlZWtzcGhvbmV8bGVub3ZvfG5leGlhbnxwYW5hc29uaWN8KD89O1xccylzb255KVtfXFxzLV0/KFtcXHctXSspKi9pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFsY2F0ZWwvR2Vla3NQaG9uZS9MZW5vdm8vTmV4aWFuL1BhbmFzb25pYy9Tb255XG4gICAgICAgICAgICBdLCBbVkVORE9SLCBbTU9ERUwsIC9fL2csICcgJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKG5leHVzXFxzOSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIVEMgTmV4dXMgOVxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnSFRDJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvZFxcL2h1YXdlaShbXFx3XFxzLV0rKVs7XFwpXS9pLFxuICAgICAgICAgICAgLyhuZXh1c1xcczZwKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSHVhd2VpXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdIdWF3ZWknXSwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC8obWljcm9zb2Z0KTtcXHMobHVtaWFbXFxzXFx3XSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWljcm9zb2Z0IEx1bWlhXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC9bXFxzXFwoO10oeGJveCg/Olxcc29uZSk/KVtcXHNcXCk7XS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNaWNyb3NvZnQgWGJveFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnTWljcm9zb2Z0J10sIFtUWVBFLCBDT05TT0xFXV0sIFtcbiAgICAgICAgICAgIC8oa2luXFwuW29uZXR3XXszfSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1pY3Jvc29mdCBLaW5cbiAgICAgICAgICAgIF0sIFtbTU9ERUwsIC9cXC4vZywgJyAnXSwgW1ZFTkRPUiwgJ01pY3Jvc29mdCddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNb3Rvcm9sYVxuICAgICAgICAgICAgL1xccyhtaWxlc3RvbmV8ZHJvaWQoPzpbMi00eF18XFxzKD86YmlvbmljfHgyfHByb3xyYXpyKSk/KDo/XFxzNGcpPylbXFx3XFxzXStidWlsZFxcLy9pLFxuICAgICAgICAgICAgL21vdFtcXHMtXT8oXFx3KykqL2ksXG4gICAgICAgICAgICAvKFhUXFxkezMsNH0pIGJ1aWxkXFwvL2ksXG4gICAgICAgICAgICAvKG5leHVzXFxzNikvaVxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnTW90b3JvbGEnXSwgW1RZUEUsIE1PQklMRV1dLCBbXG4gICAgICAgICAgICAvYW5kcm9pZC4rXFxzKG16NjBcXGR8eG9vbVtcXHMyXXswLDJ9KVxcc2J1aWxkXFwvL2lcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ01vdG9yb2xhJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvaGJidHZcXC9cXGQrXFwuXFxkK1xcLlxcZCtcXHMrXFwoW1xcd1xcc10qO1xccyooXFx3W147XSopOyhbXjtdKikvaSAgICAgICAgICAgIC8vIEhiYlRWIGRldmljZXNcbiAgICAgICAgICAgIF0sIFtbVkVORE9SLCB1dGlsLnRyaW1dLCBbTU9ERUwsIHV0aWwudHJpbV0sIFtUWVBFLCBTTUFSVFRWXV0sIFtcblxuICAgICAgICAgICAgL2hiYnR2LittYXBsZTsoXFxkKykvaVxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgL14vLCAnU21hcnRUViddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgU01BUlRUVl1dLCBbXG5cbiAgICAgICAgICAgIC9cXChkdHZbXFwpO10uKyhhcXVvcykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTaGFycFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnU2hhcnAnXSwgW1RZUEUsIFNNQVJUVFZdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rKChzY2gtaVs4OV0wXFxkfHNody1tMzgwc3xndC1wXFxkezR9fGd0LW5cXGQrfHNnaC10OFs1Nl05fG5leHVzIDEwKSkvaSxcbiAgICAgICAgICAgIC8oKFNNLVRcXHcrKSkvaVxuICAgICAgICAgICAgXSwgW1tWRU5ET1IsICdTYW1zdW5nJ10sIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFsgICAgICAgICAgICAgICAgICAvLyBTYW1zdW5nXG4gICAgICAgICAgICAvc21hcnQtdHYuKyhzYW1zdW5nKS9pXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBbVFlQRSwgU01BUlRUVl0sIE1PREVMXSwgW1xuICAgICAgICAgICAgLygoc1tjZ3BdaC1cXHcrfGd0LVxcdyt8Z2FsYXh5XFxzbmV4dXN8c20tXFx3W1xcd1xcZF0rKSkvaSxcbiAgICAgICAgICAgIC8oc2FtW3N1bmddKilbXFxzLV0qKFxcdystP1tcXHctXSopKi9pLFxuICAgICAgICAgICAgL3NlYy0oKHNnaFxcdyspKS9pXG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ1NhbXN1bmcnXSwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvc2llLShcXHcrKSovaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTaWVtZW5zXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTaWVtZW5zJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKG1hZW1vfG5va2lhKS4qKG45MDB8bHVtaWFcXHNcXGQrKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm9raWFcbiAgICAgICAgICAgIC8obm9raWEpW1xcc18tXT8oW1xcdy1dKykqL2lcbiAgICAgICAgICAgIF0sIFtbVkVORE9SLCAnTm9raWEnXSwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZFxcczNcXC5bXFxzXFx3Oy1dezEwfShhXFxkezN9KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWNlclxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnQWNlciddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKyhbdmxda1xcLT9cXGR7M30pXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBMRyBUYWJsZXRcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0xHJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgL2FuZHJvaWRcXHMzXFwuW1xcc1xcdzstXXsxMH0obGc/KS0oWzA2Y3Y5XXszLDR9KS9pICAgICAgICAgICAgICAgICAgICAgLy8gTEcgVGFibGV0XG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ0xHJ10sIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFtcbiAgICAgICAgICAgIC8obGcpIG5ldGNhc3RcXC50di9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExHIFNtYXJ0VFZcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgU01BUlRUVl1dLCBbXG4gICAgICAgICAgICAvKG5leHVzXFxzWzQ1XSkvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBMR1xuICAgICAgICAgICAgL2xnW2U7XFxzXFwvLV0rKFxcdyspKi9pLFxuICAgICAgICAgICAgL2FuZHJvaWQuK2xnKFxcLT9bXFxkXFx3XSspXFxzK2J1aWxkL2lcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0xHJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rKGlkZWF0YWJbYS16MC05XFwtXFxzXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTGVub3ZvXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdMZW5vdm8nXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9saW51eDsuKygoam9sbGEpKTsvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSm9sbGFcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLygocGViYmxlKSlhcHBcXC9bXFxkXFwuXStcXHMvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUGViYmxlXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIFdFQVJBQkxFXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKztcXHMob3BwbylcXHM/KFtcXHdcXHNdKylcXHNidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9QUE9cbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgL2Nya2V5L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBHb29nbGUgQ2hyb21lY2FzdFxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0Nocm9tZWNhc3QnXSwgW1ZFTkRPUiwgJ0dvb2dsZSddXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rO1xccyhnbGFzcylcXHNcXGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdvb2dsZSBHbGFzc1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnR29vZ2xlJ10sIFtUWVBFLCBXRUFSQUJMRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLis7XFxzKHBpeGVsIGMpXFxzL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBHb29nbGUgUGl4ZWwgQ1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnR29vZ2xlJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rO1xccyhwaXhlbCB4bHxwaXhlbClcXHMvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR29vZ2xlIFBpeGVsXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdHb29nbGUnXSwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLisoXFx3KylcXHMrYnVpbGRcXC9obVxcMS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFhpYW9taSBIb25nbWkgJ251bWVyaWMnIG1vZGVsc1xuICAgICAgICAgICAgL2FuZHJvaWQuKyhobVtcXHNcXC1fXSpub3RlP1tcXHNfXSooPzpcXGRcXHcpPylcXHMrYnVpbGQvaSwgICAgICAgICAgICAgICAvLyBYaWFvbWkgSG9uZ21pXG4gICAgICAgICAgICAvYW5kcm9pZC4rKG1pW1xcc1xcLV9dKig/Om9uZXxvbmVbXFxzX11wbHVzfG5vdGUgbHRlKT9bXFxzX10qKD86XFxkXFx3KT8pXFxzK2J1aWxkL2ksICAgIC8vIFhpYW9taSBNaVxuICAgICAgICAgICAgL2FuZHJvaWQuKyhyZWRtaVtcXHNcXC1fXSooPzpub3RlKT8oPzpbXFxzX10qW1xcd1xcc10rKT8pXFxzK2J1aWxkL2kgICAgICAvLyBSZWRtaSBQaG9uZXNcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsIC9fL2csICcgJ10sIFtWRU5ET1IsICdYaWFvbWknXSwgW1RZUEUsIE1PQklMRV1dLCBbXG4gICAgICAgICAgICAvYW5kcm9pZC4rKG1pW1xcc1xcLV9dKig/OnBhZCk/KD86W1xcc19dKltcXHdcXHNdKyk/KVxccytidWlsZC9pICAgICAgICAgIC8vIE1pIFBhZCB0YWJsZXRzXG4gICAgICAgICAgICBdLFtbTU9ERUwsIC9fL2csICcgJ10sIFtWRU5ET1IsICdYaWFvbWknXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG4gICAgICAgICAgICAvYW5kcm9pZC4rO1xccyhtWzEtNV1cXHNub3RlKVxcc2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1laXp1IFRhYmxldFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnTWVpenUnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLithMDAwKDEpXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9uZVBsdXNcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ09uZVBsdXMnXSwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKFJDVFtcXGRcXHddKylcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSQ0EgVGFibGV0c1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnUkNBJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKihWZW51ZVtcXGRcXHNdKilcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRGVsbCBWZW51ZSBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdEZWxsJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKihRW1R8TV1bXFxkXFx3XSspXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVmVyaXpvbiBUYWJsZXRcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ1Zlcml6b24nXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMrKEJhcm5lc1smXFxzXStOb2JsZVxccyt8Qk5bUlRdKShWPy4qKVxccytidWlsZC9pICAgICAvLyBCYXJuZXMgJiBOb2JsZSBUYWJsZXRcbiAgICAgICAgICAgIF0sIFtbVkVORE9SLCAnQmFybmVzICYgTm9ibGUnXSwgTU9ERUwsIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKyhUTVxcZHszfS4qXFxiKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQmFybmVzICYgTm9ibGUgVGFibGV0XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdOdVZpc2lvbiddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooenRlKT8uKyhrXFxkezJ9KVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgLy8gWlRFIEsgU2VyaWVzIFRhYmxldFxuICAgICAgICAgICAgXSwgW1tWRU5ET1IsICdaVEUnXSwgTU9ERUwsIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKihnZW5cXGR7M30pXFxzK2J1aWxkLio0OWgvaSAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTd2lzcyBHRU4gTW9iaWxlXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTd2lzcyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooenVyXFxkezN9KVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3dpc3MgWlVSIFRhYmxldFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnU3dpc3MnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKChaZWtpKT9UQi4qXFxiKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFpla2kgVGFibGV0c1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnWmVraSddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgLyhhbmRyb2lkKS4rWztcXC9dXFxzKyhbWVJdXFxkezJ9eD8uKilcXHMrYnVpbGQvaSxcbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMrKERyYWdvbltcXC1cXHNdK1RvdWNoXFxzK3xEVCkoLispXFxzK2J1aWxkL2kgICAgICAgICAgLy8gRHJhZ29uIFRvdWNoIFRhYmxldFxuICAgICAgICAgICAgXSwgW1tWRU5ET1IsICdEcmFnb24gVG91Y2gnXSwgTU9ERUwsIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKihOUy0/LispXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluc2lnbmlhIFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0luc2lnbmlhJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKigoTlh8TmV4dCktPy4rKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5leHRCb29rIFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ05leHRCb29rJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKihYdHJlbWVcXF8/KT8oVigxWzA0NV18MlswMTVdfDMwfDQwfDYwfDdbMDVdfDkwKSlcXHMrYnVpbGQvaVxuICAgICAgICAgICAgXSwgW1tWRU5ET1IsICdWb2ljZSddLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbICAgICAgICAgICAgICAgICAgICAvLyBWb2ljZSBYdHJlbWUgUGhvbmVzXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKExWVEVMXFwtPyk/KFYxWzEyXSlcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgIC8vIEx2VGVsIFBob25lc1xuICAgICAgICAgICAgXSwgW1tWRU5ET1IsICdMdlRlbCddLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKFYoMTAwTUR8NzAwTkF8NzAxMXw5MTdHKS4qXFxiKVxccytidWlsZC9pICAgICAgICAgIC8vIEVudml6ZW4gVGFibGV0c1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnRW52aXplbiddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooTGVbXFxzXFwtXStQYW4pW1xcc1xcLV0rKC4qXFxiKVxccytidWlsZC9pICAgICAgICAgICAgIC8vIExlIFBhbiBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKFRyaW9bXFxzXFwtXSouKilcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYWNoU3BlZWQgVGFibGV0c1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnTWFjaFNwZWVkJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKihUcmluaXR5KVtcXC1cXHNdKihUXFxkezN9KVxccytidWlsZC9pICAgICAgICAgICAgICAgIC8vIFRyaW5pdHkgVGFibGV0c1xuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKlRVXygxNDkxKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJvdG9yIFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ1JvdG9yJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rKEtTKC4rKSlcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBbWF6b24gS2luZGxlIFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0FtYXpvbiddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKyhHaWdhc2V0KVtcXHNcXC1dKyhRLispXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBHaWdhc2V0IFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL1xccyh0YWJsZXR8dGFiKVs7XFwvXS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVuaWRlbnRpZmlhYmxlIFRhYmxldFxuICAgICAgICAgICAgL1xccyhtb2JpbGUpKD86WztcXC9dfFxcc3NhZmFyaSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBVbmlkZW50aWZpYWJsZSBNb2JpbGVcbiAgICAgICAgICAgIF0sIFtbVFlQRSwgdXRpbC5sb3dlcml6ZV0sIFZFTkRPUiwgTU9ERUxdLCBbXG5cbiAgICAgICAgICAgIC8oYW5kcm9pZC4rKVs7XFwvXS4rYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdlbmVyaWMgQW5kcm9pZCBEZXZpY2VcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0dlbmVyaWMnXV1cblxuXG4gICAgICAgIC8qLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgICAgICAgICAgIC8vIFRPRE86IG1vdmUgdG8gc3RyaW5nIG1hcFxuICAgICAgICAgICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG4gICAgICAgICAgICAvKEM2NjAzKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvbnkgWHBlcmlhIFogQzY2MDNcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdYcGVyaWEgWiBDNjYwMyddLCBbVkVORE9SLCAnU29ueSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oQzY5MDMpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29ueSBYcGVyaWEgWiAxXG4gICAgICAgICAgICBdLCBbW01PREVMLCAnWHBlcmlhIFogMSddLCBbVkVORE9SLCAnU29ueSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhTTS1HOTAwW0Z8SF0pL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYW1zdW5nIEdhbGF4eSBTNVxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBTNSddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oU00tRzcxMDIpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZyBHYWxheHkgR3JhbmQgMlxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBHcmFuZCAyJ10sIFtWRU5ET1IsICdTYW1zdW5nJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhTTS1HNTMwSCkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYW1zdW5nIEdhbGF4eSBHcmFuZCBQcmltZVxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBHcmFuZCBQcmltZSddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oU00tRzMxM0haKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZyBHYWxheHkgVlxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBWJ10sIFtWRU5ET1IsICdTYW1zdW5nJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhTTS1UODA1KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYW1zdW5nIEdhbGF4eSBUYWIgUyAxMC41XG4gICAgICAgICAgICBdLCBbW01PREVMLCAnR2FsYXh5IFRhYiBTIDEwLjUnXSwgW1ZFTkRPUiwgJ1NhbXN1bmcnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG4gICAgICAgICAgICAvKFNNLUc4MDBGKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNhbXN1bmcgR2FsYXh5IFM1IE1pbmlcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdHYWxheHkgUzUgTWluaSddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oU00tVDMxMSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZyBHYWxheHkgVGFiIDMgOC4wXG4gICAgICAgICAgICBdLCBbW01PREVMLCAnR2FsYXh5IFRhYiAzIDguMCddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgLyhUM0MpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZHZhbiBWYW5kcm9pZCBUM0NcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0FkdmFuJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhBRFZBTiBUMUpcXCspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWR2YW4gVmFuZHJvaWQgVDFKK1xuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ1ZhbmRyb2lkIFQxSisnXSwgW1ZFTkRPUiwgJ0FkdmFuJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhBRFZBTiBTNEEpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZHZhbiBWYW5kcm9pZCBTNEFcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdWYW5kcm9pZCBTNEEnXSwgW1ZFTkRPUiwgJ0FkdmFuJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKFY5NzJNKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFpURSBWOTcyTVxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnWlRFJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKGktbW9iaWxlKVxccyhJUVxcc1tcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpLW1vYmlsZSBJUVxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhJUTYuMykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpLW1vYmlsZSBJUSBJUSA2LjNcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdJUSA2LjMnXSwgW1ZFTkRPUiwgJ2ktbW9iaWxlJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhpLW1vYmlsZSlcXHMoaS1zdHlsZVxcc1tcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaS1tb2JpbGUgaS1TVFlMRVxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhpLVNUWUxFMi4xKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpLW1vYmlsZSBpLVNUWUxFIDIuMVxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ2ktU1RZTEUgMi4xJ10sIFtWRU5ET1IsICdpLW1vYmlsZSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhtb2JpaXN0YXIgdG91Y2ggTEFJIDUxMikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtb2JpaXN0YXIgdG91Y2ggTEFJIDUxMlxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ1RvdWNoIExBSSA1MTInXSwgW1ZFTkRPUiwgJ21vYmlpc3RhciddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLy8vLy8vLy8vLy8vL1xuICAgICAgICAgICAgLy8gRU5EIFRPRE9cbiAgICAgICAgICAgIC8vLy8vLy8vLy8vKi9cblxuICAgICAgICBdLFxuXG4gICAgICAgIGVuZ2luZSA6IFtbXG5cbiAgICAgICAgICAgIC93aW5kb3dzLitcXHNlZGdlXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEVkZ2VIVE1MXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgW05BTUUsICdFZGdlSFRNTCddXSwgW1xuXG4gICAgICAgICAgICAvKHByZXN0bylcXC8oW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFByZXN0b1xuICAgICAgICAgICAgLyh3ZWJraXR8dHJpZGVudHxuZXRmcm9udHxuZXRzdXJmfGFtYXlhfGx5bnh8dzNtKVxcLyhbXFx3XFwuXSspL2ksICAgICAvLyBXZWJLaXQvVHJpZGVudC9OZXRGcm9udC9OZXRTdXJmL0FtYXlhL0x5bngvdzNtXG4gICAgICAgICAgICAvKGtodG1sfHRhc21hbnxsaW5rcylbXFwvXFxzXVxcKD8oW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gS0hUTUwvVGFzbWFuL0xpbmtzXG4gICAgICAgICAgICAvKGljYWIpW1xcL1xcc10oWzIzXVxcLltcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaUNhYlxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC9ydlxcOihbXFx3XFwuXSspLiooZ2Vja28pL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR2Vja29cbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBOQU1FXVxuICAgICAgICBdLFxuXG4gICAgICAgIG9zIDogW1tcblxuICAgICAgICAgICAgLy8gV2luZG93cyBiYXNlZFxuICAgICAgICAgICAgL21pY3Jvc29mdFxccyh3aW5kb3dzKVxccyh2aXN0YXx4cCkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpbmRvd3MgKGlUdW5lcylcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuICAgICAgICAgICAgLyh3aW5kb3dzKVxcc250XFxzNlxcLjI7XFxzKGFybSkvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2luZG93cyBSVFxuICAgICAgICAgICAgLyh3aW5kb3dzXFxzcGhvbmUoPzpcXHNvcykqKVtcXHNcXC9dPyhbXFxkXFwuXFxzXStcXHcpKi9pLCAgICAgICAgICAgICAgICAgIC8vIFdpbmRvd3MgUGhvbmVcbiAgICAgICAgICAgIC8od2luZG93c1xcc21vYmlsZXx3aW5kb3dzKVtcXHNcXC9dPyhbbnRjZVxcZFxcLlxcc10rXFx3KS9pXG4gICAgICAgICAgICBdLCBbTkFNRSwgW1ZFUlNJT04sIG1hcHBlci5zdHIsIG1hcHMub3Mud2luZG93cy52ZXJzaW9uXV0sIFtcbiAgICAgICAgICAgIC8od2luKD89M3w5fG4pfHdpblxcczl4XFxzKShbbnRcXGRcXC5dKykvaVxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnV2luZG93cyddLCBbVkVSU0lPTiwgbWFwcGVyLnN0ciwgbWFwcy5vcy53aW5kb3dzLnZlcnNpb25dXSwgW1xuXG4gICAgICAgICAgICAvLyBNb2JpbGUvRW1iZWRkZWQgT1NcbiAgICAgICAgICAgIC9cXCgoYmIpKDEwKTsvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJsYWNrQmVycnkgMTBcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0JsYWNrQmVycnknXSwgVkVSU0lPTl0sIFtcbiAgICAgICAgICAgIC8oYmxhY2tiZXJyeSlcXHcqXFwvPyhbXFx3XFwuXSspKi9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJsYWNrYmVycnlcbiAgICAgICAgICAgIC8odGl6ZW4pW1xcL1xcc10oW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRpemVuXG4gICAgICAgICAgICAvKGFuZHJvaWR8d2Vib3N8cGFsbVxcc29zfHFueHxiYWRhfHJpbVxcc3RhYmxldFxcc29zfG1lZWdvfGNvbnRpa2kpW1xcL1xccy1dPyhbXFx3XFwuXSspKi9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBbmRyb2lkL1dlYk9TL1BhbG0vUU5YL0JhZGEvUklNL01lZUdvL0NvbnRpa2lcbiAgICAgICAgICAgIC9saW51eDsuKyhzYWlsZmlzaCk7L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2FpbGZpc2ggT1NcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuICAgICAgICAgICAgLyhzeW1iaWFuXFxzP29zfHN5bWJvc3xzNjAoPz07KSlbXFwvXFxzLV0/KFtcXHdcXC5dKykqL2kgICAgICAgICAgICAgICAgIC8vIFN5bWJpYW5cbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ1N5bWJpYW4nXSwgVkVSU0lPTl0sIFtcbiAgICAgICAgICAgIC9cXCgoc2VyaWVzNDApOy9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNlcmllcyA0MFxuICAgICAgICAgICAgXSwgW05BTUVdLCBbXG4gICAgICAgICAgICAvbW96aWxsYS4rXFwobW9iaWxlOy4rZ2Vja28uK2ZpcmVmb3gvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94IE9TXG4gICAgICAgICAgICBdLCBbW05BTUUsICdGaXJlZm94IE9TJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8vIENvbnNvbGVcbiAgICAgICAgICAgIC8obmludGVuZG98cGxheXN0YXRpb24pXFxzKFt3aWRzMzRwb3J0YWJsZXZ1XSspL2ksICAgICAgICAgICAgICAgICAgIC8vIE5pbnRlbmRvL1BsYXlzdGF0aW9uXG5cbiAgICAgICAgICAgIC8vIEdOVS9MaW51eCBiYXNlZFxuICAgICAgICAgICAgLyhtaW50KVtcXC9cXHNcXChdPyhcXHcrKSovaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWludFxuICAgICAgICAgICAgLyhtYWdlaWF8dmVjdG9ybGludXgpWztcXHNdL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWFnZWlhL1ZlY3RvckxpbnV4XG4gICAgICAgICAgICAvKGpvbGl8W2t4bG5dP3VidW50dXxkZWJpYW58W29wZW5dKnN1c2V8Z2VudG9vfCg/PVxccylhcmNofHNsYWNrd2FyZXxmZWRvcmF8bWFuZHJpdmF8Y2VudG9zfHBjbGludXhvc3xyZWRoYXR8emVud2Fsa3xsaW5wdXMpW1xcL1xccy1dPyg/IWNocm9tKShbXFx3XFwuLV0rKSovaSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSm9saS9VYnVudHUvRGViaWFuL1NVU0UvR2VudG9vL0FyY2gvU2xhY2t3YXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZlZG9yYS9NYW5kcml2YS9DZW50T1MvUENMaW51eE9TL1JlZEhhdC9aZW53YWxrL0xpbnB1c1xuICAgICAgICAgICAgLyhodXJkfGxpbnV4KVxccz8oW1xcd1xcLl0rKSovaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIdXJkL0xpbnV4XG4gICAgICAgICAgICAvKGdudSlcXHM/KFtcXHdcXC5dKykqL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdOVVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oY3JvcylcXHNbXFx3XStcXHMoW1xcd1xcLl0rXFx3KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hyb21pdW0gT1NcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0Nocm9taXVtIE9TJ10sIFZFUlNJT05dLFtcblxuICAgICAgICAgICAgLy8gU29sYXJpc1xuICAgICAgICAgICAgLyhzdW5vcylcXHM/KFtcXHdcXC5dK1xcZCkqL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29sYXJpc1xuICAgICAgICAgICAgXSwgW1tOQU1FLCAnU29sYXJpcyddLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvLyBCU0QgYmFzZWRcbiAgICAgICAgICAgIC9cXHMoW2ZyZW50b3BjLV17MCw0fWJzZHxkcmFnb25mbHkpXFxzPyhbXFx3XFwuXSspKi9pICAgICAgICAgICAgICAgICAgIC8vIEZyZWVCU0QvTmV0QlNEL09wZW5CU0QvUEMtQlNEL0RyYWdvbkZseVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLFtcblxuICAgICAgICAgICAgLyhoYWlrdSlcXHMoXFx3KykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSGFpa3VcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSxbXG5cbiAgICAgICAgICAgIC9jZm5ldHdvcmtcXC8uK2Rhcndpbi9pLFxuICAgICAgICAgICAgL2lwW2hvbmVhZF0rKD86Lipvc1xccyhbXFx3XSspXFxzbGlrZVxcc21hY3w7XFxzb3BlcmEpL2kgICAgICAgICAgICAgICAgIC8vIGlPU1xuICAgICAgICAgICAgXSwgW1tWRVJTSU9OLCAvXy9nLCAnLiddLCBbTkFNRSwgJ2lPUyddXSwgW1xuXG4gICAgICAgICAgICAvKG1hY1xcc29zXFxzeClcXHM/KFtcXHdcXHNcXC5dK1xcdykqL2ksXG4gICAgICAgICAgICAvKG1hY2ludG9zaHxtYWMoPz1fcG93ZXJwYylcXHMpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYWMgT1NcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ01hYyBPUyddLCBbVkVSU0lPTiwgL18vZywgJy4nXV0sIFtcblxuICAgICAgICAgICAgLy8gT3RoZXJcbiAgICAgICAgICAgIC8oKD86b3Blbik/c29sYXJpcylbXFwvXFxzLV0/KFtcXHdcXC5dKykqL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvbGFyaXNcbiAgICAgICAgICAgIC8oYWl4KVxccygoXFxkKSg/PVxcLnxcXCl8XFxzKVtcXHdcXC5dKikqL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFJWFxuICAgICAgICAgICAgLyhwbGFuXFxzOXxtaW5peHxiZW9zfG9zXFwvMnxhbWlnYW9zfG1vcnBob3N8cmlzY1xcc29zfG9wZW52bXMpL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBsYW45L01pbml4L0JlT1MvT1MyL0FtaWdhT1MvTW9ycGhPUy9SSVNDT1MvT3BlblZNU1xuICAgICAgICAgICAgLyh1bml4KVxccz8oW1xcd1xcLl0rKSovaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBVTklYXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl1cbiAgICAgICAgXVxuICAgIH07XG5cblxuICAgIC8vLy8vLy8vLy8vLy8vLy8vXG4gICAgLy8gQ29uc3RydWN0b3JcbiAgICAvLy8vLy8vLy8vLy8vLy8vXG4gICAgLypcbiAgICB2YXIgQnJvd3NlciA9IGZ1bmN0aW9uIChuYW1lLCB2ZXJzaW9uKSB7XG4gICAgICAgIHRoaXNbTkFNRV0gPSBuYW1lO1xuICAgICAgICB0aGlzW1ZFUlNJT05dID0gdmVyc2lvbjtcbiAgICB9O1xuICAgIHZhciBDUFUgPSBmdW5jdGlvbiAoYXJjaCkge1xuICAgICAgICB0aGlzW0FSQ0hJVEVDVFVSRV0gPSBhcmNoO1xuICAgIH07XG4gICAgdmFyIERldmljZSA9IGZ1bmN0aW9uICh2ZW5kb3IsIG1vZGVsLCB0eXBlKSB7XG4gICAgICAgIHRoaXNbVkVORE9SXSA9IHZlbmRvcjtcbiAgICAgICAgdGhpc1tNT0RFTF0gPSBtb2RlbDtcbiAgICAgICAgdGhpc1tUWVBFXSA9IHR5cGU7XG4gICAgfTtcbiAgICB2YXIgRW5naW5lID0gQnJvd3NlcjtcbiAgICB2YXIgT1MgPSBCcm93c2VyO1xuICAgICovXG4gICAgdmFyIFVBUGFyc2VyID0gZnVuY3Rpb24gKHVhc3RyaW5nLCBleHRlbnNpb25zKSB7XG5cbiAgICAgICAgaWYgKHR5cGVvZiB1YXN0cmluZyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGV4dGVuc2lvbnMgPSB1YXN0cmluZztcbiAgICAgICAgICAgIHVhc3RyaW5nID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFVBUGFyc2VyKSkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBVQVBhcnNlcih1YXN0cmluZywgZXh0ZW5zaW9ucykuZ2V0UmVzdWx0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdWEgPSB1YXN0cmluZyB8fCAoKHdpbmRvdyAmJiB3aW5kb3cubmF2aWdhdG9yICYmIHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50KSA/IHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50IDogRU1QVFkpO1xuICAgICAgICB2YXIgcmd4bWFwID0gZXh0ZW5zaW9ucyA/IHV0aWwuZXh0ZW5kKHJlZ2V4ZXMsIGV4dGVuc2lvbnMpIDogcmVnZXhlcztcbiAgICAgICAgLy92YXIgYnJvd3NlciA9IG5ldyBCcm93c2VyKCk7XG4gICAgICAgIC8vdmFyIGNwdSA9IG5ldyBDUFUoKTtcbiAgICAgICAgLy92YXIgZGV2aWNlID0gbmV3IERldmljZSgpO1xuICAgICAgICAvL3ZhciBlbmdpbmUgPSBuZXcgRW5naW5lKCk7XG4gICAgICAgIC8vdmFyIG9zID0gbmV3IE9TKCk7XG5cbiAgICAgICAgdGhpcy5nZXRCcm93c2VyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGJyb3dzZXIgPSB7IG5hbWU6IHVuZGVmaW5lZCwgdmVyc2lvbjogdW5kZWZpbmVkIH07XG4gICAgICAgICAgICBtYXBwZXIucmd4LmNhbGwoYnJvd3NlciwgdWEsIHJneG1hcC5icm93c2VyKTtcbiAgICAgICAgICAgIGJyb3dzZXIubWFqb3IgPSB1dGlsLm1ham9yKGJyb3dzZXIudmVyc2lvbik7IC8vIGRlcHJlY2F0ZWRcbiAgICAgICAgICAgIHJldHVybiBicm93c2VyO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldENQVSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBjcHUgPSB7IGFyY2hpdGVjdHVyZTogdW5kZWZpbmVkIH07XG4gICAgICAgICAgICBtYXBwZXIucmd4LmNhbGwoY3B1LCB1YSwgcmd4bWFwLmNwdSk7XG4gICAgICAgICAgICByZXR1cm4gY3B1O1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldERldmljZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBkZXZpY2UgPSB7IHZlbmRvcjogdW5kZWZpbmVkLCBtb2RlbDogdW5kZWZpbmVkLCB0eXBlOiB1bmRlZmluZWQgfTtcbiAgICAgICAgICAgIG1hcHBlci5yZ3guY2FsbChkZXZpY2UsIHVhLCByZ3htYXAuZGV2aWNlKTtcbiAgICAgICAgICAgIHJldHVybiBkZXZpY2U7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ2V0RW5naW5lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGVuZ2luZSA9IHsgbmFtZTogdW5kZWZpbmVkLCB2ZXJzaW9uOiB1bmRlZmluZWQgfTtcbiAgICAgICAgICAgIG1hcHBlci5yZ3guY2FsbChlbmdpbmUsIHVhLCByZ3htYXAuZW5naW5lKTtcbiAgICAgICAgICAgIHJldHVybiBlbmdpbmU7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ2V0T1MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgb3MgPSB7IG5hbWU6IHVuZGVmaW5lZCwgdmVyc2lvbjogdW5kZWZpbmVkIH07XG4gICAgICAgICAgICBtYXBwZXIucmd4LmNhbGwob3MsIHVhLCByZ3htYXAub3MpO1xuICAgICAgICAgICAgcmV0dXJuIG9zO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldFJlc3VsdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgdWEgICAgICA6IHRoaXMuZ2V0VUEoKSxcbiAgICAgICAgICAgICAgICBicm93c2VyIDogdGhpcy5nZXRCcm93c2VyKCksXG4gICAgICAgICAgICAgICAgZW5naW5lICA6IHRoaXMuZ2V0RW5naW5lKCksXG4gICAgICAgICAgICAgICAgb3MgICAgICA6IHRoaXMuZ2V0T1MoKSxcbiAgICAgICAgICAgICAgICBkZXZpY2UgIDogdGhpcy5nZXREZXZpY2UoKSxcbiAgICAgICAgICAgICAgICBjcHUgICAgIDogdGhpcy5nZXRDUFUoKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5nZXRVQSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB1YTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5zZXRVQSA9IGZ1bmN0aW9uICh1YXN0cmluZykge1xuICAgICAgICAgICAgdWEgPSB1YXN0cmluZztcbiAgICAgICAgICAgIC8vYnJvd3NlciA9IG5ldyBCcm93c2VyKCk7XG4gICAgICAgICAgICAvL2NwdSA9IG5ldyBDUFUoKTtcbiAgICAgICAgICAgIC8vZGV2aWNlID0gbmV3IERldmljZSgpO1xuICAgICAgICAgICAgLy9lbmdpbmUgPSBuZXcgRW5naW5lKCk7XG4gICAgICAgICAgICAvL29zID0gbmV3IE9TKCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIFVBUGFyc2VyLlZFUlNJT04gPSBMSUJWRVJTSU9OO1xuICAgIFVBUGFyc2VyLkJST1dTRVIgPSB7XG4gICAgICAgIE5BTUUgICAgOiBOQU1FLFxuICAgICAgICBNQUpPUiAgIDogTUFKT1IsIC8vIGRlcHJlY2F0ZWRcbiAgICAgICAgVkVSU0lPTiA6IFZFUlNJT05cbiAgICB9O1xuICAgIFVBUGFyc2VyLkNQVSA9IHtcbiAgICAgICAgQVJDSElURUNUVVJFIDogQVJDSElURUNUVVJFXG4gICAgfTtcbiAgICBVQVBhcnNlci5ERVZJQ0UgPSB7XG4gICAgICAgIE1PREVMICAgOiBNT0RFTCxcbiAgICAgICAgVkVORE9SICA6IFZFTkRPUixcbiAgICAgICAgVFlQRSAgICA6IFRZUEUsXG4gICAgICAgIENPTlNPTEUgOiBDT05TT0xFLFxuICAgICAgICBNT0JJTEUgIDogTU9CSUxFLFxuICAgICAgICBTTUFSVFRWIDogU01BUlRUVixcbiAgICAgICAgVEFCTEVUICA6IFRBQkxFVCxcbiAgICAgICAgV0VBUkFCTEU6IFdFQVJBQkxFLFxuICAgICAgICBFTUJFRERFRDogRU1CRURERURcbiAgICB9O1xuICAgIFVBUGFyc2VyLkVOR0lORSA9IHtcbiAgICAgICAgTkFNRSAgICA6IE5BTUUsXG4gICAgICAgIFZFUlNJT04gOiBWRVJTSU9OXG4gICAgfTtcbiAgICBVQVBhcnNlci5PUyA9IHtcbiAgICAgICAgTkFNRSAgICA6IE5BTUUsXG4gICAgICAgIFZFUlNJT04gOiBWRVJTSU9OXG4gICAgfTtcbiAgICAvL1VBUGFyc2VyLlV0aWxzID0gdXRpbDtcblxuICAgIC8vLy8vLy8vLy8vXG4gICAgLy8gRXhwb3J0XG4gICAgLy8vLy8vLy8vL1xuXG5cbiAgICAvLyBjaGVjayBqcyBlbnZpcm9ubWVudFxuICAgIGlmICh0eXBlb2YoZXhwb3J0cykgIT09IFVOREVGX1RZUEUpIHtcbiAgICAgICAgLy8gbm9kZWpzIGVudlxuICAgICAgICBpZiAodHlwZW9mIG1vZHVsZSAhPT0gVU5ERUZfVFlQRSAmJiBtb2R1bGUuZXhwb3J0cykge1xuICAgICAgICAgICAgZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0gVUFQYXJzZXI7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVE9ETzogdGVzdCEhISEhISEhXG4gICAgICAgIC8qXG4gICAgICAgIGlmIChyZXF1aXJlICYmIHJlcXVpcmUubWFpbiA9PT0gbW9kdWxlICYmIHByb2Nlc3MpIHtcbiAgICAgICAgICAgIC8vIGNsaVxuICAgICAgICAgICAgdmFyIGpzb25pemUgPSBmdW5jdGlvbiAoYXJyKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlcyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgaW4gYXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlcy5wdXNoKG5ldyBVQVBhcnNlcihhcnJbaV0pLmdldFJlc3VsdCgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcHJvY2Vzcy5zdGRvdXQud3JpdGUoSlNPTi5zdHJpbmdpZnkocmVzLCBudWxsLCAyKSArICdcXG4nKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAocHJvY2Vzcy5zdGRpbi5pc1RUWSkge1xuICAgICAgICAgICAgICAgIC8vIHZpYSBhcmdzXG4gICAgICAgICAgICAgICAganNvbml6ZShwcm9jZXNzLmFyZ3Yuc2xpY2UoMikpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyB2aWEgcGlwZVxuICAgICAgICAgICAgICAgIHZhciBzdHIgPSAnJztcbiAgICAgICAgICAgICAgICBwcm9jZXNzLnN0ZGluLm9uKCdyZWFkYWJsZScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmVhZCA9IHByb2Nlc3Muc3RkaW4ucmVhZCgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVhZCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyICs9IHJlYWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBwcm9jZXNzLnN0ZGluLm9uKCdlbmQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGpzb25pemUoc3RyLnJlcGxhY2UoL1xcbiQvLCAnJykuc3BsaXQoJ1xcbicpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAqL1xuICAgICAgICBleHBvcnRzLlVBUGFyc2VyID0gVUFQYXJzZXI7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gcmVxdWlyZWpzIGVudiAob3B0aW9uYWwpXG4gICAgICAgIGlmICh0eXBlb2YoZGVmaW5lKSA9PT0gRlVOQ19UWVBFICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgICAgIGRlZmluZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFVBUGFyc2VyO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAod2luZG93KSB7XG4gICAgICAgICAgICAvLyBicm93c2VyIGVudlxuICAgICAgICAgICAgd2luZG93LlVBUGFyc2VyID0gVUFQYXJzZXI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBqUXVlcnkvWmVwdG8gc3BlY2lmaWMgKG9wdGlvbmFsKVxuICAgIC8vIE5vdGU6XG4gICAgLy8gICBJbiBBTUQgZW52IHRoZSBnbG9iYWwgc2NvcGUgc2hvdWxkIGJlIGtlcHQgY2xlYW4sIGJ1dCBqUXVlcnkgaXMgYW4gZXhjZXB0aW9uLlxuICAgIC8vICAgalF1ZXJ5IGFsd2F5cyBleHBvcnRzIHRvIGdsb2JhbCBzY29wZSwgdW5sZXNzIGpRdWVyeS5ub0NvbmZsaWN0KHRydWUpIGlzIHVzZWQsXG4gICAgLy8gICBhbmQgd2Ugc2hvdWxkIGNhdGNoIHRoYXQuXG4gICAgdmFyICQgPSB3aW5kb3cgJiYgKHdpbmRvdy5qUXVlcnkgfHwgd2luZG93LlplcHRvKTtcbiAgICBpZiAodHlwZW9mICQgIT09IFVOREVGX1RZUEUpIHtcbiAgICAgICAgdmFyIHBhcnNlciA9IG5ldyBVQVBhcnNlcigpO1xuICAgICAgICAkLnVhID0gcGFyc2VyLmdldFJlc3VsdCgpO1xuICAgICAgICAkLnVhLmdldCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZXIuZ2V0VUEoKTtcbiAgICAgICAgfTtcbiAgICAgICAgJC51YS5zZXQgPSBmdW5jdGlvbiAodWFzdHJpbmcpIHtcbiAgICAgICAgICAgIHBhcnNlci5zZXRVQSh1YXN0cmluZyk7XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gcGFyc2VyLmdldFJlc3VsdCgpO1xuICAgICAgICAgICAgZm9yICh2YXIgcHJvcCBpbiByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAkLnVhW3Byb3BdID0gcmVzdWx0W3Byb3BdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxufSkodHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcgPyB3aW5kb3cgOiB0aGlzKTtcbiIsInZhciB2MSA9IHJlcXVpcmUoJy4vdjEnKTtcbnZhciB2NCA9IHJlcXVpcmUoJy4vdjQnKTtcblxudmFyIHV1aWQgPSB2NDtcbnV1aWQudjEgPSB2MTtcbnV1aWQudjQgPSB2NDtcblxubW9kdWxlLmV4cG9ydHMgPSB1dWlkO1xuIiwiLyoqXG4gKiBDb252ZXJ0IGFycmF5IG9mIDE2IGJ5dGUgdmFsdWVzIHRvIFVVSUQgc3RyaW5nIGZvcm1hdCBvZiB0aGUgZm9ybTpcbiAqIFhYWFhYWFhYLVhYWFgtWFhYWC1YWFhYLVhYWFhYWFhYWFhYWFxuICovXG52YXIgYnl0ZVRvSGV4ID0gW107XG5mb3IgKHZhciBpID0gMDsgaSA8IDI1NjsgKytpKSB7XG4gIGJ5dGVUb0hleFtpXSA9IChpICsgMHgxMDApLnRvU3RyaW5nKDE2KS5zdWJzdHIoMSk7XG59XG5cbmZ1bmN0aW9uIGJ5dGVzVG9VdWlkKGJ1Ziwgb2Zmc2V0KSB7XG4gIHZhciBpID0gb2Zmc2V0IHx8IDA7XG4gIHZhciBidGggPSBieXRlVG9IZXg7XG4gIHJldHVybiBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gKyAnLScgK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dICsgJy0nICtcbiAgICAgICAgICBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArICctJyArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gKyAnLScgK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dICtcbiAgICAgICAgICBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYnl0ZXNUb1V1aWQ7XG4iLCIvLyBVbmlxdWUgSUQgY3JlYXRpb24gcmVxdWlyZXMgYSBoaWdoIHF1YWxpdHkgcmFuZG9tICMgZ2VuZXJhdG9yLiAgSW4gdGhlXG4vLyBicm93c2VyIHRoaXMgaXMgYSBsaXR0bGUgY29tcGxpY2F0ZWQgZHVlIHRvIHVua25vd24gcXVhbGl0eSBvZiBNYXRoLnJhbmRvbSgpXG4vLyBhbmQgaW5jb25zaXN0ZW50IHN1cHBvcnQgZm9yIHRoZSBgY3J5cHRvYCBBUEkuICBXZSBkbyB0aGUgYmVzdCB3ZSBjYW4gdmlhXG4vLyBmZWF0dXJlLWRldGVjdGlvblxudmFyIHJuZztcblxudmFyIGNyeXB0byA9IGdsb2JhbC5jcnlwdG8gfHwgZ2xvYmFsLm1zQ3J5cHRvOyAvLyBmb3IgSUUgMTFcbmlmIChjcnlwdG8gJiYgY3J5cHRvLmdldFJhbmRvbVZhbHVlcykge1xuICAvLyBXSEFUV0cgY3J5cHRvIFJORyAtIGh0dHA6Ly93aWtpLndoYXR3Zy5vcmcvd2lraS9DcnlwdG9cbiAgdmFyIHJuZHM4ID0gbmV3IFVpbnQ4QXJyYXkoMTYpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmXG4gIHJuZyA9IGZ1bmN0aW9uIHdoYXR3Z1JORygpIHtcbiAgICBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKHJuZHM4KTtcbiAgICByZXR1cm4gcm5kczg7XG4gIH07XG59XG5cbmlmICghcm5nKSB7XG4gIC8vIE1hdGgucmFuZG9tKCktYmFzZWQgKFJORylcbiAgLy9cbiAgLy8gSWYgYWxsIGVsc2UgZmFpbHMsIHVzZSBNYXRoLnJhbmRvbSgpLiAgSXQncyBmYXN0LCBidXQgaXMgb2YgdW5zcGVjaWZpZWRcbiAgLy8gcXVhbGl0eS5cbiAgdmFyIHJuZHMgPSBuZXcgQXJyYXkoMTYpO1xuICBybmcgPSBmdW5jdGlvbigpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgcjsgaSA8IDE2OyBpKyspIHtcbiAgICAgIGlmICgoaSAmIDB4MDMpID09PSAwKSByID0gTWF0aC5yYW5kb20oKSAqIDB4MTAwMDAwMDAwO1xuICAgICAgcm5kc1tpXSA9IHIgPj4+ICgoaSAmIDB4MDMpIDw8IDMpICYgMHhmZjtcbiAgICB9XG5cbiAgICByZXR1cm4gcm5kcztcbiAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBybmc7XG4iLCJ2YXIgcm5nID0gcmVxdWlyZSgnLi9saWIvcm5nJyk7XG52YXIgYnl0ZXNUb1V1aWQgPSByZXF1aXJlKCcuL2xpYi9ieXRlc1RvVXVpZCcpO1xuXG4vLyAqKmB2MSgpYCAtIEdlbmVyYXRlIHRpbWUtYmFzZWQgVVVJRCoqXG4vL1xuLy8gSW5zcGlyZWQgYnkgaHR0cHM6Ly9naXRodWIuY29tL0xpb3NLL1VVSUQuanNcbi8vIGFuZCBodHRwOi8vZG9jcy5weXRob24ub3JnL2xpYnJhcnkvdXVpZC5odG1sXG5cbi8vIHJhbmRvbSAjJ3Mgd2UgbmVlZCB0byBpbml0IG5vZGUgYW5kIGNsb2Nrc2VxXG52YXIgX3NlZWRCeXRlcyA9IHJuZygpO1xuXG4vLyBQZXIgNC41LCBjcmVhdGUgYW5kIDQ4LWJpdCBub2RlIGlkLCAoNDcgcmFuZG9tIGJpdHMgKyBtdWx0aWNhc3QgYml0ID0gMSlcbnZhciBfbm9kZUlkID0gW1xuICBfc2VlZEJ5dGVzWzBdIHwgMHgwMSxcbiAgX3NlZWRCeXRlc1sxXSwgX3NlZWRCeXRlc1syXSwgX3NlZWRCeXRlc1szXSwgX3NlZWRCeXRlc1s0XSwgX3NlZWRCeXRlc1s1XVxuXTtcblxuLy8gUGVyIDQuMi4yLCByYW5kb21pemUgKDE0IGJpdCkgY2xvY2tzZXFcbnZhciBfY2xvY2tzZXEgPSAoX3NlZWRCeXRlc1s2XSA8PCA4IHwgX3NlZWRCeXRlc1s3XSkgJiAweDNmZmY7XG5cbi8vIFByZXZpb3VzIHV1aWQgY3JlYXRpb24gdGltZVxudmFyIF9sYXN0TVNlY3MgPSAwLCBfbGFzdE5TZWNzID0gMDtcblxuLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9icm9vZmEvbm9kZS11dWlkIGZvciBBUEkgZGV0YWlsc1xuZnVuY3Rpb24gdjEob3B0aW9ucywgYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBidWYgJiYgb2Zmc2V0IHx8IDA7XG4gIHZhciBiID0gYnVmIHx8IFtdO1xuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gIHZhciBjbG9ja3NlcSA9IG9wdGlvbnMuY2xvY2tzZXEgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuY2xvY2tzZXEgOiBfY2xvY2tzZXE7XG5cbiAgLy8gVVVJRCB0aW1lc3RhbXBzIGFyZSAxMDAgbmFuby1zZWNvbmQgdW5pdHMgc2luY2UgdGhlIEdyZWdvcmlhbiBlcG9jaCxcbiAgLy8gKDE1ODItMTAtMTUgMDA6MDApLiAgSlNOdW1iZXJzIGFyZW4ndCBwcmVjaXNlIGVub3VnaCBmb3IgdGhpcywgc29cbiAgLy8gdGltZSBpcyBoYW5kbGVkIGludGVybmFsbHkgYXMgJ21zZWNzJyAoaW50ZWdlciBtaWxsaXNlY29uZHMpIGFuZCAnbnNlY3MnXG4gIC8vICgxMDAtbmFub3NlY29uZHMgb2Zmc2V0IGZyb20gbXNlY3MpIHNpbmNlIHVuaXggZXBvY2gsIDE5NzAtMDEtMDEgMDA6MDAuXG4gIHZhciBtc2VjcyA9IG9wdGlvbnMubXNlY3MgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubXNlY3MgOiBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuICAvLyBQZXIgNC4yLjEuMiwgdXNlIGNvdW50IG9mIHV1aWQncyBnZW5lcmF0ZWQgZHVyaW5nIHRoZSBjdXJyZW50IGNsb2NrXG4gIC8vIGN5Y2xlIHRvIHNpbXVsYXRlIGhpZ2hlciByZXNvbHV0aW9uIGNsb2NrXG4gIHZhciBuc2VjcyA9IG9wdGlvbnMubnNlY3MgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubnNlY3MgOiBfbGFzdE5TZWNzICsgMTtcblxuICAvLyBUaW1lIHNpbmNlIGxhc3QgdXVpZCBjcmVhdGlvbiAoaW4gbXNlY3MpXG4gIHZhciBkdCA9IChtc2VjcyAtIF9sYXN0TVNlY3MpICsgKG5zZWNzIC0gX2xhc3ROU2VjcykvMTAwMDA7XG5cbiAgLy8gUGVyIDQuMi4xLjIsIEJ1bXAgY2xvY2tzZXEgb24gY2xvY2sgcmVncmVzc2lvblxuICBpZiAoZHQgPCAwICYmIG9wdGlvbnMuY2xvY2tzZXEgPT09IHVuZGVmaW5lZCkge1xuICAgIGNsb2Nrc2VxID0gY2xvY2tzZXEgKyAxICYgMHgzZmZmO1xuICB9XG5cbiAgLy8gUmVzZXQgbnNlY3MgaWYgY2xvY2sgcmVncmVzc2VzIChuZXcgY2xvY2tzZXEpIG9yIHdlJ3ZlIG1vdmVkIG9udG8gYSBuZXdcbiAgLy8gdGltZSBpbnRlcnZhbFxuICBpZiAoKGR0IDwgMCB8fCBtc2VjcyA+IF9sYXN0TVNlY3MpICYmIG9wdGlvbnMubnNlY3MgPT09IHVuZGVmaW5lZCkge1xuICAgIG5zZWNzID0gMDtcbiAgfVxuXG4gIC8vIFBlciA0LjIuMS4yIFRocm93IGVycm9yIGlmIHRvbyBtYW55IHV1aWRzIGFyZSByZXF1ZXN0ZWRcbiAgaWYgKG5zZWNzID49IDEwMDAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd1dWlkLnYxKCk6IENhblxcJ3QgY3JlYXRlIG1vcmUgdGhhbiAxME0gdXVpZHMvc2VjJyk7XG4gIH1cblxuICBfbGFzdE1TZWNzID0gbXNlY3M7XG4gIF9sYXN0TlNlY3MgPSBuc2VjcztcbiAgX2Nsb2Nrc2VxID0gY2xvY2tzZXE7XG5cbiAgLy8gUGVyIDQuMS40IC0gQ29udmVydCBmcm9tIHVuaXggZXBvY2ggdG8gR3JlZ29yaWFuIGVwb2NoXG4gIG1zZWNzICs9IDEyMjE5MjkyODAwMDAwO1xuXG4gIC8vIGB0aW1lX2xvd2BcbiAgdmFyIHRsID0gKChtc2VjcyAmIDB4ZmZmZmZmZikgKiAxMDAwMCArIG5zZWNzKSAlIDB4MTAwMDAwMDAwO1xuICBiW2krK10gPSB0bCA+Pj4gMjQgJiAweGZmO1xuICBiW2krK10gPSB0bCA+Pj4gMTYgJiAweGZmO1xuICBiW2krK10gPSB0bCA+Pj4gOCAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRsICYgMHhmZjtcblxuICAvLyBgdGltZV9taWRgXG4gIHZhciB0bWggPSAobXNlY3MgLyAweDEwMDAwMDAwMCAqIDEwMDAwKSAmIDB4ZmZmZmZmZjtcbiAgYltpKytdID0gdG1oID4+PiA4ICYgMHhmZjtcbiAgYltpKytdID0gdG1oICYgMHhmZjtcblxuICAvLyBgdGltZV9oaWdoX2FuZF92ZXJzaW9uYFxuICBiW2krK10gPSB0bWggPj4+IDI0ICYgMHhmIHwgMHgxMDsgLy8gaW5jbHVkZSB2ZXJzaW9uXG4gIGJbaSsrXSA9IHRtaCA+Pj4gMTYgJiAweGZmO1xuXG4gIC8vIGBjbG9ja19zZXFfaGlfYW5kX3Jlc2VydmVkYCAoUGVyIDQuMi4yIC0gaW5jbHVkZSB2YXJpYW50KVxuICBiW2krK10gPSBjbG9ja3NlcSA+Pj4gOCB8IDB4ODA7XG5cbiAgLy8gYGNsb2NrX3NlcV9sb3dgXG4gIGJbaSsrXSA9IGNsb2Nrc2VxICYgMHhmZjtcblxuICAvLyBgbm9kZWBcbiAgdmFyIG5vZGUgPSBvcHRpb25zLm5vZGUgfHwgX25vZGVJZDtcbiAgZm9yICh2YXIgbiA9IDA7IG4gPCA2OyArK24pIHtcbiAgICBiW2kgKyBuXSA9IG5vZGVbbl07XG4gIH1cblxuICByZXR1cm4gYnVmID8gYnVmIDogYnl0ZXNUb1V1aWQoYik7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdjE7XG4iLCJ2YXIgcm5nID0gcmVxdWlyZSgnLi9saWIvcm5nJyk7XG52YXIgYnl0ZXNUb1V1aWQgPSByZXF1aXJlKCcuL2xpYi9ieXRlc1RvVXVpZCcpO1xuXG5mdW5jdGlvbiB2NChvcHRpb25zLCBidWYsIG9mZnNldCkge1xuICB2YXIgaSA9IGJ1ZiAmJiBvZmZzZXQgfHwgMDtcblxuICBpZiAodHlwZW9mKG9wdGlvbnMpID09ICdzdHJpbmcnKSB7XG4gICAgYnVmID0gb3B0aW9ucyA9PSAnYmluYXJ5JyA/IG5ldyBBcnJheSgxNikgOiBudWxsO1xuICAgIG9wdGlvbnMgPSBudWxsO1xuICB9XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gIHZhciBybmRzID0gb3B0aW9ucy5yYW5kb20gfHwgKG9wdGlvbnMucm5nIHx8IHJuZykoKTtcblxuICAvLyBQZXIgNC40LCBzZXQgYml0cyBmb3IgdmVyc2lvbiBhbmQgYGNsb2NrX3NlcV9oaV9hbmRfcmVzZXJ2ZWRgXG4gIHJuZHNbNl0gPSAocm5kc1s2XSAmIDB4MGYpIHwgMHg0MDtcbiAgcm5kc1s4XSA9IChybmRzWzhdICYgMHgzZikgfCAweDgwO1xuXG4gIC8vIENvcHkgYnl0ZXMgdG8gYnVmZmVyLCBpZiBwcm92aWRlZFxuICBpZiAoYnVmKSB7XG4gICAgZm9yICh2YXIgaWkgPSAwOyBpaSA8IDE2OyArK2lpKSB7XG4gICAgICBidWZbaSArIGlpXSA9IHJuZHNbaWldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBidWYgfHwgYnl0ZXNUb1V1aWQocm5kcyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdjQ7XG4iLCIvKlxuICogIENvcHlyaWdodCAoYykgMjAxNiBUaGUgV2ViUlRDIHByb2plY3QgYXV0aG9ycy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiAgVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYSBCU0Qtc3R5bGUgbGljZW5zZVxuICogIHRoYXQgY2FuIGJlIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3Qgb2YgdGhlIHNvdXJjZVxuICogIHRyZWUuXG4gKi9cbiAvKiBlc2xpbnQtZW52IG5vZGUgKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgYWRhcHRlckZhY3RvcnkgPSByZXF1aXJlKCcuL2FkYXB0ZXJfZmFjdG9yeS5qcycpO1xubW9kdWxlLmV4cG9ydHMgPSBhZGFwdGVyRmFjdG9yeSh7d2luZG93OiBnbG9iYWwud2luZG93fSk7XG4iLCIvKlxuICogIENvcHlyaWdodCAoYykgMjAxNiBUaGUgV2ViUlRDIHByb2plY3QgYXV0aG9ycy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiAgVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYSBCU0Qtc3R5bGUgbGljZW5zZVxuICogIHRoYXQgY2FuIGJlIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3Qgb2YgdGhlIHNvdXJjZVxuICogIHRyZWUuXG4gKi9cbiAvKiBlc2xpbnQtZW52IG5vZGUgKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbHMgPSByZXF1aXJlKCcuL3V0aWxzJyk7XG4vLyBTaGltbWluZyBzdGFydHMgaGVyZS5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZGVwZW5kZW5jaWVzLCBvcHRzKSB7XG4gIHZhciB3aW5kb3cgPSBkZXBlbmRlbmNpZXMgJiYgZGVwZW5kZW5jaWVzLndpbmRvdztcblxuICB2YXIgb3B0aW9ucyA9IHtcbiAgICBzaGltQ2hyb21lOiB0cnVlLFxuICAgIHNoaW1GaXJlZm94OiB0cnVlLFxuICAgIHNoaW1FZGdlOiB0cnVlLFxuICAgIHNoaW1TYWZhcmk6IHRydWUsXG4gIH07XG5cbiAgZm9yICh2YXIga2V5IGluIG9wdHMpIHtcbiAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChvcHRzLCBrZXkpKSB7XG4gICAgICBvcHRpb25zW2tleV0gPSBvcHRzW2tleV07XG4gICAgfVxuICB9XG5cbiAgLy8gVXRpbHMuXG4gIHZhciBsb2dnaW5nID0gdXRpbHMubG9nO1xuICB2YXIgYnJvd3NlckRldGFpbHMgPSB1dGlscy5kZXRlY3RCcm93c2VyKHdpbmRvdyk7XG5cbiAgLy8gVW5jb21tZW50IHRoZSBsaW5lIGJlbG93IGlmIHlvdSB3YW50IGxvZ2dpbmcgdG8gb2NjdXIsIGluY2x1ZGluZyBsb2dnaW5nXG4gIC8vIGZvciB0aGUgc3dpdGNoIHN0YXRlbWVudCBiZWxvdy4gQ2FuIGFsc28gYmUgdHVybmVkIG9uIGluIHRoZSBicm93c2VyIHZpYVxuICAvLyBhZGFwdGVyLmRpc2FibGVMb2coZmFsc2UpLCBidXQgdGhlbiBsb2dnaW5nIGZyb20gdGhlIHN3aXRjaCBzdGF0ZW1lbnQgYmVsb3dcbiAgLy8gd2lsbCBub3QgYXBwZWFyLlxuICAvLyByZXF1aXJlKCcuL3V0aWxzJykuZGlzYWJsZUxvZyhmYWxzZSk7XG5cbiAgLy8gQnJvd3NlciBzaGltcy5cbiAgdmFyIGNocm9tZVNoaW0gPSByZXF1aXJlKCcuL2Nocm9tZS9jaHJvbWVfc2hpbScpIHx8IG51bGw7XG4gIHZhciBlZGdlU2hpbSA9IHJlcXVpcmUoJy4vZWRnZS9lZGdlX3NoaW0nKSB8fCBudWxsO1xuICB2YXIgZmlyZWZveFNoaW0gPSByZXF1aXJlKCcuL2ZpcmVmb3gvZmlyZWZveF9zaGltJykgfHwgbnVsbDtcbiAgdmFyIHNhZmFyaVNoaW0gPSByZXF1aXJlKCcuL3NhZmFyaS9zYWZhcmlfc2hpbScpIHx8IG51bGw7XG4gIHZhciBjb21tb25TaGltID0gcmVxdWlyZSgnLi9jb21tb25fc2hpbScpIHx8IG51bGw7XG5cbiAgLy8gRXhwb3J0IHRvIHRoZSBhZGFwdGVyIGdsb2JhbCBvYmplY3QgdmlzaWJsZSBpbiB0aGUgYnJvd3Nlci5cbiAgdmFyIGFkYXB0ZXIgPSB7XG4gICAgYnJvd3NlckRldGFpbHM6IGJyb3dzZXJEZXRhaWxzLFxuICAgIGNvbW1vblNoaW06IGNvbW1vblNoaW0sXG4gICAgZXh0cmFjdFZlcnNpb246IHV0aWxzLmV4dHJhY3RWZXJzaW9uLFxuICAgIGRpc2FibGVMb2c6IHV0aWxzLmRpc2FibGVMb2csXG4gICAgZGlzYWJsZVdhcm5pbmdzOiB1dGlscy5kaXNhYmxlV2FybmluZ3NcbiAgfTtcblxuICAvLyBTaGltIGJyb3dzZXIgaWYgZm91bmQuXG4gIHN3aXRjaCAoYnJvd3NlckRldGFpbHMuYnJvd3Nlcikge1xuICAgIGNhc2UgJ2Nocm9tZSc6XG4gICAgICBpZiAoIWNocm9tZVNoaW0gfHwgIWNocm9tZVNoaW0uc2hpbVBlZXJDb25uZWN0aW9uIHx8XG4gICAgICAgICAgIW9wdGlvbnMuc2hpbUNocm9tZSkge1xuICAgICAgICBsb2dnaW5nKCdDaHJvbWUgc2hpbSBpcyBub3QgaW5jbHVkZWQgaW4gdGhpcyBhZGFwdGVyIHJlbGVhc2UuJyk7XG4gICAgICAgIHJldHVybiBhZGFwdGVyO1xuICAgICAgfVxuICAgICAgbG9nZ2luZygnYWRhcHRlci5qcyBzaGltbWluZyBjaHJvbWUuJyk7XG4gICAgICAvLyBFeHBvcnQgdG8gdGhlIGFkYXB0ZXIgZ2xvYmFsIG9iamVjdCB2aXNpYmxlIGluIHRoZSBicm93c2VyLlxuICAgICAgYWRhcHRlci5icm93c2VyU2hpbSA9IGNocm9tZVNoaW07XG4gICAgICBjb21tb25TaGltLnNoaW1DcmVhdGVPYmplY3RVUkwod2luZG93KTtcblxuICAgICAgY2hyb21lU2hpbS5zaGltR2V0VXNlck1lZGlhKHdpbmRvdyk7XG4gICAgICBjaHJvbWVTaGltLnNoaW1NZWRpYVN0cmVhbSh3aW5kb3cpO1xuICAgICAgY2hyb21lU2hpbS5zaGltU291cmNlT2JqZWN0KHdpbmRvdyk7XG4gICAgICBjaHJvbWVTaGltLnNoaW1QZWVyQ29ubmVjdGlvbih3aW5kb3cpO1xuICAgICAgY2hyb21lU2hpbS5zaGltT25UcmFjayh3aW5kb3cpO1xuICAgICAgY2hyb21lU2hpbS5zaGltQWRkVHJhY2tSZW1vdmVUcmFjayh3aW5kb3cpO1xuICAgICAgY2hyb21lU2hpbS5zaGltR2V0U2VuZGVyc1dpdGhEdG1mKHdpbmRvdyk7XG5cbiAgICAgIGNvbW1vblNoaW0uc2hpbVJUQ0ljZUNhbmRpZGF0ZSh3aW5kb3cpO1xuICAgICAgY29tbW9uU2hpbS5zaGltTWF4TWVzc2FnZVNpemUod2luZG93KTtcbiAgICAgIGNvbW1vblNoaW0uc2hpbVNlbmRUaHJvd1R5cGVFcnJvcih3aW5kb3cpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnZmlyZWZveCc6XG4gICAgICBpZiAoIWZpcmVmb3hTaGltIHx8ICFmaXJlZm94U2hpbS5zaGltUGVlckNvbm5lY3Rpb24gfHxcbiAgICAgICAgICAhb3B0aW9ucy5zaGltRmlyZWZveCkge1xuICAgICAgICBsb2dnaW5nKCdGaXJlZm94IHNoaW0gaXMgbm90IGluY2x1ZGVkIGluIHRoaXMgYWRhcHRlciByZWxlYXNlLicpO1xuICAgICAgICByZXR1cm4gYWRhcHRlcjtcbiAgICAgIH1cbiAgICAgIGxvZ2dpbmcoJ2FkYXB0ZXIuanMgc2hpbW1pbmcgZmlyZWZveC4nKTtcbiAgICAgIC8vIEV4cG9ydCB0byB0aGUgYWRhcHRlciBnbG9iYWwgb2JqZWN0IHZpc2libGUgaW4gdGhlIGJyb3dzZXIuXG4gICAgICBhZGFwdGVyLmJyb3dzZXJTaGltID0gZmlyZWZveFNoaW07XG4gICAgICBjb21tb25TaGltLnNoaW1DcmVhdGVPYmplY3RVUkwod2luZG93KTtcblxuICAgICAgZmlyZWZveFNoaW0uc2hpbUdldFVzZXJNZWRpYSh3aW5kb3cpO1xuICAgICAgZmlyZWZveFNoaW0uc2hpbVNvdXJjZU9iamVjdCh3aW5kb3cpO1xuICAgICAgZmlyZWZveFNoaW0uc2hpbVBlZXJDb25uZWN0aW9uKHdpbmRvdyk7XG4gICAgICBmaXJlZm94U2hpbS5zaGltT25UcmFjayh3aW5kb3cpO1xuICAgICAgZmlyZWZveFNoaW0uc2hpbVJlbW92ZVN0cmVhbSh3aW5kb3cpO1xuXG4gICAgICBjb21tb25TaGltLnNoaW1SVENJY2VDYW5kaWRhdGUod2luZG93KTtcbiAgICAgIGNvbW1vblNoaW0uc2hpbU1heE1lc3NhZ2VTaXplKHdpbmRvdyk7XG4gICAgICBjb21tb25TaGltLnNoaW1TZW5kVGhyb3dUeXBlRXJyb3Iod2luZG93KTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2VkZ2UnOlxuICAgICAgaWYgKCFlZGdlU2hpbSB8fCAhZWRnZVNoaW0uc2hpbVBlZXJDb25uZWN0aW9uIHx8ICFvcHRpb25zLnNoaW1FZGdlKSB7XG4gICAgICAgIGxvZ2dpbmcoJ01TIGVkZ2Ugc2hpbSBpcyBub3QgaW5jbHVkZWQgaW4gdGhpcyBhZGFwdGVyIHJlbGVhc2UuJyk7XG4gICAgICAgIHJldHVybiBhZGFwdGVyO1xuICAgICAgfVxuICAgICAgbG9nZ2luZygnYWRhcHRlci5qcyBzaGltbWluZyBlZGdlLicpO1xuICAgICAgLy8gRXhwb3J0IHRvIHRoZSBhZGFwdGVyIGdsb2JhbCBvYmplY3QgdmlzaWJsZSBpbiB0aGUgYnJvd3Nlci5cbiAgICAgIGFkYXB0ZXIuYnJvd3NlclNoaW0gPSBlZGdlU2hpbTtcbiAgICAgIGNvbW1vblNoaW0uc2hpbUNyZWF0ZU9iamVjdFVSTCh3aW5kb3cpO1xuXG4gICAgICBlZGdlU2hpbS5zaGltR2V0VXNlck1lZGlhKHdpbmRvdyk7XG4gICAgICBlZGdlU2hpbS5zaGltUGVlckNvbm5lY3Rpb24od2luZG93KTtcbiAgICAgIGVkZ2VTaGltLnNoaW1SZXBsYWNlVHJhY2sod2luZG93KTtcblxuICAgICAgLy8gdGhlIGVkZ2Ugc2hpbSBpbXBsZW1lbnRzIHRoZSBmdWxsIFJUQ0ljZUNhbmRpZGF0ZSBvYmplY3QuXG5cbiAgICAgIGNvbW1vblNoaW0uc2hpbU1heE1lc3NhZ2VTaXplKHdpbmRvdyk7XG4gICAgICBjb21tb25TaGltLnNoaW1TZW5kVGhyb3dUeXBlRXJyb3Iod2luZG93KTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3NhZmFyaSc6XG4gICAgICBpZiAoIXNhZmFyaVNoaW0gfHwgIW9wdGlvbnMuc2hpbVNhZmFyaSkge1xuICAgICAgICBsb2dnaW5nKCdTYWZhcmkgc2hpbSBpcyBub3QgaW5jbHVkZWQgaW4gdGhpcyBhZGFwdGVyIHJlbGVhc2UuJyk7XG4gICAgICAgIHJldHVybiBhZGFwdGVyO1xuICAgICAgfVxuICAgICAgbG9nZ2luZygnYWRhcHRlci5qcyBzaGltbWluZyBzYWZhcmkuJyk7XG4gICAgICAvLyBFeHBvcnQgdG8gdGhlIGFkYXB0ZXIgZ2xvYmFsIG9iamVjdCB2aXNpYmxlIGluIHRoZSBicm93c2VyLlxuICAgICAgYWRhcHRlci5icm93c2VyU2hpbSA9IHNhZmFyaVNoaW07XG4gICAgICBjb21tb25TaGltLnNoaW1DcmVhdGVPYmplY3RVUkwod2luZG93KTtcblxuICAgICAgc2FmYXJpU2hpbS5zaGltUlRDSWNlU2VydmVyVXJscyh3aW5kb3cpO1xuICAgICAgc2FmYXJpU2hpbS5zaGltQ2FsbGJhY2tzQVBJKHdpbmRvdyk7XG4gICAgICBzYWZhcmlTaGltLnNoaW1Mb2NhbFN0cmVhbXNBUEkod2luZG93KTtcbiAgICAgIHNhZmFyaVNoaW0uc2hpbVJlbW90ZVN0cmVhbXNBUEkod2luZG93KTtcbiAgICAgIHNhZmFyaVNoaW0uc2hpbVRyYWNrRXZlbnRUcmFuc2NlaXZlcih3aW5kb3cpO1xuICAgICAgc2FmYXJpU2hpbS5zaGltR2V0VXNlck1lZGlhKHdpbmRvdyk7XG4gICAgICBzYWZhcmlTaGltLnNoaW1DcmVhdGVPZmZlckxlZ2FjeSh3aW5kb3cpO1xuXG4gICAgICBjb21tb25TaGltLnNoaW1SVENJY2VDYW5kaWRhdGUod2luZG93KTtcbiAgICAgIGNvbW1vblNoaW0uc2hpbU1heE1lc3NhZ2VTaXplKHdpbmRvdyk7XG4gICAgICBjb21tb25TaGltLnNoaW1TZW5kVGhyb3dUeXBlRXJyb3Iod2luZG93KTtcbiAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICBsb2dnaW5nKCdVbnN1cHBvcnRlZCBicm93c2VyIScpO1xuICAgICAgYnJlYWs7XG4gIH1cblxuICByZXR1cm4gYWRhcHRlcjtcbn07XG4iLCJcbi8qXG4gKiAgQ29weXJpZ2h0IChjKSAyMDE2IFRoZSBXZWJSVEMgcHJvamVjdCBhdXRob3JzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqICBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhIEJTRC1zdHlsZSBsaWNlbnNlXG4gKiAgdGhhdCBjYW4gYmUgZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBvZiB0aGUgc291cmNlXG4gKiAgdHJlZS5cbiAqL1xuIC8qIGVzbGludC1lbnYgbm9kZSAqL1xuJ3VzZSBzdHJpY3QnO1xudmFyIHV0aWxzID0gcmVxdWlyZSgnLi4vdXRpbHMuanMnKTtcbnZhciBsb2dnaW5nID0gdXRpbHMubG9nO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgc2hpbUdldFVzZXJNZWRpYTogcmVxdWlyZSgnLi9nZXR1c2VybWVkaWEnKSxcbiAgc2hpbU1lZGlhU3RyZWFtOiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICB3aW5kb3cuTWVkaWFTdHJlYW0gPSB3aW5kb3cuTWVkaWFTdHJlYW0gfHwgd2luZG93LndlYmtpdE1lZGlhU3RyZWFtO1xuICB9LFxuXG4gIHNoaW1PblRyYWNrOiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcgJiYgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uICYmICEoJ29udHJhY2snIGluXG4gICAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUpKSB7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkod2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSwgJ29udHJhY2snLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuX29udHJhY2s7XG4gICAgICAgIH0sXG4gICAgICAgIHNldDogZnVuY3Rpb24oZikge1xuICAgICAgICAgIGlmICh0aGlzLl9vbnRyYWNrKSB7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RyYWNrJywgdGhpcy5fb250cmFjayk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcigndHJhY2snLCB0aGlzLl9vbnRyYWNrID0gZik7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgdmFyIG9yaWdTZXRSZW1vdGVEZXNjcmlwdGlvbiA9XG4gICAgICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5zZXRSZW1vdGVEZXNjcmlwdGlvbjtcbiAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuc2V0UmVtb3RlRGVzY3JpcHRpb24gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHBjID0gdGhpcztcbiAgICAgICAgaWYgKCFwYy5fb250cmFja3BvbHkpIHtcbiAgICAgICAgICBwYy5fb250cmFja3BvbHkgPSBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICAvLyBvbmFkZHN0cmVhbSBkb2VzIG5vdCBmaXJlIHdoZW4gYSB0cmFjayBpcyBhZGRlZCB0byBhbiBleGlzdGluZ1xuICAgICAgICAgICAgLy8gc3RyZWFtLiBCdXQgc3RyZWFtLm9uYWRkdHJhY2sgaXMgaW1wbGVtZW50ZWQgc28gd2UgdXNlIHRoYXQuXG4gICAgICAgICAgICBlLnN0cmVhbS5hZGRFdmVudExpc3RlbmVyKCdhZGR0cmFjaycsIGZ1bmN0aW9uKHRlKSB7XG4gICAgICAgICAgICAgIHZhciByZWNlaXZlcjtcbiAgICAgICAgICAgICAgaWYgKHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuZ2V0UmVjZWl2ZXJzKSB7XG4gICAgICAgICAgICAgICAgcmVjZWl2ZXIgPSBwYy5nZXRSZWNlaXZlcnMoKS5maW5kKGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiByLnRyYWNrICYmIHIudHJhY2suaWQgPT09IHRlLnRyYWNrLmlkO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY2VpdmVyID0ge3RyYWNrOiB0ZS50cmFja307XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICB2YXIgZXZlbnQgPSBuZXcgRXZlbnQoJ3RyYWNrJyk7XG4gICAgICAgICAgICAgIGV2ZW50LnRyYWNrID0gdGUudHJhY2s7XG4gICAgICAgICAgICAgIGV2ZW50LnJlY2VpdmVyID0gcmVjZWl2ZXI7XG4gICAgICAgICAgICAgIGV2ZW50LnRyYW5zY2VpdmVyID0ge3JlY2VpdmVyOiByZWNlaXZlcn07XG4gICAgICAgICAgICAgIGV2ZW50LnN0cmVhbXMgPSBbZS5zdHJlYW1dO1xuICAgICAgICAgICAgICBwYy5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZS5zdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaChmdW5jdGlvbih0cmFjaykge1xuICAgICAgICAgICAgICB2YXIgcmVjZWl2ZXI7XG4gICAgICAgICAgICAgIGlmICh3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmdldFJlY2VpdmVycykge1xuICAgICAgICAgICAgICAgIHJlY2VpdmVyID0gcGMuZ2V0UmVjZWl2ZXJzKCkuZmluZChmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gci50cmFjayAmJiByLnRyYWNrLmlkID09PSB0cmFjay5pZDtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZWNlaXZlciA9IHt0cmFjazogdHJhY2t9O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHZhciBldmVudCA9IG5ldyBFdmVudCgndHJhY2snKTtcbiAgICAgICAgICAgICAgZXZlbnQudHJhY2sgPSB0cmFjaztcbiAgICAgICAgICAgICAgZXZlbnQucmVjZWl2ZXIgPSByZWNlaXZlcjtcbiAgICAgICAgICAgICAgZXZlbnQudHJhbnNjZWl2ZXIgPSB7cmVjZWl2ZXI6IHJlY2VpdmVyfTtcbiAgICAgICAgICAgICAgZXZlbnQuc3RyZWFtcyA9IFtlLnN0cmVhbV07XG4gICAgICAgICAgICAgIHBjLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfTtcbiAgICAgICAgICBwYy5hZGRFdmVudExpc3RlbmVyKCdhZGRzdHJlYW0nLCBwYy5fb250cmFja3BvbHkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvcmlnU2V0UmVtb3RlRGVzY3JpcHRpb24uYXBwbHkocGMsIGFyZ3VtZW50cyk7XG4gICAgICB9O1xuICAgIH0gZWxzZSBpZiAoISgnUlRDUnRwVHJhbnNjZWl2ZXInIGluIHdpbmRvdykpIHtcbiAgICAgIHV0aWxzLndyYXBQZWVyQ29ubmVjdGlvbkV2ZW50KHdpbmRvdywgJ3RyYWNrJywgZnVuY3Rpb24oZSkge1xuICAgICAgICBpZiAoIWUudHJhbnNjZWl2ZXIpIHtcbiAgICAgICAgICBlLnRyYW5zY2VpdmVyID0ge3JlY2VpdmVyOiBlLnJlY2VpdmVyfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSxcblxuICBzaGltR2V0U2VuZGVyc1dpdGhEdG1mOiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICAvLyBPdmVycmlkZXMgYWRkVHJhY2svcmVtb3ZlVHJhY2ssIGRlcGVuZHMgb24gc2hpbUFkZFRyYWNrUmVtb3ZlVHJhY2suXG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgPT09ICdvYmplY3QnICYmIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiAmJlxuICAgICAgICAhKCdnZXRTZW5kZXJzJyBpbiB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlKSAmJlxuICAgICAgICAnY3JlYXRlRFRNRlNlbmRlcicgaW4gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSkge1xuICAgICAgdmFyIHNoaW1TZW5kZXJXaXRoRHRtZiA9IGZ1bmN0aW9uKHBjLCB0cmFjaykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHRyYWNrOiB0cmFjayxcbiAgICAgICAgICBnZXQgZHRtZigpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9kdG1mID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgaWYgKHRyYWNrLmtpbmQgPT09ICdhdWRpbycpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9kdG1mID0gcGMuY3JlYXRlRFRNRlNlbmRlcih0cmFjayk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZHRtZiA9IG51bGw7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9kdG1mO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgX3BjOiBwY1xuICAgICAgICB9O1xuICAgICAgfTtcblxuICAgICAgLy8gYXVnbWVudCBhZGRUcmFjayB3aGVuIGdldFNlbmRlcnMgaXMgbm90IGF2YWlsYWJsZS5cbiAgICAgIGlmICghd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5nZXRTZW5kZXJzKSB7XG4gICAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuZ2V0U2VuZGVycyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHRoaXMuX3NlbmRlcnMgPSB0aGlzLl9zZW5kZXJzIHx8IFtdO1xuICAgICAgICAgIHJldHVybiB0aGlzLl9zZW5kZXJzLnNsaWNlKCk7IC8vIHJldHVybiBhIGNvcHkgb2YgdGhlIGludGVybmFsIHN0YXRlLlxuICAgICAgICB9O1xuICAgICAgICB2YXIgb3JpZ0FkZFRyYWNrID0gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5hZGRUcmFjaztcbiAgICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5hZGRUcmFjayA9IGZ1bmN0aW9uKHRyYWNrLCBzdHJlYW0pIHtcbiAgICAgICAgICB2YXIgcGMgPSB0aGlzO1xuICAgICAgICAgIHZhciBzZW5kZXIgPSBvcmlnQWRkVHJhY2suYXBwbHkocGMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgaWYgKCFzZW5kZXIpIHtcbiAgICAgICAgICAgIHNlbmRlciA9IHNoaW1TZW5kZXJXaXRoRHRtZihwYywgdHJhY2spO1xuICAgICAgICAgICAgcGMuX3NlbmRlcnMucHVzaChzZW5kZXIpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gc2VuZGVyO1xuICAgICAgICB9O1xuXG4gICAgICAgIHZhciBvcmlnUmVtb3ZlVHJhY2sgPSB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnJlbW92ZVRyYWNrO1xuICAgICAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnJlbW92ZVRyYWNrID0gZnVuY3Rpb24oc2VuZGVyKSB7XG4gICAgICAgICAgdmFyIHBjID0gdGhpcztcbiAgICAgICAgICBvcmlnUmVtb3ZlVHJhY2suYXBwbHkocGMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgdmFyIGlkeCA9IHBjLl9zZW5kZXJzLmluZGV4T2Yoc2VuZGVyKTtcbiAgICAgICAgICBpZiAoaWR4ICE9PSAtMSkge1xuICAgICAgICAgICAgcGMuX3NlbmRlcnMuc3BsaWNlKGlkeCwgMSk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgdmFyIG9yaWdBZGRTdHJlYW0gPSB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmFkZFN0cmVhbTtcbiAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuYWRkU3RyZWFtID0gZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICAgIHZhciBwYyA9IHRoaXM7XG4gICAgICAgIHBjLl9zZW5kZXJzID0gcGMuX3NlbmRlcnMgfHwgW107XG4gICAgICAgIG9yaWdBZGRTdHJlYW0uYXBwbHkocGMsIFtzdHJlYW1dKTtcbiAgICAgICAgc3RyZWFtLmdldFRyYWNrcygpLmZvckVhY2goZnVuY3Rpb24odHJhY2spIHtcbiAgICAgICAgICBwYy5fc2VuZGVycy5wdXNoKHNoaW1TZW5kZXJXaXRoRHRtZihwYywgdHJhY2spKTtcbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgb3JpZ1JlbW92ZVN0cmVhbSA9IHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUucmVtb3ZlU3RyZWFtO1xuICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5yZW1vdmVTdHJlYW0gPSBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgdmFyIHBjID0gdGhpcztcbiAgICAgICAgcGMuX3NlbmRlcnMgPSBwYy5fc2VuZGVycyB8fCBbXTtcbiAgICAgICAgb3JpZ1JlbW92ZVN0cmVhbS5hcHBseShwYywgW3N0cmVhbV0pO1xuXG4gICAgICAgIHN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKGZ1bmN0aW9uKHRyYWNrKSB7XG4gICAgICAgICAgdmFyIHNlbmRlciA9IHBjLl9zZW5kZXJzLmZpbmQoZnVuY3Rpb24ocykge1xuICAgICAgICAgICAgcmV0dXJuIHMudHJhY2sgPT09IHRyYWNrO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIGlmIChzZW5kZXIpIHtcbiAgICAgICAgICAgIHBjLl9zZW5kZXJzLnNwbGljZShwYy5fc2VuZGVycy5pbmRleE9mKHNlbmRlciksIDEpOyAvLyByZW1vdmUgc2VuZGVyXG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgfSBlbHNlIGlmICh0eXBlb2Ygd2luZG93ID09PSAnb2JqZWN0JyAmJiB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24gJiZcbiAgICAgICAgICAgICAgICdnZXRTZW5kZXJzJyBpbiB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlICYmXG4gICAgICAgICAgICAgICAnY3JlYXRlRFRNRlNlbmRlcicgaW4gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSAmJlxuICAgICAgICAgICAgICAgd2luZG93LlJUQ1J0cFNlbmRlciAmJlxuICAgICAgICAgICAgICAgISgnZHRtZicgaW4gd2luZG93LlJUQ1J0cFNlbmRlci5wcm90b3R5cGUpKSB7XG4gICAgICB2YXIgb3JpZ0dldFNlbmRlcnMgPSB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmdldFNlbmRlcnM7XG4gICAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmdldFNlbmRlcnMgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHBjID0gdGhpcztcbiAgICAgICAgdmFyIHNlbmRlcnMgPSBvcmlnR2V0U2VuZGVycy5hcHBseShwYywgW10pO1xuICAgICAgICBzZW5kZXJzLmZvckVhY2goZnVuY3Rpb24oc2VuZGVyKSB7XG4gICAgICAgICAgc2VuZGVyLl9wYyA9IHBjO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHNlbmRlcnM7XG4gICAgICB9O1xuXG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkod2luZG93LlJUQ1J0cFNlbmRlci5wcm90b3R5cGUsICdkdG1mJywge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGlmICh0aGlzLl9kdG1mID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnRyYWNrLmtpbmQgPT09ICdhdWRpbycpIHtcbiAgICAgICAgICAgICAgdGhpcy5fZHRtZiA9IHRoaXMuX3BjLmNyZWF0ZURUTUZTZW5kZXIodGhpcy50cmFjayk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aGlzLl9kdG1mID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHRoaXMuX2R0bWY7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfSxcblxuICBzaGltU291cmNlT2JqZWN0OiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICB2YXIgVVJMID0gd2luZG93ICYmIHdpbmRvdy5VUkw7XG5cbiAgICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGlmICh3aW5kb3cuSFRNTE1lZGlhRWxlbWVudCAmJlxuICAgICAgICAhKCdzcmNPYmplY3QnIGluIHdpbmRvdy5IVE1MTWVkaWFFbGVtZW50LnByb3RvdHlwZSkpIHtcbiAgICAgICAgLy8gU2hpbSB0aGUgc3JjT2JqZWN0IHByb3BlcnR5LCBvbmNlLCB3aGVuIEhUTUxNZWRpYUVsZW1lbnQgaXMgZm91bmQuXG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh3aW5kb3cuSFRNTE1lZGlhRWxlbWVudC5wcm90b3R5cGUsICdzcmNPYmplY3QnLCB7XG4gICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9zcmNPYmplY3Q7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBzZXQ6IGZ1bmN0aW9uKHN0cmVhbSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgLy8gVXNlIF9zcmNPYmplY3QgYXMgYSBwcml2YXRlIHByb3BlcnR5IGZvciB0aGlzIHNoaW1cbiAgICAgICAgICAgIHRoaXMuX3NyY09iamVjdCA9IHN0cmVhbTtcbiAgICAgICAgICAgIGlmICh0aGlzLnNyYykge1xuICAgICAgICAgICAgICBVUkwucmV2b2tlT2JqZWN0VVJMKHRoaXMuc3JjKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFzdHJlYW0pIHtcbiAgICAgICAgICAgICAgdGhpcy5zcmMgPSAnJztcbiAgICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc3JjID0gVVJMLmNyZWF0ZU9iamVjdFVSTChzdHJlYW0pO1xuICAgICAgICAgICAgLy8gV2UgbmVlZCB0byByZWNyZWF0ZSB0aGUgYmxvYiB1cmwgd2hlbiBhIHRyYWNrIGlzIGFkZGVkIG9yXG4gICAgICAgICAgICAvLyByZW1vdmVkLiBEb2luZyBpdCBtYW51YWxseSBzaW5jZSB3ZSB3YW50IHRvIGF2b2lkIGEgcmVjdXJzaW9uLlxuICAgICAgICAgICAgc3RyZWFtLmFkZEV2ZW50TGlzdGVuZXIoJ2FkZHRyYWNrJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgIGlmIChzZWxmLnNyYykge1xuICAgICAgICAgICAgICAgIFVSTC5yZXZva2VPYmplY3RVUkwoc2VsZi5zcmMpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHNlbGYuc3JjID0gVVJMLmNyZWF0ZU9iamVjdFVSTChzdHJlYW0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzdHJlYW0uYWRkRXZlbnRMaXN0ZW5lcigncmVtb3ZldHJhY2snLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgaWYgKHNlbGYuc3JjKSB7XG4gICAgICAgICAgICAgICAgVVJMLnJldm9rZU9iamVjdFVSTChzZWxmLnNyYyk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgc2VsZi5zcmMgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKHN0cmVhbSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfSxcblxuICBzaGltQWRkVHJhY2tSZW1vdmVUcmFja1dpdGhOYXRpdmU6IGZ1bmN0aW9uKHdpbmRvdykge1xuICAgIC8vIHNoaW0gYWRkVHJhY2svcmVtb3ZlVHJhY2sgd2l0aCBuYXRpdmUgdmFyaWFudHMgaW4gb3JkZXIgdG8gbWFrZVxuICAgIC8vIHRoZSBpbnRlcmFjdGlvbnMgd2l0aCBsZWdhY3kgZ2V0TG9jYWxTdHJlYW1zIGJlaGF2ZSBhcyBpbiBvdGhlciBicm93c2Vycy5cbiAgICAvLyBLZWVwcyBhIG1hcHBpbmcgc3RyZWFtLmlkID0+IFtzdHJlYW0sIHJ0cHNlbmRlcnMuLi5dXG4gICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5nZXRMb2NhbFN0cmVhbXMgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBwYyA9IHRoaXM7XG4gICAgICB0aGlzLl9zaGltbWVkTG9jYWxTdHJlYW1zID0gdGhpcy5fc2hpbW1lZExvY2FsU3RyZWFtcyB8fCB7fTtcbiAgICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLl9zaGltbWVkTG9jYWxTdHJlYW1zKS5tYXAoZnVuY3Rpb24oc3RyZWFtSWQpIHtcbiAgICAgICAgcmV0dXJuIHBjLl9zaGltbWVkTG9jYWxTdHJlYW1zW3N0cmVhbUlkXVswXTtcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICB2YXIgb3JpZ0FkZFRyYWNrID0gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5hZGRUcmFjaztcbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmFkZFRyYWNrID0gZnVuY3Rpb24odHJhY2ssIHN0cmVhbSkge1xuICAgICAgaWYgKCFzdHJlYW0pIHtcbiAgICAgICAgcmV0dXJuIG9yaWdBZGRUcmFjay5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgfVxuICAgICAgdGhpcy5fc2hpbW1lZExvY2FsU3RyZWFtcyA9IHRoaXMuX3NoaW1tZWRMb2NhbFN0cmVhbXMgfHwge307XG5cbiAgICAgIHZhciBzZW5kZXIgPSBvcmlnQWRkVHJhY2suYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIGlmICghdGhpcy5fc2hpbW1lZExvY2FsU3RyZWFtc1tzdHJlYW0uaWRdKSB7XG4gICAgICAgIHRoaXMuX3NoaW1tZWRMb2NhbFN0cmVhbXNbc3RyZWFtLmlkXSA9IFtzdHJlYW0sIHNlbmRlcl07XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuX3NoaW1tZWRMb2NhbFN0cmVhbXNbc3RyZWFtLmlkXS5pbmRleE9mKHNlbmRlcikgPT09IC0xKSB7XG4gICAgICAgIHRoaXMuX3NoaW1tZWRMb2NhbFN0cmVhbXNbc3RyZWFtLmlkXS5wdXNoKHNlbmRlcik7XG4gICAgICB9XG4gICAgICByZXR1cm4gc2VuZGVyO1xuICAgIH07XG5cbiAgICB2YXIgb3JpZ0FkZFN0cmVhbSA9IHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuYWRkU3RyZWFtO1xuICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuYWRkU3RyZWFtID0gZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICB2YXIgcGMgPSB0aGlzO1xuICAgICAgdGhpcy5fc2hpbW1lZExvY2FsU3RyZWFtcyA9IHRoaXMuX3NoaW1tZWRMb2NhbFN0cmVhbXMgfHwge307XG5cbiAgICAgIHN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKGZ1bmN0aW9uKHRyYWNrKSB7XG4gICAgICAgIHZhciBhbHJlYWR5RXhpc3RzID0gcGMuZ2V0U2VuZGVycygpLmZpbmQoZnVuY3Rpb24ocykge1xuICAgICAgICAgIHJldHVybiBzLnRyYWNrID09PSB0cmFjaztcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChhbHJlYWR5RXhpc3RzKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IERPTUV4Y2VwdGlvbignVHJhY2sgYWxyZWFkeSBleGlzdHMuJyxcbiAgICAgICAgICAgICAgJ0ludmFsaWRBY2Nlc3NFcnJvcicpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHZhciBleGlzdGluZ1NlbmRlcnMgPSBwYy5nZXRTZW5kZXJzKCk7XG4gICAgICBvcmlnQWRkU3RyZWFtLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICB2YXIgbmV3U2VuZGVycyA9IHBjLmdldFNlbmRlcnMoKS5maWx0ZXIoZnVuY3Rpb24obmV3U2VuZGVyKSB7XG4gICAgICAgIHJldHVybiBleGlzdGluZ1NlbmRlcnMuaW5kZXhPZihuZXdTZW5kZXIpID09PSAtMTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5fc2hpbW1lZExvY2FsU3RyZWFtc1tzdHJlYW0uaWRdID0gW3N0cmVhbV0uY29uY2F0KG5ld1NlbmRlcnMpO1xuICAgIH07XG5cbiAgICB2YXIgb3JpZ1JlbW92ZVN0cmVhbSA9IHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUucmVtb3ZlU3RyZWFtO1xuICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUucmVtb3ZlU3RyZWFtID0gZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICB0aGlzLl9zaGltbWVkTG9jYWxTdHJlYW1zID0gdGhpcy5fc2hpbW1lZExvY2FsU3RyZWFtcyB8fCB7fTtcbiAgICAgIGRlbGV0ZSB0aGlzLl9zaGltbWVkTG9jYWxTdHJlYW1zW3N0cmVhbS5pZF07XG4gICAgICByZXR1cm4gb3JpZ1JlbW92ZVN0cmVhbS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG5cbiAgICB2YXIgb3JpZ1JlbW92ZVRyYWNrID0gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5yZW1vdmVUcmFjaztcbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnJlbW92ZVRyYWNrID0gZnVuY3Rpb24oc2VuZGVyKSB7XG4gICAgICB2YXIgcGMgPSB0aGlzO1xuICAgICAgdGhpcy5fc2hpbW1lZExvY2FsU3RyZWFtcyA9IHRoaXMuX3NoaW1tZWRMb2NhbFN0cmVhbXMgfHwge307XG4gICAgICBpZiAoc2VuZGVyKSB7XG4gICAgICAgIE9iamVjdC5rZXlzKHRoaXMuX3NoaW1tZWRMb2NhbFN0cmVhbXMpLmZvckVhY2goZnVuY3Rpb24oc3RyZWFtSWQpIHtcbiAgICAgICAgICB2YXIgaWR4ID0gcGMuX3NoaW1tZWRMb2NhbFN0cmVhbXNbc3RyZWFtSWRdLmluZGV4T2Yoc2VuZGVyKTtcbiAgICAgICAgICBpZiAoaWR4ICE9PSAtMSkge1xuICAgICAgICAgICAgcGMuX3NoaW1tZWRMb2NhbFN0cmVhbXNbc3RyZWFtSWRdLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAocGMuX3NoaW1tZWRMb2NhbFN0cmVhbXNbc3RyZWFtSWRdLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgZGVsZXRlIHBjLl9zaGltbWVkTG9jYWxTdHJlYW1zW3N0cmVhbUlkXTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG9yaWdSZW1vdmVUcmFjay5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG4gIH0sXG5cbiAgc2hpbUFkZFRyYWNrUmVtb3ZlVHJhY2s6IGZ1bmN0aW9uKHdpbmRvdykge1xuICAgIHZhciBicm93c2VyRGV0YWlscyA9IHV0aWxzLmRldGVjdEJyb3dzZXIod2luZG93KTtcbiAgICAvLyBzaGltIGFkZFRyYWNrIGFuZCByZW1vdmVUcmFjay5cbiAgICBpZiAod2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5hZGRUcmFjayAmJlxuICAgICAgICBicm93c2VyRGV0YWlscy52ZXJzaW9uID49IDY1KSB7XG4gICAgICByZXR1cm4gdGhpcy5zaGltQWRkVHJhY2tSZW1vdmVUcmFja1dpdGhOYXRpdmUod2luZG93KTtcbiAgICB9XG5cbiAgICAvLyBhbHNvIHNoaW0gcGMuZ2V0TG9jYWxTdHJlYW1zIHdoZW4gYWRkVHJhY2sgaXMgc2hpbW1lZFxuICAgIC8vIHRvIHJldHVybiB0aGUgb3JpZ2luYWwgc3RyZWFtcy5cbiAgICB2YXIgb3JpZ0dldExvY2FsU3RyZWFtcyA9IHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGVcbiAgICAgICAgLmdldExvY2FsU3RyZWFtcztcbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmdldExvY2FsU3RyZWFtcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHBjID0gdGhpcztcbiAgICAgIHZhciBuYXRpdmVTdHJlYW1zID0gb3JpZ0dldExvY2FsU3RyZWFtcy5hcHBseSh0aGlzKTtcbiAgICAgIHBjLl9yZXZlcnNlU3RyZWFtcyA9IHBjLl9yZXZlcnNlU3RyZWFtcyB8fCB7fTtcbiAgICAgIHJldHVybiBuYXRpdmVTdHJlYW1zLm1hcChmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgcmV0dXJuIHBjLl9yZXZlcnNlU3RyZWFtc1tzdHJlYW0uaWRdO1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIHZhciBvcmlnQWRkU3RyZWFtID0gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5hZGRTdHJlYW07XG4gICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5hZGRTdHJlYW0gPSBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgIHZhciBwYyA9IHRoaXM7XG4gICAgICBwYy5fc3RyZWFtcyA9IHBjLl9zdHJlYW1zIHx8IHt9O1xuICAgICAgcGMuX3JldmVyc2VTdHJlYW1zID0gcGMuX3JldmVyc2VTdHJlYW1zIHx8IHt9O1xuXG4gICAgICBzdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaChmdW5jdGlvbih0cmFjaykge1xuICAgICAgICB2YXIgYWxyZWFkeUV4aXN0cyA9IHBjLmdldFNlbmRlcnMoKS5maW5kKGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgICByZXR1cm4gcy50cmFjayA9PT0gdHJhY2s7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoYWxyZWFkeUV4aXN0cykge1xuICAgICAgICAgIHRocm93IG5ldyBET01FeGNlcHRpb24oJ1RyYWNrIGFscmVhZHkgZXhpc3RzLicsXG4gICAgICAgICAgICAgICdJbnZhbGlkQWNjZXNzRXJyb3InKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICAvLyBBZGQgaWRlbnRpdHkgbWFwcGluZyBmb3IgY29uc2lzdGVuY3kgd2l0aCBhZGRUcmFjay5cbiAgICAgIC8vIFVubGVzcyB0aGlzIGlzIGJlaW5nIHVzZWQgd2l0aCBhIHN0cmVhbSBmcm9tIGFkZFRyYWNrLlxuICAgICAgaWYgKCFwYy5fcmV2ZXJzZVN0cmVhbXNbc3RyZWFtLmlkXSkge1xuICAgICAgICB2YXIgbmV3U3RyZWFtID0gbmV3IHdpbmRvdy5NZWRpYVN0cmVhbShzdHJlYW0uZ2V0VHJhY2tzKCkpO1xuICAgICAgICBwYy5fc3RyZWFtc1tzdHJlYW0uaWRdID0gbmV3U3RyZWFtO1xuICAgICAgICBwYy5fcmV2ZXJzZVN0cmVhbXNbbmV3U3RyZWFtLmlkXSA9IHN0cmVhbTtcbiAgICAgICAgc3RyZWFtID0gbmV3U3RyZWFtO1xuICAgICAgfVxuICAgICAgb3JpZ0FkZFN0cmVhbS5hcHBseShwYywgW3N0cmVhbV0pO1xuICAgIH07XG5cbiAgICB2YXIgb3JpZ1JlbW92ZVN0cmVhbSA9IHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUucmVtb3ZlU3RyZWFtO1xuICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUucmVtb3ZlU3RyZWFtID0gZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICB2YXIgcGMgPSB0aGlzO1xuICAgICAgcGMuX3N0cmVhbXMgPSBwYy5fc3RyZWFtcyB8fCB7fTtcbiAgICAgIHBjLl9yZXZlcnNlU3RyZWFtcyA9IHBjLl9yZXZlcnNlU3RyZWFtcyB8fCB7fTtcblxuICAgICAgb3JpZ1JlbW92ZVN0cmVhbS5hcHBseShwYywgWyhwYy5fc3RyZWFtc1tzdHJlYW0uaWRdIHx8IHN0cmVhbSldKTtcbiAgICAgIGRlbGV0ZSBwYy5fcmV2ZXJzZVN0cmVhbXNbKHBjLl9zdHJlYW1zW3N0cmVhbS5pZF0gP1xuICAgICAgICAgIHBjLl9zdHJlYW1zW3N0cmVhbS5pZF0uaWQgOiBzdHJlYW0uaWQpXTtcbiAgICAgIGRlbGV0ZSBwYy5fc3RyZWFtc1tzdHJlYW0uaWRdO1xuICAgIH07XG5cbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmFkZFRyYWNrID0gZnVuY3Rpb24odHJhY2ssIHN0cmVhbSkge1xuICAgICAgdmFyIHBjID0gdGhpcztcbiAgICAgIGlmIChwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgdGhyb3cgbmV3IERPTUV4Y2VwdGlvbihcbiAgICAgICAgICAnVGhlIFJUQ1BlZXJDb25uZWN0aW9uXFwncyBzaWduYWxpbmdTdGF0ZSBpcyBcXCdjbG9zZWRcXCcuJyxcbiAgICAgICAgICAnSW52YWxpZFN0YXRlRXJyb3InKTtcbiAgICAgIH1cbiAgICAgIHZhciBzdHJlYW1zID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgaWYgKHN0cmVhbXMubGVuZ3RoICE9PSAxIHx8XG4gICAgICAgICAgIXN0cmVhbXNbMF0uZ2V0VHJhY2tzKCkuZmluZChmdW5jdGlvbih0KSB7XG4gICAgICAgICAgICByZXR1cm4gdCA9PT0gdHJhY2s7XG4gICAgICAgICAgfSkpIHtcbiAgICAgICAgLy8gdGhpcyBpcyBub3QgZnVsbHkgY29ycmVjdCBidXQgYWxsIHdlIGNhbiBtYW5hZ2Ugd2l0aG91dFxuICAgICAgICAvLyBbW2Fzc29jaWF0ZWQgTWVkaWFTdHJlYW1zXV0gaW50ZXJuYWwgc2xvdC5cbiAgICAgICAgdGhyb3cgbmV3IERPTUV4Y2VwdGlvbihcbiAgICAgICAgICAnVGhlIGFkYXB0ZXIuanMgYWRkVHJhY2sgcG9seWZpbGwgb25seSBzdXBwb3J0cyBhIHNpbmdsZSAnICtcbiAgICAgICAgICAnIHN0cmVhbSB3aGljaCBpcyBhc3NvY2lhdGVkIHdpdGggdGhlIHNwZWNpZmllZCB0cmFjay4nLFxuICAgICAgICAgICdOb3RTdXBwb3J0ZWRFcnJvcicpO1xuICAgICAgfVxuXG4gICAgICB2YXIgYWxyZWFkeUV4aXN0cyA9IHBjLmdldFNlbmRlcnMoKS5maW5kKGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgcmV0dXJuIHMudHJhY2sgPT09IHRyYWNrO1xuICAgICAgfSk7XG4gICAgICBpZiAoYWxyZWFkeUV4aXN0cykge1xuICAgICAgICB0aHJvdyBuZXcgRE9NRXhjZXB0aW9uKCdUcmFjayBhbHJlYWR5IGV4aXN0cy4nLFxuICAgICAgICAgICAgJ0ludmFsaWRBY2Nlc3NFcnJvcicpO1xuICAgICAgfVxuXG4gICAgICBwYy5fc3RyZWFtcyA9IHBjLl9zdHJlYW1zIHx8IHt9O1xuICAgICAgcGMuX3JldmVyc2VTdHJlYW1zID0gcGMuX3JldmVyc2VTdHJlYW1zIHx8IHt9O1xuICAgICAgdmFyIG9sZFN0cmVhbSA9IHBjLl9zdHJlYW1zW3N0cmVhbS5pZF07XG4gICAgICBpZiAob2xkU3RyZWFtKSB7XG4gICAgICAgIC8vIHRoaXMgaXMgdXNpbmcgb2RkIENocm9tZSBiZWhhdmlvdXIsIHVzZSB3aXRoIGNhdXRpb246XG4gICAgICAgIC8vIGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC93ZWJydGMvaXNzdWVzL2RldGFpbD9pZD03ODE1XG4gICAgICAgIC8vIE5vdGU6IHdlIHJlbHkgb24gdGhlIGhpZ2gtbGV2ZWwgYWRkVHJhY2svZHRtZiBzaGltIHRvXG4gICAgICAgIC8vIGNyZWF0ZSB0aGUgc2VuZGVyIHdpdGggYSBkdG1mIHNlbmRlci5cbiAgICAgICAgb2xkU3RyZWFtLmFkZFRyYWNrKHRyYWNrKTtcblxuICAgICAgICAvLyBUcmlnZ2VyIE9OTiBhc3luYy5cbiAgICAgICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbihmdW5jdGlvbigpIHtcbiAgICAgICAgICBwYy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudCgnbmVnb3RpYXRpb25uZWVkZWQnKSk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIG5ld1N0cmVhbSA9IG5ldyB3aW5kb3cuTWVkaWFTdHJlYW0oW3RyYWNrXSk7XG4gICAgICAgIHBjLl9zdHJlYW1zW3N0cmVhbS5pZF0gPSBuZXdTdHJlYW07XG4gICAgICAgIHBjLl9yZXZlcnNlU3RyZWFtc1tuZXdTdHJlYW0uaWRdID0gc3RyZWFtO1xuICAgICAgICBwYy5hZGRTdHJlYW0obmV3U3RyZWFtKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBwYy5nZXRTZW5kZXJzKCkuZmluZChmdW5jdGlvbihzKSB7XG4gICAgICAgIHJldHVybiBzLnRyYWNrID09PSB0cmFjaztcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvLyByZXBsYWNlIHRoZSBpbnRlcm5hbCBzdHJlYW0gaWQgd2l0aCB0aGUgZXh0ZXJuYWwgb25lIGFuZFxuICAgIC8vIHZpY2UgdmVyc2EuXG4gICAgZnVuY3Rpb24gcmVwbGFjZUludGVybmFsU3RyZWFtSWQocGMsIGRlc2NyaXB0aW9uKSB7XG4gICAgICB2YXIgc2RwID0gZGVzY3JpcHRpb24uc2RwO1xuICAgICAgT2JqZWN0LmtleXMocGMuX3JldmVyc2VTdHJlYW1zIHx8IFtdKS5mb3JFYWNoKGZ1bmN0aW9uKGludGVybmFsSWQpIHtcbiAgICAgICAgdmFyIGV4dGVybmFsU3RyZWFtID0gcGMuX3JldmVyc2VTdHJlYW1zW2ludGVybmFsSWRdO1xuICAgICAgICB2YXIgaW50ZXJuYWxTdHJlYW0gPSBwYy5fc3RyZWFtc1tleHRlcm5hbFN0cmVhbS5pZF07XG4gICAgICAgIHNkcCA9IHNkcC5yZXBsYWNlKG5ldyBSZWdFeHAoaW50ZXJuYWxTdHJlYW0uaWQsICdnJyksXG4gICAgICAgICAgICBleHRlcm5hbFN0cmVhbS5pZCk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBuZXcgUlRDU2Vzc2lvbkRlc2NyaXB0aW9uKHtcbiAgICAgICAgdHlwZTogZGVzY3JpcHRpb24udHlwZSxcbiAgICAgICAgc2RwOiBzZHBcbiAgICAgIH0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZXBsYWNlRXh0ZXJuYWxTdHJlYW1JZChwYywgZGVzY3JpcHRpb24pIHtcbiAgICAgIHZhciBzZHAgPSBkZXNjcmlwdGlvbi5zZHA7XG4gICAgICBPYmplY3Qua2V5cyhwYy5fcmV2ZXJzZVN0cmVhbXMgfHwgW10pLmZvckVhY2goZnVuY3Rpb24oaW50ZXJuYWxJZCkge1xuICAgICAgICB2YXIgZXh0ZXJuYWxTdHJlYW0gPSBwYy5fcmV2ZXJzZVN0cmVhbXNbaW50ZXJuYWxJZF07XG4gICAgICAgIHZhciBpbnRlcm5hbFN0cmVhbSA9IHBjLl9zdHJlYW1zW2V4dGVybmFsU3RyZWFtLmlkXTtcbiAgICAgICAgc2RwID0gc2RwLnJlcGxhY2UobmV3IFJlZ0V4cChleHRlcm5hbFN0cmVhbS5pZCwgJ2cnKSxcbiAgICAgICAgICAgIGludGVybmFsU3RyZWFtLmlkKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIG5ldyBSVENTZXNzaW9uRGVzY3JpcHRpb24oe1xuICAgICAgICB0eXBlOiBkZXNjcmlwdGlvbi50eXBlLFxuICAgICAgICBzZHA6IHNkcFxuICAgICAgfSk7XG4gICAgfVxuICAgIFsnY3JlYXRlT2ZmZXInLCAnY3JlYXRlQW5zd2VyJ10uZm9yRWFjaChmdW5jdGlvbihtZXRob2QpIHtcbiAgICAgIHZhciBuYXRpdmVNZXRob2QgPSB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlW21ldGhvZF07XG4gICAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlW21ldGhvZF0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHBjID0gdGhpcztcbiAgICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgIHZhciBpc0xlZ2FjeUNhbGwgPSBhcmd1bWVudHMubGVuZ3RoICYmXG4gICAgICAgICAgICB0eXBlb2YgYXJndW1lbnRzWzBdID09PSAnZnVuY3Rpb24nO1xuICAgICAgICBpZiAoaXNMZWdhY3lDYWxsKSB7XG4gICAgICAgICAgcmV0dXJuIG5hdGl2ZU1ldGhvZC5hcHBseShwYywgW1xuICAgICAgICAgICAgZnVuY3Rpb24oZGVzY3JpcHRpb24pIHtcbiAgICAgICAgICAgICAgdmFyIGRlc2MgPSByZXBsYWNlSW50ZXJuYWxTdHJlYW1JZChwYywgZGVzY3JpcHRpb24pO1xuICAgICAgICAgICAgICBhcmdzWzBdLmFwcGx5KG51bGwsIFtkZXNjXSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZnVuY3Rpb24oZXJyKSB7XG4gICAgICAgICAgICAgIGlmIChhcmdzWzFdKSB7XG4gICAgICAgICAgICAgICAgYXJnc1sxXS5hcHBseShudWxsLCBlcnIpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LCBhcmd1bWVudHNbMl1cbiAgICAgICAgICBdKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmF0aXZlTWV0aG9kLmFwcGx5KHBjLCBhcmd1bWVudHMpXG4gICAgICAgIC50aGVuKGZ1bmN0aW9uKGRlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgcmV0dXJuIHJlcGxhY2VJbnRlcm5hbFN0cmVhbUlkKHBjLCBkZXNjcmlwdGlvbik7XG4gICAgICAgIH0pO1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIHZhciBvcmlnU2V0TG9jYWxEZXNjcmlwdGlvbiA9XG4gICAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuc2V0TG9jYWxEZXNjcmlwdGlvbjtcbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnNldExvY2FsRGVzY3JpcHRpb24gPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBwYyA9IHRoaXM7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGggfHwgIWFyZ3VtZW50c1swXS50eXBlKSB7XG4gICAgICAgIHJldHVybiBvcmlnU2V0TG9jYWxEZXNjcmlwdGlvbi5hcHBseShwYywgYXJndW1lbnRzKTtcbiAgICAgIH1cbiAgICAgIGFyZ3VtZW50c1swXSA9IHJlcGxhY2VFeHRlcm5hbFN0cmVhbUlkKHBjLCBhcmd1bWVudHNbMF0pO1xuICAgICAgcmV0dXJuIG9yaWdTZXRMb2NhbERlc2NyaXB0aW9uLmFwcGx5KHBjLCBhcmd1bWVudHMpO1xuICAgIH07XG5cbiAgICAvLyBUT0RPOiBtYW5nbGUgZ2V0U3RhdHM6IGh0dHBzOi8vdzNjLmdpdGh1Yi5pby93ZWJydGMtc3RhdHMvI2RvbS1ydGNtZWRpYXN0cmVhbXN0YXRzLXN0cmVhbWlkZW50aWZpZXJcblxuICAgIHZhciBvcmlnTG9jYWxEZXNjcmlwdGlvbiA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoXG4gICAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUsICdsb2NhbERlc2NyaXB0aW9uJyk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUsXG4gICAgICAgICdsb2NhbERlc2NyaXB0aW9uJywge1xuICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgcGMgPSB0aGlzO1xuICAgICAgICAgICAgdmFyIGRlc2NyaXB0aW9uID0gb3JpZ0xvY2FsRGVzY3JpcHRpb24uZ2V0LmFwcGx5KHRoaXMpO1xuICAgICAgICAgICAgaWYgKGRlc2NyaXB0aW9uLnR5cGUgPT09ICcnKSB7XG4gICAgICAgICAgICAgIHJldHVybiBkZXNjcmlwdGlvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXBsYWNlSW50ZXJuYWxTdHJlYW1JZChwYywgZGVzY3JpcHRpb24pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnJlbW92ZVRyYWNrID0gZnVuY3Rpb24oc2VuZGVyKSB7XG4gICAgICB2YXIgcGMgPSB0aGlzO1xuICAgICAgaWYgKHBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgICB0aHJvdyBuZXcgRE9NRXhjZXB0aW9uKFxuICAgICAgICAgICdUaGUgUlRDUGVlckNvbm5lY3Rpb25cXCdzIHNpZ25hbGluZ1N0YXRlIGlzIFxcJ2Nsb3NlZFxcJy4nLFxuICAgICAgICAgICdJbnZhbGlkU3RhdGVFcnJvcicpO1xuICAgICAgfVxuICAgICAgLy8gV2UgY2FuIG5vdCB5ZXQgY2hlY2sgZm9yIHNlbmRlciBpbnN0YW5jZW9mIFJUQ1J0cFNlbmRlclxuICAgICAgLy8gc2luY2Ugd2Ugc2hpbSBSVFBTZW5kZXIuIFNvIHdlIGNoZWNrIGlmIHNlbmRlci5fcGMgaXMgc2V0LlxuICAgICAgaWYgKCFzZW5kZXIuX3BjKSB7XG4gICAgICAgIHRocm93IG5ldyBET01FeGNlcHRpb24oJ0FyZ3VtZW50IDEgb2YgUlRDUGVlckNvbm5lY3Rpb24ucmVtb3ZlVHJhY2sgJyArXG4gICAgICAgICAgICAnZG9lcyBub3QgaW1wbGVtZW50IGludGVyZmFjZSBSVENSdHBTZW5kZXIuJywgJ1R5cGVFcnJvcicpO1xuICAgICAgfVxuICAgICAgdmFyIGlzTG9jYWwgPSBzZW5kZXIuX3BjID09PSBwYztcbiAgICAgIGlmICghaXNMb2NhbCkge1xuICAgICAgICB0aHJvdyBuZXcgRE9NRXhjZXB0aW9uKCdTZW5kZXIgd2FzIG5vdCBjcmVhdGVkIGJ5IHRoaXMgY29ubmVjdGlvbi4nLFxuICAgICAgICAgICAgJ0ludmFsaWRBY2Nlc3NFcnJvcicpO1xuICAgICAgfVxuXG4gICAgICAvLyBTZWFyY2ggZm9yIHRoZSBuYXRpdmUgc3RyZWFtIHRoZSBzZW5kZXJzIHRyYWNrIGJlbG9uZ3MgdG8uXG4gICAgICBwYy5fc3RyZWFtcyA9IHBjLl9zdHJlYW1zIHx8IHt9O1xuICAgICAgdmFyIHN0cmVhbTtcbiAgICAgIE9iamVjdC5rZXlzKHBjLl9zdHJlYW1zKS5mb3JFYWNoKGZ1bmN0aW9uKHN0cmVhbWlkKSB7XG4gICAgICAgIHZhciBoYXNUcmFjayA9IHBjLl9zdHJlYW1zW3N0cmVhbWlkXS5nZXRUcmFja3MoKS5maW5kKGZ1bmN0aW9uKHRyYWNrKSB7XG4gICAgICAgICAgcmV0dXJuIHNlbmRlci50cmFjayA9PT0gdHJhY2s7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoaGFzVHJhY2spIHtcbiAgICAgICAgICBzdHJlYW0gPSBwYy5fc3RyZWFtc1tzdHJlYW1pZF07XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBpZiAoc3RyZWFtKSB7XG4gICAgICAgIGlmIChzdHJlYW0uZ2V0VHJhY2tzKCkubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgLy8gaWYgdGhpcyBpcyB0aGUgbGFzdCB0cmFjayBvZiB0aGUgc3RyZWFtLCByZW1vdmUgdGhlIHN0cmVhbS4gVGhpc1xuICAgICAgICAgIC8vIHRha2VzIGNhcmUgb2YgYW55IHNoaW1tZWQgX3NlbmRlcnMuXG4gICAgICAgICAgcGMucmVtb3ZlU3RyZWFtKHBjLl9yZXZlcnNlU3RyZWFtc1tzdHJlYW0uaWRdKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyByZWx5aW5nIG9uIHRoZSBzYW1lIG9kZCBjaHJvbWUgYmVoYXZpb3VyIGFzIGFib3ZlLlxuICAgICAgICAgIHN0cmVhbS5yZW1vdmVUcmFjayhzZW5kZXIudHJhY2spO1xuICAgICAgICB9XG4gICAgICAgIHBjLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KCduZWdvdGlhdGlvbm5lZWRlZCcpKTtcbiAgICAgIH1cbiAgICB9O1xuICB9LFxuXG4gIHNoaW1QZWVyQ29ubmVjdGlvbjogZnVuY3Rpb24od2luZG93KSB7XG4gICAgdmFyIGJyb3dzZXJEZXRhaWxzID0gdXRpbHMuZGV0ZWN0QnJvd3Nlcih3aW5kb3cpO1xuXG4gICAgLy8gVGhlIFJUQ1BlZXJDb25uZWN0aW9uIG9iamVjdC5cbiAgICBpZiAoIXdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiAmJiB3aW5kb3cud2Via2l0UlRDUGVlckNvbm5lY3Rpb24pIHtcbiAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiA9IGZ1bmN0aW9uKHBjQ29uZmlnLCBwY0NvbnN0cmFpbnRzKSB7XG4gICAgICAgIC8vIFRyYW5zbGF0ZSBpY2VUcmFuc3BvcnRQb2xpY3kgdG8gaWNlVHJhbnNwb3J0cyxcbiAgICAgICAgLy8gc2VlIGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3Avd2VicnRjL2lzc3Vlcy9kZXRhaWw/aWQ9NDg2OVxuICAgICAgICAvLyB0aGlzIHdhcyBmaXhlZCBpbiBNNTYgYWxvbmcgd2l0aCB1bnByZWZpeGluZyBSVENQZWVyQ29ubmVjdGlvbi5cbiAgICAgICAgbG9nZ2luZygnUGVlckNvbm5lY3Rpb24nKTtcbiAgICAgICAgaWYgKHBjQ29uZmlnICYmIHBjQ29uZmlnLmljZVRyYW5zcG9ydFBvbGljeSkge1xuICAgICAgICAgIHBjQ29uZmlnLmljZVRyYW5zcG9ydHMgPSBwY0NvbmZpZy5pY2VUcmFuc3BvcnRQb2xpY3k7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbmV3IHdpbmRvdy53ZWJraXRSVENQZWVyQ29ubmVjdGlvbihwY0NvbmZpZywgcGNDb25zdHJhaW50cyk7XG4gICAgICB9O1xuICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSA9XG4gICAgICAgICAgd2luZG93LndlYmtpdFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZTtcbiAgICAgIC8vIHdyYXAgc3RhdGljIG1ldGhvZHMuIEN1cnJlbnRseSBqdXN0IGdlbmVyYXRlQ2VydGlmaWNhdGUuXG4gICAgICBpZiAod2luZG93LndlYmtpdFJUQ1BlZXJDb25uZWN0aW9uLmdlbmVyYXRlQ2VydGlmaWNhdGUpIHtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiwgJ2dlbmVyYXRlQ2VydGlmaWNhdGUnLCB7XG4gICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiB3aW5kb3cud2Via2l0UlRDUGVlckNvbm5lY3Rpb24uZ2VuZXJhdGVDZXJ0aWZpY2F0ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBtaWdyYXRlIGZyb20gbm9uLXNwZWMgUlRDSWNlU2VydmVyLnVybCB0byBSVENJY2VTZXJ2ZXIudXJsc1xuICAgICAgdmFyIE9yaWdQZWVyQ29ubmVjdGlvbiA9IHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbjtcbiAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiA9IGZ1bmN0aW9uKHBjQ29uZmlnLCBwY0NvbnN0cmFpbnRzKSB7XG4gICAgICAgIGlmIChwY0NvbmZpZyAmJiBwY0NvbmZpZy5pY2VTZXJ2ZXJzKSB7XG4gICAgICAgICAgdmFyIG5ld0ljZVNlcnZlcnMgPSBbXTtcbiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBjQ29uZmlnLmljZVNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBzZXJ2ZXIgPSBwY0NvbmZpZy5pY2VTZXJ2ZXJzW2ldO1xuICAgICAgICAgICAgaWYgKCFzZXJ2ZXIuaGFzT3duUHJvcGVydHkoJ3VybHMnKSAmJlxuICAgICAgICAgICAgICAgIHNlcnZlci5oYXNPd25Qcm9wZXJ0eSgndXJsJykpIHtcbiAgICAgICAgICAgICAgdXRpbHMuZGVwcmVjYXRlZCgnUlRDSWNlU2VydmVyLnVybCcsICdSVENJY2VTZXJ2ZXIudXJscycpO1xuICAgICAgICAgICAgICBzZXJ2ZXIgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KHNlcnZlcikpO1xuICAgICAgICAgICAgICBzZXJ2ZXIudXJscyA9IHNlcnZlci51cmw7XG4gICAgICAgICAgICAgIG5ld0ljZVNlcnZlcnMucHVzaChzZXJ2ZXIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgbmV3SWNlU2VydmVycy5wdXNoKHBjQ29uZmlnLmljZVNlcnZlcnNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBwY0NvbmZpZy5pY2VTZXJ2ZXJzID0gbmV3SWNlU2VydmVycztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IE9yaWdQZWVyQ29ubmVjdGlvbihwY0NvbmZpZywgcGNDb25zdHJhaW50cyk7XG4gICAgICB9O1xuICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSA9IE9yaWdQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGU7XG4gICAgICAvLyB3cmFwIHN0YXRpYyBtZXRob2RzLiBDdXJyZW50bHkganVzdCBnZW5lcmF0ZUNlcnRpZmljYXRlLlxuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiwgJ2dlbmVyYXRlQ2VydGlmaWNhdGUnLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIE9yaWdQZWVyQ29ubmVjdGlvbi5nZW5lcmF0ZUNlcnRpZmljYXRlO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgb3JpZ0dldFN0YXRzID0gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5nZXRTdGF0cztcbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmdldFN0YXRzID0gZnVuY3Rpb24oc2VsZWN0b3IsXG4gICAgICAgIHN1Y2Nlc3NDYWxsYmFjaywgZXJyb3JDYWxsYmFjaykge1xuICAgICAgdmFyIHBjID0gdGhpcztcbiAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzO1xuXG4gICAgICAvLyBJZiBzZWxlY3RvciBpcyBhIGZ1bmN0aW9uIHRoZW4gd2UgYXJlIGluIHRoZSBvbGQgc3R5bGUgc3RhdHMgc28ganVzdFxuICAgICAgLy8gcGFzcyBiYWNrIHRoZSBvcmlnaW5hbCBnZXRTdGF0cyBmb3JtYXQgdG8gYXZvaWQgYnJlYWtpbmcgb2xkIHVzZXJzLlxuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIHR5cGVvZiBzZWxlY3RvciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gb3JpZ0dldFN0YXRzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICB9XG5cbiAgICAgIC8vIFdoZW4gc3BlYy1zdHlsZSBnZXRTdGF0cyBpcyBzdXBwb3J0ZWQsIHJldHVybiB0aG9zZSB3aGVuIGNhbGxlZCB3aXRoXG4gICAgICAvLyBlaXRoZXIgbm8gYXJndW1lbnRzIG9yIHRoZSBzZWxlY3RvciBhcmd1bWVudCBpcyBudWxsLlxuICAgICAgaWYgKG9yaWdHZXRTdGF0cy5sZW5ndGggPT09IDAgJiYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDAgfHxcbiAgICAgICAgICB0eXBlb2YgYXJndW1lbnRzWzBdICE9PSAnZnVuY3Rpb24nKSkge1xuICAgICAgICByZXR1cm4gb3JpZ0dldFN0YXRzLmFwcGx5KHRoaXMsIFtdKTtcbiAgICAgIH1cblxuICAgICAgdmFyIGZpeENocm9tZVN0YXRzXyA9IGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG4gICAgICAgIHZhciBzdGFuZGFyZFJlcG9ydCA9IHt9O1xuICAgICAgICB2YXIgcmVwb3J0cyA9IHJlc3BvbnNlLnJlc3VsdCgpO1xuICAgICAgICByZXBvcnRzLmZvckVhY2goZnVuY3Rpb24ocmVwb3J0KSB7XG4gICAgICAgICAgdmFyIHN0YW5kYXJkU3RhdHMgPSB7XG4gICAgICAgICAgICBpZDogcmVwb3J0LmlkLFxuICAgICAgICAgICAgdGltZXN0YW1wOiByZXBvcnQudGltZXN0YW1wLFxuICAgICAgICAgICAgdHlwZToge1xuICAgICAgICAgICAgICBsb2NhbGNhbmRpZGF0ZTogJ2xvY2FsLWNhbmRpZGF0ZScsXG4gICAgICAgICAgICAgIHJlbW90ZWNhbmRpZGF0ZTogJ3JlbW90ZS1jYW5kaWRhdGUnXG4gICAgICAgICAgICB9W3JlcG9ydC50eXBlXSB8fCByZXBvcnQudHlwZVxuICAgICAgICAgIH07XG4gICAgICAgICAgcmVwb3J0Lm5hbWVzKCkuZm9yRWFjaChmdW5jdGlvbihuYW1lKSB7XG4gICAgICAgICAgICBzdGFuZGFyZFN0YXRzW25hbWVdID0gcmVwb3J0LnN0YXQobmFtZSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgc3RhbmRhcmRSZXBvcnRbc3RhbmRhcmRTdGF0cy5pZF0gPSBzdGFuZGFyZFN0YXRzO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gc3RhbmRhcmRSZXBvcnQ7XG4gICAgICB9O1xuXG4gICAgICAvLyBzaGltIGdldFN0YXRzIHdpdGggbWFwbGlrZSBzdXBwb3J0XG4gICAgICB2YXIgbWFrZU1hcFN0YXRzID0gZnVuY3Rpb24oc3RhdHMpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBNYXAoT2JqZWN0LmtleXMoc3RhdHMpLm1hcChmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgICByZXR1cm4gW2tleSwgc3RhdHNba2V5XV07XG4gICAgICAgIH0pKTtcbiAgICAgIH07XG5cbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID49IDIpIHtcbiAgICAgICAgdmFyIHN1Y2Nlc3NDYWxsYmFja1dyYXBwZXJfID0gZnVuY3Rpb24ocmVzcG9uc2UpIHtcbiAgICAgICAgICBhcmdzWzFdKG1ha2VNYXBTdGF0cyhmaXhDaHJvbWVTdGF0c18ocmVzcG9uc2UpKSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIG9yaWdHZXRTdGF0cy5hcHBseSh0aGlzLCBbc3VjY2Vzc0NhbGxiYWNrV3JhcHBlcl8sXG4gICAgICAgICAgYXJndW1lbnRzWzBdXSk7XG4gICAgICB9XG5cbiAgICAgIC8vIHByb21pc2Utc3VwcG9ydFxuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICBvcmlnR2V0U3RhdHMuYXBwbHkocGMsIFtcbiAgICAgICAgICBmdW5jdGlvbihyZXNwb25zZSkge1xuICAgICAgICAgICAgcmVzb2x2ZShtYWtlTWFwU3RhdHMoZml4Q2hyb21lU3RhdHNfKHJlc3BvbnNlKSkpO1xuICAgICAgICAgIH0sIHJlamVjdF0pO1xuICAgICAgfSkudGhlbihzdWNjZXNzQ2FsbGJhY2ssIGVycm9yQ2FsbGJhY2spO1xuICAgIH07XG5cbiAgICAvLyBhZGQgcHJvbWlzZSBzdXBwb3J0IC0tIG5hdGl2ZWx5IGF2YWlsYWJsZSBpbiBDaHJvbWUgNTFcbiAgICBpZiAoYnJvd3NlckRldGFpbHMudmVyc2lvbiA8IDUxKSB7XG4gICAgICBbJ3NldExvY2FsRGVzY3JpcHRpb24nLCAnc2V0UmVtb3RlRGVzY3JpcHRpb24nLCAnYWRkSWNlQ2FuZGlkYXRlJ11cbiAgICAgICAgICAuZm9yRWFjaChmdW5jdGlvbihtZXRob2QpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVNZXRob2QgPSB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlW21ldGhvZF07XG4gICAgICAgICAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlW21ldGhvZF0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgICAgICAgIHZhciBwYyA9IHRoaXM7XG4gICAgICAgICAgICAgIHZhciBwcm9taXNlID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgICAgICAgICAgbmF0aXZlTWV0aG9kLmFwcGx5KHBjLCBbYXJnc1swXSwgcmVzb2x2ZSwgcmVqZWN0XSk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICBpZiAoYXJncy5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmV0dXJuIHByb21pc2UudGhlbihmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBhcmdzWzFdLmFwcGx5KG51bGwsIFtdKTtcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgZnVuY3Rpb24oZXJyKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFyZ3MubGVuZ3RoID49IDMpIHtcbiAgICAgICAgICAgICAgICAgIGFyZ3NbMl0uYXBwbHkobnVsbCwgW2Vycl0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIHByb21pc2Ugc3VwcG9ydCBmb3IgY3JlYXRlT2ZmZXIgYW5kIGNyZWF0ZUFuc3dlci4gQXZhaWxhYmxlICh3aXRob3V0XG4gICAgLy8gYnVncykgc2luY2UgTTUyOiBjcmJ1Zy82MTkyODlcbiAgICBpZiAoYnJvd3NlckRldGFpbHMudmVyc2lvbiA8IDUyKSB7XG4gICAgICBbJ2NyZWF0ZU9mZmVyJywgJ2NyZWF0ZUFuc3dlciddLmZvckVhY2goZnVuY3Rpb24obWV0aG9kKSB7XG4gICAgICAgIHZhciBuYXRpdmVNZXRob2QgPSB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlW21ldGhvZF07XG4gICAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGVbbWV0aG9kXSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHZhciBwYyA9IHRoaXM7XG4gICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAxIHx8IChhcmd1bWVudHMubGVuZ3RoID09PSAxICYmXG4gICAgICAgICAgICAgIHR5cGVvZiBhcmd1bWVudHNbMF0gPT09ICdvYmplY3QnKSkge1xuICAgICAgICAgICAgdmFyIG9wdHMgPSBhcmd1bWVudHMubGVuZ3RoID09PSAxID8gYXJndW1lbnRzWzBdIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAgICAgICBuYXRpdmVNZXRob2QuYXBwbHkocGMsIFtyZXNvbHZlLCByZWplY3QsIG9wdHNdKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbmF0aXZlTWV0aG9kLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH07XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBzaGltIGltcGxpY2l0IGNyZWF0aW9uIG9mIFJUQ1Nlc3Npb25EZXNjcmlwdGlvbi9SVENJY2VDYW5kaWRhdGVcbiAgICBbJ3NldExvY2FsRGVzY3JpcHRpb24nLCAnc2V0UmVtb3RlRGVzY3JpcHRpb24nLCAnYWRkSWNlQ2FuZGlkYXRlJ11cbiAgICAgICAgLmZvckVhY2goZnVuY3Rpb24obWV0aG9kKSB7XG4gICAgICAgICAgdmFyIG5hdGl2ZU1ldGhvZCA9IHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGVbbWV0aG9kXTtcbiAgICAgICAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlW21ldGhvZF0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGFyZ3VtZW50c1swXSA9IG5ldyAoKG1ldGhvZCA9PT0gJ2FkZEljZUNhbmRpZGF0ZScpID9cbiAgICAgICAgICAgICAgICB3aW5kb3cuUlRDSWNlQ2FuZGlkYXRlIDpcbiAgICAgICAgICAgICAgICB3aW5kb3cuUlRDU2Vzc2lvbkRlc2NyaXB0aW9uKShhcmd1bWVudHNbMF0pO1xuICAgICAgICAgICAgcmV0dXJuIG5hdGl2ZU1ldGhvZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuXG4gICAgLy8gc3VwcG9ydCBmb3IgYWRkSWNlQ2FuZGlkYXRlKG51bGwgb3IgdW5kZWZpbmVkKVxuICAgIHZhciBuYXRpdmVBZGRJY2VDYW5kaWRhdGUgPVxuICAgICAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmFkZEljZUNhbmRpZGF0ZTtcbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmFkZEljZUNhbmRpZGF0ZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKCFhcmd1bWVudHNbMF0pIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50c1sxXSkge1xuICAgICAgICAgIGFyZ3VtZW50c1sxXS5hcHBseShudWxsKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gbmF0aXZlQWRkSWNlQ2FuZGlkYXRlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfTtcbiAgfVxufTtcbiIsIi8qXG4gKiAgQ29weXJpZ2h0IChjKSAyMDE2IFRoZSBXZWJSVEMgcHJvamVjdCBhdXRob3JzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqICBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhIEJTRC1zdHlsZSBsaWNlbnNlXG4gKiAgdGhhdCBjYW4gYmUgZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBvZiB0aGUgc291cmNlXG4gKiAgdHJlZS5cbiAqL1xuIC8qIGVzbGludC1lbnYgbm9kZSAqL1xuJ3VzZSBzdHJpY3QnO1xudmFyIHV0aWxzID0gcmVxdWlyZSgnLi4vdXRpbHMuanMnKTtcbnZhciBsb2dnaW5nID0gdXRpbHMubG9nO1xuXG4vLyBFeHBvc2UgcHVibGljIG1ldGhvZHMuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHdpbmRvdykge1xuICB2YXIgYnJvd3NlckRldGFpbHMgPSB1dGlscy5kZXRlY3RCcm93c2VyKHdpbmRvdyk7XG4gIHZhciBuYXZpZ2F0b3IgPSB3aW5kb3cgJiYgd2luZG93Lm5hdmlnYXRvcjtcblxuICB2YXIgY29uc3RyYWludHNUb0Nocm9tZV8gPSBmdW5jdGlvbihjKSB7XG4gICAgaWYgKHR5cGVvZiBjICE9PSAnb2JqZWN0JyB8fCBjLm1hbmRhdG9yeSB8fCBjLm9wdGlvbmFsKSB7XG4gICAgICByZXR1cm4gYztcbiAgICB9XG4gICAgdmFyIGNjID0ge307XG4gICAgT2JqZWN0LmtleXMoYykuZm9yRWFjaChmdW5jdGlvbihrZXkpIHtcbiAgICAgIGlmIChrZXkgPT09ICdyZXF1aXJlJyB8fCBrZXkgPT09ICdhZHZhbmNlZCcgfHwga2V5ID09PSAnbWVkaWFTb3VyY2UnKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHZhciByID0gKHR5cGVvZiBjW2tleV0gPT09ICdvYmplY3QnKSA/IGNba2V5XSA6IHtpZGVhbDogY1trZXldfTtcbiAgICAgIGlmIChyLmV4YWN0ICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIHIuZXhhY3QgPT09ICdudW1iZXInKSB7XG4gICAgICAgIHIubWluID0gci5tYXggPSByLmV4YWN0O1xuICAgICAgfVxuICAgICAgdmFyIG9sZG5hbWVfID0gZnVuY3Rpb24ocHJlZml4LCBuYW1lKSB7XG4gICAgICAgIGlmIChwcmVmaXgpIHtcbiAgICAgICAgICByZXR1cm4gcHJlZml4ICsgbmFtZS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIG5hbWUuc2xpY2UoMSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIChuYW1lID09PSAnZGV2aWNlSWQnKSA/ICdzb3VyY2VJZCcgOiBuYW1lO1xuICAgICAgfTtcbiAgICAgIGlmIChyLmlkZWFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY2Mub3B0aW9uYWwgPSBjYy5vcHRpb25hbCB8fCBbXTtcbiAgICAgICAgdmFyIG9jID0ge307XG4gICAgICAgIGlmICh0eXBlb2Ygci5pZGVhbCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICBvY1tvbGRuYW1lXygnbWluJywga2V5KV0gPSByLmlkZWFsO1xuICAgICAgICAgIGNjLm9wdGlvbmFsLnB1c2gob2MpO1xuICAgICAgICAgIG9jID0ge307XG4gICAgICAgICAgb2Nbb2xkbmFtZV8oJ21heCcsIGtleSldID0gci5pZGVhbDtcbiAgICAgICAgICBjYy5vcHRpb25hbC5wdXNoKG9jKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvY1tvbGRuYW1lXygnJywga2V5KV0gPSByLmlkZWFsO1xuICAgICAgICAgIGNjLm9wdGlvbmFsLnB1c2gob2MpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoci5leGFjdCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiByLmV4YWN0ICE9PSAnbnVtYmVyJykge1xuICAgICAgICBjYy5tYW5kYXRvcnkgPSBjYy5tYW5kYXRvcnkgfHwge307XG4gICAgICAgIGNjLm1hbmRhdG9yeVtvbGRuYW1lXygnJywga2V5KV0gPSByLmV4YWN0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgWydtaW4nLCAnbWF4J10uZm9yRWFjaChmdW5jdGlvbihtaXgpIHtcbiAgICAgICAgICBpZiAoclttaXhdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNjLm1hbmRhdG9yeSA9IGNjLm1hbmRhdG9yeSB8fCB7fTtcbiAgICAgICAgICAgIGNjLm1hbmRhdG9yeVtvbGRuYW1lXyhtaXgsIGtleSldID0gclttaXhdO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgaWYgKGMuYWR2YW5jZWQpIHtcbiAgICAgIGNjLm9wdGlvbmFsID0gKGNjLm9wdGlvbmFsIHx8IFtdKS5jb25jYXQoYy5hZHZhbmNlZCk7XG4gICAgfVxuICAgIHJldHVybiBjYztcbiAgfTtcblxuICB2YXIgc2hpbUNvbnN0cmFpbnRzXyA9IGZ1bmN0aW9uKGNvbnN0cmFpbnRzLCBmdW5jKSB7XG4gICAgaWYgKGJyb3dzZXJEZXRhaWxzLnZlcnNpb24gPj0gNjEpIHtcbiAgICAgIHJldHVybiBmdW5jKGNvbnN0cmFpbnRzKTtcbiAgICB9XG4gICAgY29uc3RyYWludHMgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGNvbnN0cmFpbnRzKSk7XG4gICAgaWYgKGNvbnN0cmFpbnRzICYmIHR5cGVvZiBjb25zdHJhaW50cy5hdWRpbyA9PT0gJ29iamVjdCcpIHtcbiAgICAgIHZhciByZW1hcCA9IGZ1bmN0aW9uKG9iaiwgYSwgYikge1xuICAgICAgICBpZiAoYSBpbiBvYmogJiYgIShiIGluIG9iaikpIHtcbiAgICAgICAgICBvYmpbYl0gPSBvYmpbYV07XG4gICAgICAgICAgZGVsZXRlIG9ialthXTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIGNvbnN0cmFpbnRzID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShjb25zdHJhaW50cykpO1xuICAgICAgcmVtYXAoY29uc3RyYWludHMuYXVkaW8sICdhdXRvR2FpbkNvbnRyb2wnLCAnZ29vZ0F1dG9HYWluQ29udHJvbCcpO1xuICAgICAgcmVtYXAoY29uc3RyYWludHMuYXVkaW8sICdub2lzZVN1cHByZXNzaW9uJywgJ2dvb2dOb2lzZVN1cHByZXNzaW9uJyk7XG4gICAgICBjb25zdHJhaW50cy5hdWRpbyA9IGNvbnN0cmFpbnRzVG9DaHJvbWVfKGNvbnN0cmFpbnRzLmF1ZGlvKTtcbiAgICB9XG4gICAgaWYgKGNvbnN0cmFpbnRzICYmIHR5cGVvZiBjb25zdHJhaW50cy52aWRlbyA9PT0gJ29iamVjdCcpIHtcbiAgICAgIC8vIFNoaW0gZmFjaW5nTW9kZSBmb3IgbW9iaWxlICYgc3VyZmFjZSBwcm8uXG4gICAgICB2YXIgZmFjZSA9IGNvbnN0cmFpbnRzLnZpZGVvLmZhY2luZ01vZGU7XG4gICAgICBmYWNlID0gZmFjZSAmJiAoKHR5cGVvZiBmYWNlID09PSAnb2JqZWN0JykgPyBmYWNlIDoge2lkZWFsOiBmYWNlfSk7XG4gICAgICB2YXIgZ2V0U3VwcG9ydGVkRmFjaW5nTW9kZUxpZXMgPSBicm93c2VyRGV0YWlscy52ZXJzaW9uIDwgNjY7XG5cbiAgICAgIGlmICgoZmFjZSAmJiAoZmFjZS5leGFjdCA9PT0gJ3VzZXInIHx8IGZhY2UuZXhhY3QgPT09ICdlbnZpcm9ubWVudCcgfHxcbiAgICAgICAgICAgICAgICAgICAgZmFjZS5pZGVhbCA9PT0gJ3VzZXInIHx8IGZhY2UuaWRlYWwgPT09ICdlbnZpcm9ubWVudCcpKSAmJlxuICAgICAgICAgICEobmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRTdXBwb3J0ZWRDb25zdHJhaW50cyAmJlxuICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRTdXBwb3J0ZWRDb25zdHJhaW50cygpLmZhY2luZ01vZGUgJiZcbiAgICAgICAgICAgICFnZXRTdXBwb3J0ZWRGYWNpbmdNb2RlTGllcykpIHtcbiAgICAgICAgZGVsZXRlIGNvbnN0cmFpbnRzLnZpZGVvLmZhY2luZ01vZGU7XG4gICAgICAgIHZhciBtYXRjaGVzO1xuICAgICAgICBpZiAoZmFjZS5leGFjdCA9PT0gJ2Vudmlyb25tZW50JyB8fCBmYWNlLmlkZWFsID09PSAnZW52aXJvbm1lbnQnKSB7XG4gICAgICAgICAgbWF0Y2hlcyA9IFsnYmFjaycsICdyZWFyJ107XG4gICAgICAgIH0gZWxzZSBpZiAoZmFjZS5leGFjdCA9PT0gJ3VzZXInIHx8IGZhY2UuaWRlYWwgPT09ICd1c2VyJykge1xuICAgICAgICAgIG1hdGNoZXMgPSBbJ2Zyb250J107XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1hdGNoZXMpIHtcbiAgICAgICAgICAvLyBMb29rIGZvciBtYXRjaGVzIGluIGxhYmVsLCBvciB1c2UgbGFzdCBjYW0gZm9yIGJhY2sgKHR5cGljYWwpLlxuICAgICAgICAgIHJldHVybiBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmVudW1lcmF0ZURldmljZXMoKVxuICAgICAgICAgIC50aGVuKGZ1bmN0aW9uKGRldmljZXMpIHtcbiAgICAgICAgICAgIGRldmljZXMgPSBkZXZpY2VzLmZpbHRlcihmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgIHJldHVybiBkLmtpbmQgPT09ICd2aWRlb2lucHV0JztcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdmFyIGRldiA9IGRldmljZXMuZmluZChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgIHJldHVybiBtYXRjaGVzLnNvbWUoZnVuY3Rpb24obWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZC5sYWJlbC50b0xvd2VyQ2FzZSgpLmluZGV4T2YobWF0Y2gpICE9PSAtMTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmICghZGV2ICYmIGRldmljZXMubGVuZ3RoICYmIG1hdGNoZXMuaW5kZXhPZignYmFjaycpICE9PSAtMSkge1xuICAgICAgICAgICAgICBkZXYgPSBkZXZpY2VzW2RldmljZXMubGVuZ3RoIC0gMV07IC8vIG1vcmUgbGlrZWx5IHRoZSBiYWNrIGNhbVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGRldikge1xuICAgICAgICAgICAgICBjb25zdHJhaW50cy52aWRlby5kZXZpY2VJZCA9IGZhY2UuZXhhY3QgPyB7ZXhhY3Q6IGRldi5kZXZpY2VJZH0gOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7aWRlYWw6IGRldi5kZXZpY2VJZH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdHJhaW50cy52aWRlbyA9IGNvbnN0cmFpbnRzVG9DaHJvbWVfKGNvbnN0cmFpbnRzLnZpZGVvKTtcbiAgICAgICAgICAgIGxvZ2dpbmcoJ2Nocm9tZTogJyArIEpTT04uc3RyaW5naWZ5KGNvbnN0cmFpbnRzKSk7XG4gICAgICAgICAgICByZXR1cm4gZnVuYyhjb25zdHJhaW50cyk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNvbnN0cmFpbnRzLnZpZGVvID0gY29uc3RyYWludHNUb0Nocm9tZV8oY29uc3RyYWludHMudmlkZW8pO1xuICAgIH1cbiAgICBsb2dnaW5nKCdjaHJvbWU6ICcgKyBKU09OLnN0cmluZ2lmeShjb25zdHJhaW50cykpO1xuICAgIHJldHVybiBmdW5jKGNvbnN0cmFpbnRzKTtcbiAgfTtcblxuICB2YXIgc2hpbUVycm9yXyA9IGZ1bmN0aW9uKGUpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbmFtZToge1xuICAgICAgICBQZXJtaXNzaW9uRGVuaWVkRXJyb3I6ICdOb3RBbGxvd2VkRXJyb3InLFxuICAgICAgICBJbnZhbGlkU3RhdGVFcnJvcjogJ05vdFJlYWRhYmxlRXJyb3InLFxuICAgICAgICBEZXZpY2VzTm90Rm91bmRFcnJvcjogJ05vdEZvdW5kRXJyb3InLFxuICAgICAgICBDb25zdHJhaW50Tm90U2F0aXNmaWVkRXJyb3I6ICdPdmVyY29uc3RyYWluZWRFcnJvcicsXG4gICAgICAgIFRyYWNrU3RhcnRFcnJvcjogJ05vdFJlYWRhYmxlRXJyb3InLFxuICAgICAgICBNZWRpYURldmljZUZhaWxlZER1ZVRvU2h1dGRvd246ICdOb3RSZWFkYWJsZUVycm9yJyxcbiAgICAgICAgTWVkaWFEZXZpY2VLaWxsU3dpdGNoT246ICdOb3RSZWFkYWJsZUVycm9yJ1xuICAgICAgfVtlLm5hbWVdIHx8IGUubmFtZSxcbiAgICAgIG1lc3NhZ2U6IGUubWVzc2FnZSxcbiAgICAgIGNvbnN0cmFpbnQ6IGUuY29uc3RyYWludE5hbWUsXG4gICAgICB0b1N0cmluZzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm5hbWUgKyAodGhpcy5tZXNzYWdlICYmICc6ICcpICsgdGhpcy5tZXNzYWdlO1xuICAgICAgfVxuICAgIH07XG4gIH07XG5cbiAgdmFyIGdldFVzZXJNZWRpYV8gPSBmdW5jdGlvbihjb25zdHJhaW50cywgb25TdWNjZXNzLCBvbkVycm9yKSB7XG4gICAgc2hpbUNvbnN0cmFpbnRzXyhjb25zdHJhaW50cywgZnVuY3Rpb24oYykge1xuICAgICAgbmF2aWdhdG9yLndlYmtpdEdldFVzZXJNZWRpYShjLCBvblN1Y2Nlc3MsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgaWYgKG9uRXJyb3IpIHtcbiAgICAgICAgICBvbkVycm9yKHNoaW1FcnJvcl8oZSkpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfTtcblxuICBuYXZpZ2F0b3IuZ2V0VXNlck1lZGlhID0gZ2V0VXNlck1lZGlhXztcblxuICAvLyBSZXR1cm5zIHRoZSByZXN1bHQgb2YgZ2V0VXNlck1lZGlhIGFzIGEgUHJvbWlzZS5cbiAgdmFyIGdldFVzZXJNZWRpYVByb21pc2VfID0gZnVuY3Rpb24oY29uc3RyYWludHMpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICBuYXZpZ2F0b3IuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzLCByZXNvbHZlLCByZWplY3QpO1xuICAgIH0pO1xuICB9O1xuXG4gIGlmICghbmF2aWdhdG9yLm1lZGlhRGV2aWNlcykge1xuICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMgPSB7XG4gICAgICBnZXRVc2VyTWVkaWE6IGdldFVzZXJNZWRpYVByb21pc2VfLFxuICAgICAgZW51bWVyYXRlRGV2aWNlczogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlKSB7XG4gICAgICAgICAgdmFyIGtpbmRzID0ge2F1ZGlvOiAnYXVkaW9pbnB1dCcsIHZpZGVvOiAndmlkZW9pbnB1dCd9O1xuICAgICAgICAgIHJldHVybiB3aW5kb3cuTWVkaWFTdHJlYW1UcmFjay5nZXRTb3VyY2VzKGZ1bmN0aW9uKGRldmljZXMpIHtcbiAgICAgICAgICAgIHJlc29sdmUoZGV2aWNlcy5tYXAoZnVuY3Rpb24oZGV2aWNlKSB7XG4gICAgICAgICAgICAgIHJldHVybiB7bGFiZWw6IGRldmljZS5sYWJlbCxcbiAgICAgICAgICAgICAgICBraW5kOiBraW5kc1tkZXZpY2Uua2luZF0sXG4gICAgICAgICAgICAgICAgZGV2aWNlSWQ6IGRldmljZS5pZCxcbiAgICAgICAgICAgICAgICBncm91cElkOiAnJ307XG4gICAgICAgICAgICB9KSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICAgIGdldFN1cHBvcnRlZENvbnN0cmFpbnRzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBkZXZpY2VJZDogdHJ1ZSwgZWNob0NhbmNlbGxhdGlvbjogdHJ1ZSwgZmFjaW5nTW9kZTogdHJ1ZSxcbiAgICAgICAgICBmcmFtZVJhdGU6IHRydWUsIGhlaWdodDogdHJ1ZSwgd2lkdGg6IHRydWVcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgLy8gQSBzaGltIGZvciBnZXRVc2VyTWVkaWEgbWV0aG9kIG9uIHRoZSBtZWRpYURldmljZXMgb2JqZWN0LlxuICAvLyBUT0RPKEthcHRlbkphbnNzb24pIHJlbW92ZSBvbmNlIGltcGxlbWVudGVkIGluIENocm9tZSBzdGFibGUuXG4gIGlmICghbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEpIHtcbiAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSA9IGZ1bmN0aW9uKGNvbnN0cmFpbnRzKSB7XG4gICAgICByZXR1cm4gZ2V0VXNlck1lZGlhUHJvbWlzZV8oY29uc3RyYWludHMpO1xuICAgIH07XG4gIH0gZWxzZSB7XG4gICAgLy8gRXZlbiB0aG91Z2ggQ2hyb21lIDQ1IGhhcyBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzIGFuZCBhIGdldFVzZXJNZWRpYVxuICAgIC8vIGZ1bmN0aW9uIHdoaWNoIHJldHVybnMgYSBQcm9taXNlLCBpdCBkb2VzIG5vdCBhY2NlcHQgc3BlYy1zdHlsZVxuICAgIC8vIGNvbnN0cmFpbnRzLlxuICAgIHZhciBvcmlnR2V0VXNlck1lZGlhID0gbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEuXG4gICAgICAgIGJpbmQobmF2aWdhdG9yLm1lZGlhRGV2aWNlcyk7XG4gICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEgPSBmdW5jdGlvbihjcykge1xuICAgICAgcmV0dXJuIHNoaW1Db25zdHJhaW50c18oY3MsIGZ1bmN0aW9uKGMpIHtcbiAgICAgICAgcmV0dXJuIG9yaWdHZXRVc2VyTWVkaWEoYykudGhlbihmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgICBpZiAoYy5hdWRpbyAmJiAhc3RyZWFtLmdldEF1ZGlvVHJhY2tzKCkubGVuZ3RoIHx8XG4gICAgICAgICAgICAgIGMudmlkZW8gJiYgIXN0cmVhbS5nZXRWaWRlb1RyYWNrcygpLmxlbmd0aCkge1xuICAgICAgICAgICAgc3RyZWFtLmdldFRyYWNrcygpLmZvckVhY2goZnVuY3Rpb24odHJhY2spIHtcbiAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRE9NRXhjZXB0aW9uKCcnLCAnTm90Rm91bmRFcnJvcicpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gc3RyZWFtO1xuICAgICAgICB9LCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHNoaW1FcnJvcl8oZSkpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH07XG4gIH1cblxuICAvLyBEdW1teSBkZXZpY2VjaGFuZ2UgZXZlbnQgbWV0aG9kcy5cbiAgLy8gVE9ETyhLYXB0ZW5KYW5zc29uKSByZW1vdmUgb25jZSBpbXBsZW1lbnRlZCBpbiBDaHJvbWUgc3RhYmxlLlxuICBpZiAodHlwZW9mIG5hdmlnYXRvci5tZWRpYURldmljZXMuYWRkRXZlbnRMaXN0ZW5lciA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgIGxvZ2dpbmcoJ0R1bW15IG1lZGlhRGV2aWNlcy5hZGRFdmVudExpc3RlbmVyIGNhbGxlZC4nKTtcbiAgICB9O1xuICB9XG4gIGlmICh0eXBlb2YgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5yZW1vdmVFdmVudExpc3RlbmVyID09PSAndW5kZWZpbmVkJykge1xuICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMucmVtb3ZlRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uKCkge1xuICAgICAgbG9nZ2luZygnRHVtbXkgbWVkaWFEZXZpY2VzLnJlbW92ZUV2ZW50TGlzdGVuZXIgY2FsbGVkLicpO1xuICAgIH07XG4gIH1cbn07XG4iLCIvKlxuICogIENvcHlyaWdodCAoYykgMjAxNyBUaGUgV2ViUlRDIHByb2plY3QgYXV0aG9ycy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiAgVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYSBCU0Qtc3R5bGUgbGljZW5zZVxuICogIHRoYXQgY2FuIGJlIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3Qgb2YgdGhlIHNvdXJjZVxuICogIHRyZWUuXG4gKi9cbiAvKiBlc2xpbnQtZW52IG5vZGUgKi9cbid1c2Ugc3RyaWN0JztcblxudmFyIFNEUFV0aWxzID0gcmVxdWlyZSgnc2RwJyk7XG52YXIgdXRpbHMgPSByZXF1aXJlKCcuL3V0aWxzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBzaGltUlRDSWNlQ2FuZGlkYXRlOiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICAvLyBmb3VuZGF0aW9uIGlzIGFyYml0cmFyaWx5IGNob3NlbiBhcyBhbiBpbmRpY2F0b3IgZm9yIGZ1bGwgc3VwcG9ydCBmb3JcbiAgICAvLyBodHRwczovL3czYy5naXRodWIuaW8vd2VicnRjLXBjLyNydGNpY2VjYW5kaWRhdGUtaW50ZXJmYWNlXG4gICAgaWYgKHdpbmRvdy5SVENJY2VDYW5kaWRhdGUgJiYgJ2ZvdW5kYXRpb24nIGluXG4gICAgICAgIHdpbmRvdy5SVENJY2VDYW5kaWRhdGUucHJvdG90eXBlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIE5hdGl2ZVJUQ0ljZUNhbmRpZGF0ZSA9IHdpbmRvdy5SVENJY2VDYW5kaWRhdGU7XG4gICAgd2luZG93LlJUQ0ljZUNhbmRpZGF0ZSA9IGZ1bmN0aW9uKGFyZ3MpIHtcbiAgICAgIC8vIFJlbW92ZSB0aGUgYT0gd2hpY2ggc2hvdWxkbid0IGJlIHBhcnQgb2YgdGhlIGNhbmRpZGF0ZSBzdHJpbmcuXG4gICAgICBpZiAodHlwZW9mIGFyZ3MgPT09ICdvYmplY3QnICYmIGFyZ3MuY2FuZGlkYXRlICYmXG4gICAgICAgICAgYXJncy5jYW5kaWRhdGUuaW5kZXhPZignYT0nKSA9PT0gMCkge1xuICAgICAgICBhcmdzID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShhcmdzKSk7XG4gICAgICAgIGFyZ3MuY2FuZGlkYXRlID0gYXJncy5jYW5kaWRhdGUuc3Vic3RyKDIpO1xuICAgICAgfVxuXG4gICAgICAvLyBBdWdtZW50IHRoZSBuYXRpdmUgY2FuZGlkYXRlIHdpdGggdGhlIHBhcnNlZCBmaWVsZHMuXG4gICAgICB2YXIgbmF0aXZlQ2FuZGlkYXRlID0gbmV3IE5hdGl2ZVJUQ0ljZUNhbmRpZGF0ZShhcmdzKTtcbiAgICAgIHZhciBwYXJzZWRDYW5kaWRhdGUgPSBTRFBVdGlscy5wYXJzZUNhbmRpZGF0ZShhcmdzLmNhbmRpZGF0ZSk7XG4gICAgICB2YXIgYXVnbWVudGVkQ2FuZGlkYXRlID0gT2JqZWN0LmFzc2lnbihuYXRpdmVDYW5kaWRhdGUsXG4gICAgICAgICAgcGFyc2VkQ2FuZGlkYXRlKTtcblxuICAgICAgLy8gQWRkIGEgc2VyaWFsaXplciB0aGF0IGRvZXMgbm90IHNlcmlhbGl6ZSB0aGUgZXh0cmEgYXR0cmlidXRlcy5cbiAgICAgIGF1Z21lbnRlZENhbmRpZGF0ZS50b0pTT04gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBjYW5kaWRhdGU6IGF1Z21lbnRlZENhbmRpZGF0ZS5jYW5kaWRhdGUsXG4gICAgICAgICAgc2RwTWlkOiBhdWdtZW50ZWRDYW5kaWRhdGUuc2RwTWlkLFxuICAgICAgICAgIHNkcE1MaW5lSW5kZXg6IGF1Z21lbnRlZENhbmRpZGF0ZS5zZHBNTGluZUluZGV4LFxuICAgICAgICAgIHVzZXJuYW1lRnJhZ21lbnQ6IGF1Z21lbnRlZENhbmRpZGF0ZS51c2VybmFtZUZyYWdtZW50LFxuICAgICAgICB9O1xuICAgICAgfTtcbiAgICAgIHJldHVybiBhdWdtZW50ZWRDYW5kaWRhdGU7XG4gICAgfTtcblxuICAgIC8vIEhvb2sgdXAgdGhlIGF1Z21lbnRlZCBjYW5kaWRhdGUgaW4gb25pY2VjYW5kaWRhdGUgYW5kXG4gICAgLy8gYWRkRXZlbnRMaXN0ZW5lcignaWNlY2FuZGlkYXRlJywgLi4uKVxuICAgIHV0aWxzLndyYXBQZWVyQ29ubmVjdGlvbkV2ZW50KHdpbmRvdywgJ2ljZWNhbmRpZGF0ZScsIGZ1bmN0aW9uKGUpIHtcbiAgICAgIGlmIChlLmNhbmRpZGF0ZSkge1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZSwgJ2NhbmRpZGF0ZScsIHtcbiAgICAgICAgICB2YWx1ZTogbmV3IHdpbmRvdy5SVENJY2VDYW5kaWRhdGUoZS5jYW5kaWRhdGUpLFxuICAgICAgICAgIHdyaXRhYmxlOiAnZmFsc2UnXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGU7XG4gICAgfSk7XG4gIH0sXG5cbiAgLy8gc2hpbUNyZWF0ZU9iamVjdFVSTCBtdXN0IGJlIGNhbGxlZCBiZWZvcmUgc2hpbVNvdXJjZU9iamVjdCB0byBhdm9pZCBsb29wLlxuXG4gIHNoaW1DcmVhdGVPYmplY3RVUkw6IGZ1bmN0aW9uKHdpbmRvdykge1xuICAgIHZhciBVUkwgPSB3aW5kb3cgJiYgd2luZG93LlVSTDtcblxuICAgIGlmICghKHR5cGVvZiB3aW5kb3cgPT09ICdvYmplY3QnICYmIHdpbmRvdy5IVE1MTWVkaWFFbGVtZW50ICYmXG4gICAgICAgICAgJ3NyY09iamVjdCcgaW4gd2luZG93LkhUTUxNZWRpYUVsZW1lbnQucHJvdG90eXBlICYmXG4gICAgICAgIFVSTC5jcmVhdGVPYmplY3RVUkwgJiYgVVJMLnJldm9rZU9iamVjdFVSTCkpIHtcbiAgICAgIC8vIE9ubHkgc2hpbSBDcmVhdGVPYmplY3RVUkwgdXNpbmcgc3JjT2JqZWN0IGlmIHNyY09iamVjdCBleGlzdHMuXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHZhciBuYXRpdmVDcmVhdGVPYmplY3RVUkwgPSBVUkwuY3JlYXRlT2JqZWN0VVJMLmJpbmQoVVJMKTtcbiAgICB2YXIgbmF0aXZlUmV2b2tlT2JqZWN0VVJMID0gVVJMLnJldm9rZU9iamVjdFVSTC5iaW5kKFVSTCk7XG4gICAgdmFyIHN0cmVhbXMgPSBuZXcgTWFwKCksIG5ld0lkID0gMDtcblxuICAgIFVSTC5jcmVhdGVPYmplY3RVUkwgPSBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgIGlmICgnZ2V0VHJhY2tzJyBpbiBzdHJlYW0pIHtcbiAgICAgICAgdmFyIHVybCA9ICdwb2x5YmxvYjonICsgKCsrbmV3SWQpO1xuICAgICAgICBzdHJlYW1zLnNldCh1cmwsIHN0cmVhbSk7XG4gICAgICAgIHV0aWxzLmRlcHJlY2F0ZWQoJ1VSTC5jcmVhdGVPYmplY3RVUkwoc3RyZWFtKScsXG4gICAgICAgICAgICAnZWxlbS5zcmNPYmplY3QgPSBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHVybDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuYXRpdmVDcmVhdGVPYmplY3RVUkwoc3RyZWFtKTtcbiAgICB9O1xuICAgIFVSTC5yZXZva2VPYmplY3RVUkwgPSBmdW5jdGlvbih1cmwpIHtcbiAgICAgIG5hdGl2ZVJldm9rZU9iamVjdFVSTCh1cmwpO1xuICAgICAgc3RyZWFtcy5kZWxldGUodXJsKTtcbiAgICB9O1xuXG4gICAgdmFyIGRzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iod2luZG93LkhUTUxNZWRpYUVsZW1lbnQucHJvdG90eXBlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzcmMnKTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkod2luZG93LkhUTUxNZWRpYUVsZW1lbnQucHJvdG90eXBlLCAnc3JjJywge1xuICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIGRzYy5nZXQuYXBwbHkodGhpcyk7XG4gICAgICB9LFxuICAgICAgc2V0OiBmdW5jdGlvbih1cmwpIHtcbiAgICAgICAgdGhpcy5zcmNPYmplY3QgPSBzdHJlYW1zLmdldCh1cmwpIHx8IG51bGw7XG4gICAgICAgIHJldHVybiBkc2Muc2V0LmFwcGx5KHRoaXMsIFt1cmxdKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHZhciBuYXRpdmVTZXRBdHRyaWJ1dGUgPSB3aW5kb3cuSFRNTE1lZGlhRWxlbWVudC5wcm90b3R5cGUuc2V0QXR0cmlidXRlO1xuICAgIHdpbmRvdy5IVE1MTWVkaWFFbGVtZW50LnByb3RvdHlwZS5zZXRBdHRyaWJ1dGUgPSBmdW5jdGlvbigpIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyICYmXG4gICAgICAgICAgKCcnICsgYXJndW1lbnRzWzBdKS50b0xvd2VyQ2FzZSgpID09PSAnc3JjJykge1xuICAgICAgICB0aGlzLnNyY09iamVjdCA9IHN0cmVhbXMuZ2V0KGFyZ3VtZW50c1sxXSkgfHwgbnVsbDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuYXRpdmVTZXRBdHRyaWJ1dGUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9O1xuICB9LFxuXG4gIHNoaW1NYXhNZXNzYWdlU2l6ZTogZnVuY3Rpb24od2luZG93KSB7XG4gICAgaWYgKHdpbmRvdy5SVENTY3RwVHJhbnNwb3J0IHx8ICF3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIGJyb3dzZXJEZXRhaWxzID0gdXRpbHMuZGV0ZWN0QnJvd3Nlcih3aW5kb3cpO1xuXG4gICAgaWYgKCEoJ3NjdHAnIGluIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUpKSB7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkod2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSwgJ3NjdHAnLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIHR5cGVvZiB0aGlzLl9zY3RwID09PSAndW5kZWZpbmVkJyA/IG51bGwgOiB0aGlzLl9zY3RwO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgc2N0cEluRGVzY3JpcHRpb24gPSBmdW5jdGlvbihkZXNjcmlwdGlvbikge1xuICAgICAgdmFyIHNlY3Rpb25zID0gU0RQVXRpbHMuc3BsaXRTZWN0aW9ucyhkZXNjcmlwdGlvbi5zZHApO1xuICAgICAgc2VjdGlvbnMuc2hpZnQoKTtcbiAgICAgIHJldHVybiBzZWN0aW9ucy5zb21lKGZ1bmN0aW9uKG1lZGlhU2VjdGlvbikge1xuICAgICAgICB2YXIgbUxpbmUgPSBTRFBVdGlscy5wYXJzZU1MaW5lKG1lZGlhU2VjdGlvbik7XG4gICAgICAgIHJldHVybiBtTGluZSAmJiBtTGluZS5raW5kID09PSAnYXBwbGljYXRpb24nXG4gICAgICAgICAgICAmJiBtTGluZS5wcm90b2NvbC5pbmRleE9mKCdTQ1RQJykgIT09IC0xO1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIHZhciBnZXRSZW1vdGVGaXJlZm94VmVyc2lvbiA9IGZ1bmN0aW9uKGRlc2NyaXB0aW9uKSB7XG4gICAgICAvLyBUT0RPOiBJcyB0aGVyZSBhIGJldHRlciBzb2x1dGlvbiBmb3IgZGV0ZWN0aW5nIEZpcmVmb3g/XG4gICAgICB2YXIgbWF0Y2ggPSBkZXNjcmlwdGlvbi5zZHAubWF0Y2goL21vemlsbGEuLi5USElTX0lTX1NEUEFSVEEtKFxcZCspLyk7XG4gICAgICBpZiAobWF0Y2ggPT09IG51bGwgfHwgbWF0Y2gubGVuZ3RoIDwgMikge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG4gICAgICB2YXIgdmVyc2lvbiA9IHBhcnNlSW50KG1hdGNoWzFdLCAxMCk7XG4gICAgICAvLyBUZXN0IGZvciBOYU4gKHllcywgdGhpcyBpcyB1Z2x5KVxuICAgICAgcmV0dXJuIHZlcnNpb24gIT09IHZlcnNpb24gPyAtMSA6IHZlcnNpb247XG4gICAgfTtcblxuICAgIHZhciBnZXRDYW5TZW5kTWF4TWVzc2FnZVNpemUgPSBmdW5jdGlvbihyZW1vdGVJc0ZpcmVmb3gpIHtcbiAgICAgIC8vIEV2ZXJ5IGltcGxlbWVudGF0aW9uIHdlIGtub3cgY2FuIHNlbmQgYXQgbGVhc3QgNjQgS2lCLlxuICAgICAgLy8gTm90ZTogQWx0aG91Z2ggQ2hyb21lIGlzIHRlY2huaWNhbGx5IGFibGUgdG8gc2VuZCB1cCB0byAyNTYgS2lCLCB0aGVcbiAgICAgIC8vICAgICAgIGRhdGEgZG9lcyBub3QgcmVhY2ggdGhlIG90aGVyIHBlZXIgcmVsaWFibHkuXG4gICAgICAvLyAgICAgICBTZWU6IGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC93ZWJydGMvaXNzdWVzL2RldGFpbD9pZD04NDE5XG4gICAgICB2YXIgY2FuU2VuZE1heE1lc3NhZ2VTaXplID0gNjU1MzY7XG4gICAgICBpZiAoYnJvd3NlckRldGFpbHMuYnJvd3NlciA9PT0gJ2ZpcmVmb3gnKSB7XG4gICAgICAgIGlmIChicm93c2VyRGV0YWlscy52ZXJzaW9uIDwgNTcpIHtcbiAgICAgICAgICBpZiAocmVtb3RlSXNGaXJlZm94ID09PSAtMSkge1xuICAgICAgICAgICAgLy8gRkYgPCA1NyB3aWxsIHNlbmQgaW4gMTYgS2lCIGNodW5rcyB1c2luZyB0aGUgZGVwcmVjYXRlZCBQUElEXG4gICAgICAgICAgICAvLyBmcmFnbWVudGF0aW9uLlxuICAgICAgICAgICAgY2FuU2VuZE1heE1lc3NhZ2VTaXplID0gMTYzODQ7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEhvd2V2ZXIsIG90aGVyIEZGIChhbmQgUkFXUlRDKSBjYW4gcmVhc3NlbWJsZSBQUElELWZyYWdtZW50ZWRcbiAgICAgICAgICAgIC8vIG1lc3NhZ2VzLiBUaHVzLCBzdXBwb3J0aW5nIH4yIEdpQiB3aGVuIHNlbmRpbmcuXG4gICAgICAgICAgICBjYW5TZW5kTWF4TWVzc2FnZVNpemUgPSAyMTQ3NDgzNjM3O1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBDdXJyZW50bHksIGFsbCBGRiA+PSA1NyB3aWxsIHJlc2V0IHRoZSByZW1vdGUgbWF4aW11bSBtZXNzYWdlIHNpemVcbiAgICAgICAgICAvLyB0byB0aGUgZGVmYXVsdCB2YWx1ZSB3aGVuIGEgZGF0YSBjaGFubmVsIGlzIGNyZWF0ZWQgYXQgYSBsYXRlclxuICAgICAgICAgIC8vIHN0YWdlLiA6KFxuICAgICAgICAgIC8vIFNlZTogaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTQyNjgzMVxuICAgICAgICAgIGNhblNlbmRNYXhNZXNzYWdlU2l6ZSA9XG4gICAgICAgICAgICBicm93c2VyRGV0YWlscy52ZXJzaW9uID09PSA1NyA/IDY1NTM1IDogNjU1MzY7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBjYW5TZW5kTWF4TWVzc2FnZVNpemU7XG4gICAgfTtcblxuICAgIHZhciBnZXRNYXhNZXNzYWdlU2l6ZSA9IGZ1bmN0aW9uKGRlc2NyaXB0aW9uLCByZW1vdGVJc0ZpcmVmb3gpIHtcbiAgICAgIC8vIE5vdGU6IDY1NTM2IGJ5dGVzIGlzIHRoZSBkZWZhdWx0IHZhbHVlIGZyb20gdGhlIFNEUCBzcGVjLiBBbHNvLFxuICAgICAgLy8gICAgICAgZXZlcnkgaW1wbGVtZW50YXRpb24gd2Uga25vdyBzdXBwb3J0cyByZWNlaXZpbmcgNjU1MzYgYnl0ZXMuXG4gICAgICB2YXIgbWF4TWVzc2FnZVNpemUgPSA2NTUzNjtcblxuICAgICAgLy8gRkYgNTcgaGFzIGEgc2xpZ2h0bHkgaW5jb3JyZWN0IGRlZmF1bHQgcmVtb3RlIG1heCBtZXNzYWdlIHNpemUsIHNvXG4gICAgICAvLyB3ZSBuZWVkIHRvIGFkanVzdCBpdCBoZXJlIHRvIGF2b2lkIGEgZmFpbHVyZSB3aGVuIHNlbmRpbmcuXG4gICAgICAvLyBTZWU6IGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTE0MjU2OTdcbiAgICAgIGlmIChicm93c2VyRGV0YWlscy5icm93c2VyID09PSAnZmlyZWZveCdcbiAgICAgICAgICAgJiYgYnJvd3NlckRldGFpbHMudmVyc2lvbiA9PT0gNTcpIHtcbiAgICAgICAgbWF4TWVzc2FnZVNpemUgPSA2NTUzNTtcbiAgICAgIH1cblxuICAgICAgdmFyIG1hdGNoID0gU0RQVXRpbHMubWF0Y2hQcmVmaXgoZGVzY3JpcHRpb24uc2RwLCAnYT1tYXgtbWVzc2FnZS1zaXplOicpO1xuICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDApIHtcbiAgICAgICAgbWF4TWVzc2FnZVNpemUgPSBwYXJzZUludChtYXRjaFswXS5zdWJzdHIoMTkpLCAxMCk7XG4gICAgICB9IGVsc2UgaWYgKGJyb3dzZXJEZXRhaWxzLmJyb3dzZXIgPT09ICdmaXJlZm94JyAmJlxuICAgICAgICAgICAgICAgICAgcmVtb3RlSXNGaXJlZm94ICE9PSAtMSkge1xuICAgICAgICAvLyBJZiB0aGUgbWF4aW11bSBtZXNzYWdlIHNpemUgaXMgbm90IHByZXNlbnQgaW4gdGhlIHJlbW90ZSBTRFAgYW5kXG4gICAgICAgIC8vIGJvdGggbG9jYWwgYW5kIHJlbW90ZSBhcmUgRmlyZWZveCwgdGhlIHJlbW90ZSBwZWVyIGNhbiByZWNlaXZlXG4gICAgICAgIC8vIH4yIEdpQi5cbiAgICAgICAgbWF4TWVzc2FnZVNpemUgPSAyMTQ3NDgzNjM3O1xuICAgICAgfVxuICAgICAgcmV0dXJuIG1heE1lc3NhZ2VTaXplO1xuICAgIH07XG5cbiAgICB2YXIgb3JpZ1NldFJlbW90ZURlc2NyaXB0aW9uID1cbiAgICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5zZXRSZW1vdGVEZXNjcmlwdGlvbjtcbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnNldFJlbW90ZURlc2NyaXB0aW9uID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgcGMgPSB0aGlzO1xuICAgICAgcGMuX3NjdHAgPSBudWxsO1xuXG4gICAgICBpZiAoc2N0cEluRGVzY3JpcHRpb24oYXJndW1lbnRzWzBdKSkge1xuICAgICAgICAvLyBDaGVjayBpZiB0aGUgcmVtb3RlIGlzIEZGLlxuICAgICAgICB2YXIgaXNGaXJlZm94ID0gZ2V0UmVtb3RlRmlyZWZveFZlcnNpb24oYXJndW1lbnRzWzBdKTtcblxuICAgICAgICAvLyBHZXQgdGhlIG1heGltdW0gbWVzc2FnZSBzaXplIHRoZSBsb2NhbCBwZWVyIGlzIGNhcGFibGUgb2Ygc2VuZGluZ1xuICAgICAgICB2YXIgY2FuU2VuZE1NUyA9IGdldENhblNlbmRNYXhNZXNzYWdlU2l6ZShpc0ZpcmVmb3gpO1xuXG4gICAgICAgIC8vIEdldCB0aGUgbWF4aW11bSBtZXNzYWdlIHNpemUgb2YgdGhlIHJlbW90ZSBwZWVyLlxuICAgICAgICB2YXIgcmVtb3RlTU1TID0gZ2V0TWF4TWVzc2FnZVNpemUoYXJndW1lbnRzWzBdLCBpc0ZpcmVmb3gpO1xuXG4gICAgICAgIC8vIERldGVybWluZSBmaW5hbCBtYXhpbXVtIG1lc3NhZ2Ugc2l6ZVxuICAgICAgICB2YXIgbWF4TWVzc2FnZVNpemU7XG4gICAgICAgIGlmIChjYW5TZW5kTU1TID09PSAwICYmIHJlbW90ZU1NUyA9PT0gMCkge1xuICAgICAgICAgIG1heE1lc3NhZ2VTaXplID0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZO1xuICAgICAgICB9IGVsc2UgaWYgKGNhblNlbmRNTVMgPT09IDAgfHwgcmVtb3RlTU1TID09PSAwKSB7XG4gICAgICAgICAgbWF4TWVzc2FnZVNpemUgPSBNYXRoLm1heChjYW5TZW5kTU1TLCByZW1vdGVNTVMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG1heE1lc3NhZ2VTaXplID0gTWF0aC5taW4oY2FuU2VuZE1NUywgcmVtb3RlTU1TKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENyZWF0ZSBhIGR1bW15IFJUQ1NjdHBUcmFuc3BvcnQgb2JqZWN0IGFuZCB0aGUgJ21heE1lc3NhZ2VTaXplJ1xuICAgICAgICAvLyBhdHRyaWJ1dGUuXG4gICAgICAgIHZhciBzY3RwID0ge307XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShzY3RwLCAnbWF4TWVzc2FnZVNpemUnLCB7XG4gICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiBtYXhNZXNzYWdlU2l6ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBwYy5fc2N0cCA9IHNjdHA7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBvcmlnU2V0UmVtb3RlRGVzY3JpcHRpb24uYXBwbHkocGMsIGFyZ3VtZW50cyk7XG4gICAgfTtcbiAgfSxcblxuICBzaGltU2VuZFRocm93VHlwZUVycm9yOiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICAvLyBOb3RlOiBBbHRob3VnaCBGaXJlZm94ID49IDU3IGhhcyBhIG5hdGl2ZSBpbXBsZW1lbnRhdGlvbiwgdGhlIG1heGltdW1cbiAgICAvLyAgICAgICBtZXNzYWdlIHNpemUgY2FuIGJlIHJlc2V0IGZvciBhbGwgZGF0YSBjaGFubmVscyBhdCBhIGxhdGVyIHN0YWdlLlxuICAgIC8vICAgICAgIFNlZTogaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTQyNjgzMVxuXG4gICAgdmFyIG9yaWdDcmVhdGVEYXRhQ2hhbm5lbCA9XG4gICAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmNyZWF0ZURhdGFDaGFubmVsO1xuICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuY3JlYXRlRGF0YUNoYW5uZWwgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBwYyA9IHRoaXM7XG4gICAgICB2YXIgZGF0YUNoYW5uZWwgPSBvcmlnQ3JlYXRlRGF0YUNoYW5uZWwuYXBwbHkocGMsIGFyZ3VtZW50cyk7XG4gICAgICB2YXIgb3JpZ0RhdGFDaGFubmVsU2VuZCA9IGRhdGFDaGFubmVsLnNlbmQ7XG5cbiAgICAgIC8vIFBhdGNoICdzZW5kJyBtZXRob2RcbiAgICAgIGRhdGFDaGFubmVsLnNlbmQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGRjID0gdGhpcztcbiAgICAgICAgdmFyIGRhdGEgPSBhcmd1bWVudHNbMF07XG4gICAgICAgIHZhciBsZW5ndGggPSBkYXRhLmxlbmd0aCB8fCBkYXRhLnNpemUgfHwgZGF0YS5ieXRlTGVuZ3RoO1xuICAgICAgICBpZiAobGVuZ3RoID4gcGMuc2N0cC5tYXhNZXNzYWdlU2l6ZSkge1xuICAgICAgICAgIHRocm93IG5ldyBET01FeGNlcHRpb24oJ01lc3NhZ2UgdG9vIGxhcmdlIChjYW4gc2VuZCBhIG1heGltdW0gb2YgJyArXG4gICAgICAgICAgICBwYy5zY3RwLm1heE1lc3NhZ2VTaXplICsgJyBieXRlcyknLCAnVHlwZUVycm9yJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9yaWdEYXRhQ2hhbm5lbFNlbmQuYXBwbHkoZGMsIGFyZ3VtZW50cyk7XG4gICAgICB9O1xuXG4gICAgICByZXR1cm4gZGF0YUNoYW5uZWw7XG4gICAgfTtcbiAgfVxufTtcbiIsIi8qXG4gKiAgQ29weXJpZ2h0IChjKSAyMDE2IFRoZSBXZWJSVEMgcHJvamVjdCBhdXRob3JzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqICBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhIEJTRC1zdHlsZSBsaWNlbnNlXG4gKiAgdGhhdCBjYW4gYmUgZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBvZiB0aGUgc291cmNlXG4gKiAgdHJlZS5cbiAqL1xuIC8qIGVzbGludC1lbnYgbm9kZSAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbHMgPSByZXF1aXJlKCcuLi91dGlscycpO1xudmFyIHNoaW1SVENQZWVyQ29ubmVjdGlvbiA9IHJlcXVpcmUoJ3J0Y3BlZXJjb25uZWN0aW9uLXNoaW0nKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHNoaW1HZXRVc2VyTWVkaWE6IHJlcXVpcmUoJy4vZ2V0dXNlcm1lZGlhJyksXG4gIHNoaW1QZWVyQ29ubmVjdGlvbjogZnVuY3Rpb24od2luZG93KSB7XG4gICAgdmFyIGJyb3dzZXJEZXRhaWxzID0gdXRpbHMuZGV0ZWN0QnJvd3Nlcih3aW5kb3cpO1xuXG4gICAgaWYgKHdpbmRvdy5SVENJY2VHYXRoZXJlcikge1xuICAgICAgLy8gT1JUQyBkZWZpbmVzIGFuIFJUQ0ljZUNhbmRpZGF0ZSBvYmplY3QgYnV0IG5vIGNvbnN0cnVjdG9yLlxuICAgICAgLy8gTm90IGltcGxlbWVudGVkIGluIEVkZ2UuXG4gICAgICBpZiAoIXdpbmRvdy5SVENJY2VDYW5kaWRhdGUpIHtcbiAgICAgICAgd2luZG93LlJUQ0ljZUNhbmRpZGF0ZSA9IGZ1bmN0aW9uKGFyZ3MpIHtcbiAgICAgICAgICByZXR1cm4gYXJncztcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIC8vIE9SVEMgZG9lcyBub3QgaGF2ZSBhIHNlc3Npb24gZGVzY3JpcHRpb24gb2JqZWN0IGJ1dFxuICAgICAgLy8gb3RoZXIgYnJvd3NlcnMgKGkuZS4gQ2hyb21lKSB0aGF0IHdpbGwgc3VwcG9ydCBib3RoIFBDIGFuZCBPUlRDXG4gICAgICAvLyBpbiB0aGUgZnV0dXJlIG1pZ2h0IGhhdmUgdGhpcyBkZWZpbmVkIGFscmVhZHkuXG4gICAgICBpZiAoIXdpbmRvdy5SVENTZXNzaW9uRGVzY3JpcHRpb24pIHtcbiAgICAgICAgd2luZG93LlJUQ1Nlc3Npb25EZXNjcmlwdGlvbiA9IGZ1bmN0aW9uKGFyZ3MpIHtcbiAgICAgICAgICByZXR1cm4gYXJncztcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIC8vIHRoaXMgYWRkcyBhbiBhZGRpdGlvbmFsIGV2ZW50IGxpc3RlbmVyIHRvIE1lZGlhU3RyYWNrVHJhY2sgdGhhdCBzaWduYWxzXG4gICAgICAvLyB3aGVuIGEgdHJhY2tzIGVuYWJsZWQgcHJvcGVydHkgd2FzIGNoYW5nZWQuIFdvcmthcm91bmQgZm9yIGEgYnVnIGluXG4gICAgICAvLyBhZGRTdHJlYW0sIHNlZSBiZWxvdy4gTm8gbG9uZ2VyIHJlcXVpcmVkIGluIDE1MDI1K1xuICAgICAgaWYgKGJyb3dzZXJEZXRhaWxzLnZlcnNpb24gPCAxNTAyNSkge1xuICAgICAgICB2YXIgb3JpZ01TVEVuYWJsZWQgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKFxuICAgICAgICAgICAgd2luZG93Lk1lZGlhU3RyZWFtVHJhY2sucHJvdG90eXBlLCAnZW5hYmxlZCcpO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkod2luZG93Lk1lZGlhU3RyZWFtVHJhY2sucHJvdG90eXBlLCAnZW5hYmxlZCcsIHtcbiAgICAgICAgICBzZXQ6IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgICAgICBvcmlnTVNURW5hYmxlZC5zZXQuY2FsbCh0aGlzLCB2YWx1ZSk7XG4gICAgICAgICAgICB2YXIgZXYgPSBuZXcgRXZlbnQoJ2VuYWJsZWQnKTtcbiAgICAgICAgICAgIGV2LmVuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChldik7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBPUlRDIGRlZmluZXMgdGhlIERUTUYgc2VuZGVyIGEgYml0IGRpZmZlcmVudC5cbiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vdzNjL29ydGMvaXNzdWVzLzcxNFxuICAgIGlmICh3aW5kb3cuUlRDUnRwU2VuZGVyICYmICEoJ2R0bWYnIGluIHdpbmRvdy5SVENSdHBTZW5kZXIucHJvdG90eXBlKSkge1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHdpbmRvdy5SVENSdHBTZW5kZXIucHJvdG90eXBlLCAnZHRtZicsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICBpZiAodGhpcy5fZHRtZiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBpZiAodGhpcy50cmFjay5raW5kID09PSAnYXVkaW8nKSB7XG4gICAgICAgICAgICAgIHRoaXMuX2R0bWYgPSBuZXcgd2luZG93LlJUQ0R0bWZTZW5kZXIodGhpcyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMudHJhY2sua2luZCA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICB0aGlzLl9kdG1mID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHRoaXMuX2R0bWY7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiA9XG4gICAgICAgIHNoaW1SVENQZWVyQ29ubmVjdGlvbih3aW5kb3csIGJyb3dzZXJEZXRhaWxzLnZlcnNpb24pO1xuICB9LFxuICBzaGltUmVwbGFjZVRyYWNrOiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICAvLyBPUlRDIGhhcyByZXBsYWNlVHJhY2sgLS0gaHR0cHM6Ly9naXRodWIuY29tL3czYy9vcnRjL2lzc3Vlcy82MTRcbiAgICBpZiAod2luZG93LlJUQ1J0cFNlbmRlciAmJlxuICAgICAgICAhKCdyZXBsYWNlVHJhY2snIGluIHdpbmRvdy5SVENSdHBTZW5kZXIucHJvdG90eXBlKSkge1xuICAgICAgd2luZG93LlJUQ1J0cFNlbmRlci5wcm90b3R5cGUucmVwbGFjZVRyYWNrID1cbiAgICAgICAgICB3aW5kb3cuUlRDUnRwU2VuZGVyLnByb3RvdHlwZS5zZXRUcmFjaztcbiAgICB9XG4gIH1cbn07XG4iLCIvKlxuICogIENvcHlyaWdodCAoYykgMjAxNiBUaGUgV2ViUlRDIHByb2plY3QgYXV0aG9ycy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiAgVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYSBCU0Qtc3R5bGUgbGljZW5zZVxuICogIHRoYXQgY2FuIGJlIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3Qgb2YgdGhlIHNvdXJjZVxuICogIHRyZWUuXG4gKi9cbiAvKiBlc2xpbnQtZW52IG5vZGUgKi9cbid1c2Ugc3RyaWN0JztcblxuLy8gRXhwb3NlIHB1YmxpYyBtZXRob2RzLlxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbih3aW5kb3cpIHtcbiAgdmFyIG5hdmlnYXRvciA9IHdpbmRvdyAmJiB3aW5kb3cubmF2aWdhdG9yO1xuXG4gIHZhciBzaGltRXJyb3JfID0gZnVuY3Rpb24oZSkge1xuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiB7UGVybWlzc2lvbkRlbmllZEVycm9yOiAnTm90QWxsb3dlZEVycm9yJ31bZS5uYW1lXSB8fCBlLm5hbWUsXG4gICAgICBtZXNzYWdlOiBlLm1lc3NhZ2UsXG4gICAgICBjb25zdHJhaW50OiBlLmNvbnN0cmFpbnQsXG4gICAgICB0b1N0cmluZzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm5hbWU7XG4gICAgICB9XG4gICAgfTtcbiAgfTtcblxuICAvLyBnZXRVc2VyTWVkaWEgZXJyb3Igc2hpbS5cbiAgdmFyIG9yaWdHZXRVc2VyTWVkaWEgPSBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYS5cbiAgICAgIGJpbmQobmF2aWdhdG9yLm1lZGlhRGV2aWNlcyk7XG4gIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhID0gZnVuY3Rpb24oYykge1xuICAgIHJldHVybiBvcmlnR2V0VXNlck1lZGlhKGMpLmNhdGNoKGZ1bmN0aW9uKGUpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChzaGltRXJyb3JfKGUpKTtcbiAgICB9KTtcbiAgfTtcbn07XG4iLCIvKlxuICogIENvcHlyaWdodCAoYykgMjAxNiBUaGUgV2ViUlRDIHByb2plY3QgYXV0aG9ycy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiAgVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYSBCU0Qtc3R5bGUgbGljZW5zZVxuICogIHRoYXQgY2FuIGJlIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3Qgb2YgdGhlIHNvdXJjZVxuICogIHRyZWUuXG4gKi9cbiAvKiBlc2xpbnQtZW52IG5vZGUgKi9cbid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWxzID0gcmVxdWlyZSgnLi4vdXRpbHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHNoaW1HZXRVc2VyTWVkaWE6IHJlcXVpcmUoJy4vZ2V0dXNlcm1lZGlhJyksXG4gIHNoaW1PblRyYWNrOiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcgJiYgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uICYmICEoJ29udHJhY2snIGluXG4gICAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUpKSB7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkod2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSwgJ29udHJhY2snLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuX29udHJhY2s7XG4gICAgICAgIH0sXG4gICAgICAgIHNldDogZnVuY3Rpb24oZikge1xuICAgICAgICAgIGlmICh0aGlzLl9vbnRyYWNrKSB7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RyYWNrJywgdGhpcy5fb250cmFjayk7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2FkZHN0cmVhbScsIHRoaXMuX29udHJhY2twb2x5KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCd0cmFjaycsIHRoaXMuX29udHJhY2sgPSBmKTtcbiAgICAgICAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ2FkZHN0cmVhbScsIHRoaXMuX29udHJhY2twb2x5ID0gZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgZS5zdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaChmdW5jdGlvbih0cmFjaykge1xuICAgICAgICAgICAgICB2YXIgZXZlbnQgPSBuZXcgRXZlbnQoJ3RyYWNrJyk7XG4gICAgICAgICAgICAgIGV2ZW50LnRyYWNrID0gdHJhY2s7XG4gICAgICAgICAgICAgIGV2ZW50LnJlY2VpdmVyID0ge3RyYWNrOiB0cmFja307XG4gICAgICAgICAgICAgIGV2ZW50LnRyYW5zY2VpdmVyID0ge3JlY2VpdmVyOiBldmVudC5yZWNlaXZlcn07XG4gICAgICAgICAgICAgIGV2ZW50LnN0cmVhbXMgPSBbZS5zdHJlYW1dO1xuICAgICAgICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgICAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgPT09ICdvYmplY3QnICYmIHdpbmRvdy5SVENUcmFja0V2ZW50ICYmXG4gICAgICAgICgncmVjZWl2ZXInIGluIHdpbmRvdy5SVENUcmFja0V2ZW50LnByb3RvdHlwZSkgJiZcbiAgICAgICAgISgndHJhbnNjZWl2ZXInIGluIHdpbmRvdy5SVENUcmFja0V2ZW50LnByb3RvdHlwZSkpIHtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh3aW5kb3cuUlRDVHJhY2tFdmVudC5wcm90b3R5cGUsICd0cmFuc2NlaXZlcicsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4ge3JlY2VpdmVyOiB0aGlzLnJlY2VpdmVyfTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9LFxuXG4gIHNoaW1Tb3VyY2VPYmplY3Q6IGZ1bmN0aW9uKHdpbmRvdykge1xuICAgIC8vIEZpcmVmb3ggaGFzIHN1cHBvcnRlZCBtb3pTcmNPYmplY3Qgc2luY2UgRkYyMiwgdW5wcmVmaXhlZCBpbiA0Mi5cbiAgICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGlmICh3aW5kb3cuSFRNTE1lZGlhRWxlbWVudCAmJlxuICAgICAgICAhKCdzcmNPYmplY3QnIGluIHdpbmRvdy5IVE1MTWVkaWFFbGVtZW50LnByb3RvdHlwZSkpIHtcbiAgICAgICAgLy8gU2hpbSB0aGUgc3JjT2JqZWN0IHByb3BlcnR5LCBvbmNlLCB3aGVuIEhUTUxNZWRpYUVsZW1lbnQgaXMgZm91bmQuXG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh3aW5kb3cuSFRNTE1lZGlhRWxlbWVudC5wcm90b3R5cGUsICdzcmNPYmplY3QnLCB7XG4gICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1velNyY09iamVjdDtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHNldDogZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICAgICAgICB0aGlzLm1velNyY09iamVjdCA9IHN0cmVhbTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfSxcblxuICBzaGltUGVlckNvbm5lY3Rpb246IGZ1bmN0aW9uKHdpbmRvdykge1xuICAgIHZhciBicm93c2VyRGV0YWlscyA9IHV0aWxzLmRldGVjdEJyb3dzZXIod2luZG93KTtcblxuICAgIGlmICh0eXBlb2Ygd2luZG93ICE9PSAnb2JqZWN0JyB8fCAhKHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiB8fFxuICAgICAgICB3aW5kb3cubW96UlRDUGVlckNvbm5lY3Rpb24pKSB7XG4gICAgICByZXR1cm47IC8vIHByb2JhYmx5IG1lZGlhLnBlZXJjb25uZWN0aW9uLmVuYWJsZWQ9ZmFsc2UgaW4gYWJvdXQ6Y29uZmlnXG4gICAgfVxuICAgIC8vIFRoZSBSVENQZWVyQ29ubmVjdGlvbiBvYmplY3QuXG4gICAgaWYgKCF3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24pIHtcbiAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiA9IGZ1bmN0aW9uKHBjQ29uZmlnLCBwY0NvbnN0cmFpbnRzKSB7XG4gICAgICAgIGlmIChicm93c2VyRGV0YWlscy52ZXJzaW9uIDwgMzgpIHtcbiAgICAgICAgICAvLyAudXJscyBpcyBub3Qgc3VwcG9ydGVkIGluIEZGIDwgMzguXG4gICAgICAgICAgLy8gY3JlYXRlIFJUQ0ljZVNlcnZlcnMgd2l0aCBhIHNpbmdsZSB1cmwuXG4gICAgICAgICAgaWYgKHBjQ29uZmlnICYmIHBjQ29uZmlnLmljZVNlcnZlcnMpIHtcbiAgICAgICAgICAgIHZhciBuZXdJY2VTZXJ2ZXJzID0gW107XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBjQ29uZmlnLmljZVNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgdmFyIHNlcnZlciA9IHBjQ29uZmlnLmljZVNlcnZlcnNbaV07XG4gICAgICAgICAgICAgIGlmIChzZXJ2ZXIuaGFzT3duUHJvcGVydHkoJ3VybHMnKSkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgc2VydmVyLnVybHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgIHZhciBuZXdTZXJ2ZXIgPSB7XG4gICAgICAgICAgICAgICAgICAgIHVybDogc2VydmVyLnVybHNbal1cbiAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICBpZiAoc2VydmVyLnVybHNbal0uaW5kZXhPZigndHVybicpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld1NlcnZlci51c2VybmFtZSA9IHNlcnZlci51c2VybmFtZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3U2VydmVyLmNyZWRlbnRpYWwgPSBzZXJ2ZXIuY3JlZGVudGlhbDtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIG5ld0ljZVNlcnZlcnMucHVzaChuZXdTZXJ2ZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBuZXdJY2VTZXJ2ZXJzLnB1c2gocGNDb25maWcuaWNlU2VydmVyc1tpXSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBjQ29uZmlnLmljZVNlcnZlcnMgPSBuZXdJY2VTZXJ2ZXJzO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IHdpbmRvdy5tb3pSVENQZWVyQ29ubmVjdGlvbihwY0NvbmZpZywgcGNDb25zdHJhaW50cyk7XG4gICAgICB9O1xuICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSA9XG4gICAgICAgICAgd2luZG93Lm1velJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZTtcblxuICAgICAgLy8gd3JhcCBzdGF0aWMgbWV0aG9kcy4gQ3VycmVudGx5IGp1c3QgZ2VuZXJhdGVDZXJ0aWZpY2F0ZS5cbiAgICAgIGlmICh3aW5kb3cubW96UlRDUGVlckNvbm5lY3Rpb24uZ2VuZXJhdGVDZXJ0aWZpY2F0ZSkge1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkod2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLCAnZ2VuZXJhdGVDZXJ0aWZpY2F0ZScsIHtcbiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIHdpbmRvdy5tb3pSVENQZWVyQ29ubmVjdGlvbi5nZW5lcmF0ZUNlcnRpZmljYXRlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHdpbmRvdy5SVENTZXNzaW9uRGVzY3JpcHRpb24gPSB3aW5kb3cubW96UlRDU2Vzc2lvbkRlc2NyaXB0aW9uO1xuICAgICAgd2luZG93LlJUQ0ljZUNhbmRpZGF0ZSA9IHdpbmRvdy5tb3pSVENJY2VDYW5kaWRhdGU7XG4gICAgfVxuXG4gICAgLy8gc2hpbSBhd2F5IG5lZWQgZm9yIG9ic29sZXRlIFJUQ0ljZUNhbmRpZGF0ZS9SVENTZXNzaW9uRGVzY3JpcHRpb24uXG4gICAgWydzZXRMb2NhbERlc2NyaXB0aW9uJywgJ3NldFJlbW90ZURlc2NyaXB0aW9uJywgJ2FkZEljZUNhbmRpZGF0ZSddXG4gICAgICAgIC5mb3JFYWNoKGZ1bmN0aW9uKG1ldGhvZCkge1xuICAgICAgICAgIHZhciBuYXRpdmVNZXRob2QgPSB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlW21ldGhvZF07XG4gICAgICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZVttZXRob2RdID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBhcmd1bWVudHNbMF0gPSBuZXcgKChtZXRob2QgPT09ICdhZGRJY2VDYW5kaWRhdGUnKSA/XG4gICAgICAgICAgICAgICAgd2luZG93LlJUQ0ljZUNhbmRpZGF0ZSA6XG4gICAgICAgICAgICAgICAgd2luZG93LlJUQ1Nlc3Npb25EZXNjcmlwdGlvbikoYXJndW1lbnRzWzBdKTtcbiAgICAgICAgICAgIHJldHVybiBuYXRpdmVNZXRob2QuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICB9O1xuICAgICAgICB9KTtcblxuICAgIC8vIHN1cHBvcnQgZm9yIGFkZEljZUNhbmRpZGF0ZShudWxsIG9yIHVuZGVmaW5lZClcbiAgICB2YXIgbmF0aXZlQWRkSWNlQ2FuZGlkYXRlID1cbiAgICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5hZGRJY2VDYW5kaWRhdGU7XG4gICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5hZGRJY2VDYW5kaWRhdGUgPSBmdW5jdGlvbigpIHtcbiAgICAgIGlmICghYXJndW1lbnRzWzBdKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHNbMV0pIHtcbiAgICAgICAgICBhcmd1bWVudHNbMV0uYXBwbHkobnVsbCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG5hdGl2ZUFkZEljZUNhbmRpZGF0ZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG5cbiAgICAvLyBzaGltIGdldFN0YXRzIHdpdGggbWFwbGlrZSBzdXBwb3J0XG4gICAgdmFyIG1ha2VNYXBTdGF0cyA9IGZ1bmN0aW9uKHN0YXRzKSB7XG4gICAgICB2YXIgbWFwID0gbmV3IE1hcCgpO1xuICAgICAgT2JqZWN0LmtleXMoc3RhdHMpLmZvckVhY2goZnVuY3Rpb24oa2V5KSB7XG4gICAgICAgIG1hcC5zZXQoa2V5LCBzdGF0c1trZXldKTtcbiAgICAgICAgbWFwW2tleV0gPSBzdGF0c1trZXldO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gbWFwO1xuICAgIH07XG5cbiAgICB2YXIgbW9kZXJuU3RhdHNUeXBlcyA9IHtcbiAgICAgIGluYm91bmRydHA6ICdpbmJvdW5kLXJ0cCcsXG4gICAgICBvdXRib3VuZHJ0cDogJ291dGJvdW5kLXJ0cCcsXG4gICAgICBjYW5kaWRhdGVwYWlyOiAnY2FuZGlkYXRlLXBhaXInLFxuICAgICAgbG9jYWxjYW5kaWRhdGU6ICdsb2NhbC1jYW5kaWRhdGUnLFxuICAgICAgcmVtb3RlY2FuZGlkYXRlOiAncmVtb3RlLWNhbmRpZGF0ZSdcbiAgICB9O1xuXG4gICAgdmFyIG5hdGl2ZUdldFN0YXRzID0gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5nZXRTdGF0cztcbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmdldFN0YXRzID0gZnVuY3Rpb24oXG4gICAgICBzZWxlY3RvcixcbiAgICAgIG9uU3VjYyxcbiAgICAgIG9uRXJyXG4gICAgKSB7XG4gICAgICByZXR1cm4gbmF0aXZlR2V0U3RhdHMuYXBwbHkodGhpcywgW3NlbGVjdG9yIHx8IG51bGxdKVxuICAgICAgICAudGhlbihmdW5jdGlvbihzdGF0cykge1xuICAgICAgICAgIGlmIChicm93c2VyRGV0YWlscy52ZXJzaW9uIDwgNDgpIHtcbiAgICAgICAgICAgIHN0YXRzID0gbWFrZU1hcFN0YXRzKHN0YXRzKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGJyb3dzZXJEZXRhaWxzLnZlcnNpb24gPCA1MyAmJiAhb25TdWNjKSB7XG4gICAgICAgICAgICAvLyBTaGltIG9ubHkgcHJvbWlzZSBnZXRTdGF0cyB3aXRoIHNwZWMtaHlwaGVucyBpbiB0eXBlIG5hbWVzXG4gICAgICAgICAgICAvLyBMZWF2ZSBjYWxsYmFjayB2ZXJzaW9uIGFsb25lOyBtaXNjIG9sZCB1c2VzIG9mIGZvckVhY2ggYmVmb3JlIE1hcFxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgc3RhdHMuZm9yRWFjaChmdW5jdGlvbihzdGF0KSB7XG4gICAgICAgICAgICAgICAgc3RhdC50eXBlID0gbW9kZXJuU3RhdHNUeXBlc1tzdGF0LnR5cGVdIHx8IHN0YXQudHlwZTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgIGlmIChlLm5hbWUgIT09ICdUeXBlRXJyb3InKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAvLyBBdm9pZCBUeXBlRXJyb3I6IFwidHlwZVwiIGlzIHJlYWQtb25seSwgaW4gb2xkIHZlcnNpb25zLiAzNC00M2lzaFxuICAgICAgICAgICAgICBzdGF0cy5mb3JFYWNoKGZ1bmN0aW9uKHN0YXQsIGkpIHtcbiAgICAgICAgICAgICAgICBzdGF0cy5zZXQoaSwgT2JqZWN0LmFzc2lnbih7fSwgc3RhdCwge1xuICAgICAgICAgICAgICAgICAgdHlwZTogbW9kZXJuU3RhdHNUeXBlc1tzdGF0LnR5cGVdIHx8IHN0YXQudHlwZVxuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBzdGF0cztcbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4ob25TdWNjLCBvbkVycik7XG4gICAgfTtcbiAgfSxcblxuICBzaGltUmVtb3ZlU3RyZWFtOiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICBpZiAoIXdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiB8fFxuICAgICAgICAncmVtb3ZlU3RyZWFtJyBpbiB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUucmVtb3ZlU3RyZWFtID0gZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICB2YXIgcGMgPSB0aGlzO1xuICAgICAgdXRpbHMuZGVwcmVjYXRlZCgncmVtb3ZlU3RyZWFtJywgJ3JlbW92ZVRyYWNrJyk7XG4gICAgICB0aGlzLmdldFNlbmRlcnMoKS5mb3JFYWNoKGZ1bmN0aW9uKHNlbmRlcikge1xuICAgICAgICBpZiAoc2VuZGVyLnRyYWNrICYmIHN0cmVhbS5nZXRUcmFja3MoKS5pbmRleE9mKHNlbmRlci50cmFjaykgIT09IC0xKSB7XG4gICAgICAgICAgcGMucmVtb3ZlVHJhY2soc2VuZGVyKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfTtcbiAgfVxufTtcbiIsIi8qXG4gKiAgQ29weXJpZ2h0IChjKSAyMDE2IFRoZSBXZWJSVEMgcHJvamVjdCBhdXRob3JzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqICBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhIEJTRC1zdHlsZSBsaWNlbnNlXG4gKiAgdGhhdCBjYW4gYmUgZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBvZiB0aGUgc291cmNlXG4gKiAgdHJlZS5cbiAqL1xuIC8qIGVzbGludC1lbnYgbm9kZSAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbHMgPSByZXF1aXJlKCcuLi91dGlscycpO1xudmFyIGxvZ2dpbmcgPSB1dGlscy5sb2c7XG5cbi8vIEV4cG9zZSBwdWJsaWMgbWV0aG9kcy5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24od2luZG93KSB7XG4gIHZhciBicm93c2VyRGV0YWlscyA9IHV0aWxzLmRldGVjdEJyb3dzZXIod2luZG93KTtcbiAgdmFyIG5hdmlnYXRvciA9IHdpbmRvdyAmJiB3aW5kb3cubmF2aWdhdG9yO1xuICB2YXIgTWVkaWFTdHJlYW1UcmFjayA9IHdpbmRvdyAmJiB3aW5kb3cuTWVkaWFTdHJlYW1UcmFjaztcblxuICB2YXIgc2hpbUVycm9yXyA9IGZ1bmN0aW9uKGUpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbmFtZToge1xuICAgICAgICBJbnRlcm5hbEVycm9yOiAnTm90UmVhZGFibGVFcnJvcicsXG4gICAgICAgIE5vdFN1cHBvcnRlZEVycm9yOiAnVHlwZUVycm9yJyxcbiAgICAgICAgUGVybWlzc2lvbkRlbmllZEVycm9yOiAnTm90QWxsb3dlZEVycm9yJyxcbiAgICAgICAgU2VjdXJpdHlFcnJvcjogJ05vdEFsbG93ZWRFcnJvcidcbiAgICAgIH1bZS5uYW1lXSB8fCBlLm5hbWUsXG4gICAgICBtZXNzYWdlOiB7XG4gICAgICAgICdUaGUgb3BlcmF0aW9uIGlzIGluc2VjdXJlLic6ICdUaGUgcmVxdWVzdCBpcyBub3QgYWxsb3dlZCBieSB0aGUgJyArXG4gICAgICAgICd1c2VyIGFnZW50IG9yIHRoZSBwbGF0Zm9ybSBpbiB0aGUgY3VycmVudCBjb250ZXh0LidcbiAgICAgIH1bZS5tZXNzYWdlXSB8fCBlLm1lc3NhZ2UsXG4gICAgICBjb25zdHJhaW50OiBlLmNvbnN0cmFpbnQsXG4gICAgICB0b1N0cmluZzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm5hbWUgKyAodGhpcy5tZXNzYWdlICYmICc6ICcpICsgdGhpcy5tZXNzYWdlO1xuICAgICAgfVxuICAgIH07XG4gIH07XG5cbiAgLy8gZ2V0VXNlck1lZGlhIGNvbnN0cmFpbnRzIHNoaW0uXG4gIHZhciBnZXRVc2VyTWVkaWFfID0gZnVuY3Rpb24oY29uc3RyYWludHMsIG9uU3VjY2Vzcywgb25FcnJvcikge1xuICAgIHZhciBjb25zdHJhaW50c1RvRkYzN18gPSBmdW5jdGlvbihjKSB7XG4gICAgICBpZiAodHlwZW9mIGMgIT09ICdvYmplY3QnIHx8IGMucmVxdWlyZSkge1xuICAgICAgICByZXR1cm4gYztcbiAgICAgIH1cbiAgICAgIHZhciByZXF1aXJlID0gW107XG4gICAgICBPYmplY3Qua2V5cyhjKS5mb3JFYWNoKGZ1bmN0aW9uKGtleSkge1xuICAgICAgICBpZiAoa2V5ID09PSAncmVxdWlyZScgfHwga2V5ID09PSAnYWR2YW5jZWQnIHx8IGtleSA9PT0gJ21lZGlhU291cmNlJykge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgciA9IGNba2V5XSA9ICh0eXBlb2YgY1trZXldID09PSAnb2JqZWN0JykgP1xuICAgICAgICAgICAgY1trZXldIDoge2lkZWFsOiBjW2tleV19O1xuICAgICAgICBpZiAoci5taW4gIT09IHVuZGVmaW5lZCB8fFxuICAgICAgICAgICAgci5tYXggIT09IHVuZGVmaW5lZCB8fCByLmV4YWN0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICByZXF1aXJlLnB1c2goa2V5KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoci5leGFjdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiByLmV4YWN0ID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgci4gbWluID0gci5tYXggPSByLmV4YWN0O1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjW2tleV0gPSByLmV4YWN0O1xuICAgICAgICAgIH1cbiAgICAgICAgICBkZWxldGUgci5leGFjdDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoci5pZGVhbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgYy5hZHZhbmNlZCA9IGMuYWR2YW5jZWQgfHwgW107XG4gICAgICAgICAgdmFyIG9jID0ge307XG4gICAgICAgICAgaWYgKHR5cGVvZiByLmlkZWFsID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgb2Nba2V5XSA9IHttaW46IHIuaWRlYWwsIG1heDogci5pZGVhbH07XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG9jW2tleV0gPSByLmlkZWFsO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjLmFkdmFuY2VkLnB1c2gob2MpO1xuICAgICAgICAgIGRlbGV0ZSByLmlkZWFsO1xuICAgICAgICAgIGlmICghT2JqZWN0LmtleXMocikubGVuZ3RoKSB7XG4gICAgICAgICAgICBkZWxldGUgY1trZXldO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBpZiAocmVxdWlyZS5sZW5ndGgpIHtcbiAgICAgICAgYy5yZXF1aXJlID0gcmVxdWlyZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBjO1xuICAgIH07XG4gICAgY29uc3RyYWludHMgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGNvbnN0cmFpbnRzKSk7XG4gICAgaWYgKGJyb3dzZXJEZXRhaWxzLnZlcnNpb24gPCAzOCkge1xuICAgICAgbG9nZ2luZygnc3BlYzogJyArIEpTT04uc3RyaW5naWZ5KGNvbnN0cmFpbnRzKSk7XG4gICAgICBpZiAoY29uc3RyYWludHMuYXVkaW8pIHtcbiAgICAgICAgY29uc3RyYWludHMuYXVkaW8gPSBjb25zdHJhaW50c1RvRkYzN18oY29uc3RyYWludHMuYXVkaW8pO1xuICAgICAgfVxuICAgICAgaWYgKGNvbnN0cmFpbnRzLnZpZGVvKSB7XG4gICAgICAgIGNvbnN0cmFpbnRzLnZpZGVvID0gY29uc3RyYWludHNUb0ZGMzdfKGNvbnN0cmFpbnRzLnZpZGVvKTtcbiAgICAgIH1cbiAgICAgIGxvZ2dpbmcoJ2ZmMzc6ICcgKyBKU09OLnN0cmluZ2lmeShjb25zdHJhaW50cykpO1xuICAgIH1cbiAgICByZXR1cm4gbmF2aWdhdG9yLm1vekdldFVzZXJNZWRpYShjb25zdHJhaW50cywgb25TdWNjZXNzLCBmdW5jdGlvbihlKSB7XG4gICAgICBvbkVycm9yKHNoaW1FcnJvcl8oZSkpO1xuICAgIH0pO1xuICB9O1xuXG4gIC8vIFJldHVybnMgdGhlIHJlc3VsdCBvZiBnZXRVc2VyTWVkaWEgYXMgYSBQcm9taXNlLlxuICB2YXIgZ2V0VXNlck1lZGlhUHJvbWlzZV8gPSBmdW5jdGlvbihjb25zdHJhaW50cykge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIGdldFVzZXJNZWRpYV8oY29uc3RyYWludHMsIHJlc29sdmUsIHJlamVjdCk7XG4gICAgfSk7XG4gIH07XG5cbiAgLy8gU2hpbSBmb3IgbWVkaWFEZXZpY2VzIG9uIG9sZGVyIHZlcnNpb25zLlxuICBpZiAoIW5hdmlnYXRvci5tZWRpYURldmljZXMpIHtcbiAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzID0ge2dldFVzZXJNZWRpYTogZ2V0VXNlck1lZGlhUHJvbWlzZV8sXG4gICAgICBhZGRFdmVudExpc3RlbmVyOiBmdW5jdGlvbigpIHsgfSxcbiAgICAgIHJlbW92ZUV2ZW50TGlzdGVuZXI6IGZ1bmN0aW9uKCkgeyB9XG4gICAgfTtcbiAgfVxuICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmVudW1lcmF0ZURldmljZXMgPVxuICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzIHx8IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSkge1xuICAgICAgICAgIHZhciBpbmZvcyA9IFtcbiAgICAgICAgICAgIHtraW5kOiAnYXVkaW9pbnB1dCcsIGRldmljZUlkOiAnZGVmYXVsdCcsIGxhYmVsOiAnJywgZ3JvdXBJZDogJyd9LFxuICAgICAgICAgICAge2tpbmQ6ICd2aWRlb2lucHV0JywgZGV2aWNlSWQ6ICdkZWZhdWx0JywgbGFiZWw6ICcnLCBncm91cElkOiAnJ31cbiAgICAgICAgICBdO1xuICAgICAgICAgIHJlc29sdmUoaW5mb3MpO1xuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgaWYgKGJyb3dzZXJEZXRhaWxzLnZlcnNpb24gPCA0MSkge1xuICAgIC8vIFdvcmsgYXJvdW5kIGh0dHA6Ly9idWd6aWwubGEvMTE2OTY2NVxuICAgIHZhciBvcmdFbnVtZXJhdGVEZXZpY2VzID1cbiAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzLmJpbmQobmF2aWdhdG9yLm1lZGlhRGV2aWNlcyk7XG4gICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gb3JnRW51bWVyYXRlRGV2aWNlcygpLnRoZW4odW5kZWZpbmVkLCBmdW5jdGlvbihlKSB7XG4gICAgICAgIGlmIChlLm5hbWUgPT09ICdOb3RGb3VuZEVycm9yJykge1xuICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlO1xuICAgICAgfSk7XG4gICAgfTtcbiAgfVxuICBpZiAoYnJvd3NlckRldGFpbHMudmVyc2lvbiA8IDQ5KSB7XG4gICAgdmFyIG9yaWdHZXRVc2VyTWVkaWEgPSBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYS5cbiAgICAgICAgYmluZChuYXZpZ2F0b3IubWVkaWFEZXZpY2VzKTtcbiAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSA9IGZ1bmN0aW9uKGMpIHtcbiAgICAgIHJldHVybiBvcmlnR2V0VXNlck1lZGlhKGMpLnRoZW4oZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICAgIC8vIFdvcmsgYXJvdW5kIGh0dHBzOi8vYnVnemlsLmxhLzgwMjMyNlxuICAgICAgICBpZiAoYy5hdWRpbyAmJiAhc3RyZWFtLmdldEF1ZGlvVHJhY2tzKCkubGVuZ3RoIHx8XG4gICAgICAgICAgICBjLnZpZGVvICYmICFzdHJlYW0uZ2V0VmlkZW9UcmFja3MoKS5sZW5ndGgpIHtcbiAgICAgICAgICBzdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaChmdW5jdGlvbih0cmFjaykge1xuICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIHRocm93IG5ldyBET01FeGNlcHRpb24oJ1RoZSBvYmplY3QgY2FuIG5vdCBiZSBmb3VuZCBoZXJlLicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnTm90Rm91bmRFcnJvcicpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdHJlYW07XG4gICAgICB9LCBmdW5jdGlvbihlKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChzaGltRXJyb3JfKGUpKTtcbiAgICAgIH0pO1xuICAgIH07XG4gIH1cbiAgaWYgKCEoYnJvd3NlckRldGFpbHMudmVyc2lvbiA+IDU1ICYmXG4gICAgICAnYXV0b0dhaW5Db250cm9sJyBpbiBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFN1cHBvcnRlZENvbnN0cmFpbnRzKCkpKSB7XG4gICAgdmFyIHJlbWFwID0gZnVuY3Rpb24ob2JqLCBhLCBiKSB7XG4gICAgICBpZiAoYSBpbiBvYmogJiYgIShiIGluIG9iaikpIHtcbiAgICAgICAgb2JqW2JdID0gb2JqW2FdO1xuICAgICAgICBkZWxldGUgb2JqW2FdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB2YXIgbmF0aXZlR2V0VXNlck1lZGlhID0gbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEuXG4gICAgICAgIGJpbmQobmF2aWdhdG9yLm1lZGlhRGV2aWNlcyk7XG4gICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEgPSBmdW5jdGlvbihjKSB7XG4gICAgICBpZiAodHlwZW9mIGMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBjLmF1ZGlvID09PSAnb2JqZWN0Jykge1xuICAgICAgICBjID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShjKSk7XG4gICAgICAgIHJlbWFwKGMuYXVkaW8sICdhdXRvR2FpbkNvbnRyb2wnLCAnbW96QXV0b0dhaW5Db250cm9sJyk7XG4gICAgICAgIHJlbWFwKGMuYXVkaW8sICdub2lzZVN1cHByZXNzaW9uJywgJ21vek5vaXNlU3VwcHJlc3Npb24nKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuYXRpdmVHZXRVc2VyTWVkaWEoYyk7XG4gICAgfTtcblxuICAgIGlmIChNZWRpYVN0cmVhbVRyYWNrICYmIE1lZGlhU3RyZWFtVHJhY2sucHJvdG90eXBlLmdldFNldHRpbmdzKSB7XG4gICAgICB2YXIgbmF0aXZlR2V0U2V0dGluZ3MgPSBNZWRpYVN0cmVhbVRyYWNrLnByb3RvdHlwZS5nZXRTZXR0aW5ncztcbiAgICAgIE1lZGlhU3RyZWFtVHJhY2sucHJvdG90eXBlLmdldFNldHRpbmdzID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBvYmogPSBuYXRpdmVHZXRTZXR0aW5ncy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICByZW1hcChvYmosICdtb3pBdXRvR2FpbkNvbnRyb2wnLCAnYXV0b0dhaW5Db250cm9sJyk7XG4gICAgICAgIHJlbWFwKG9iaiwgJ21vek5vaXNlU3VwcHJlc3Npb24nLCAnbm9pc2VTdXBwcmVzc2lvbicpO1xuICAgICAgICByZXR1cm4gb2JqO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAoTWVkaWFTdHJlYW1UcmFjayAmJiBNZWRpYVN0cmVhbVRyYWNrLnByb3RvdHlwZS5hcHBseUNvbnN0cmFpbnRzKSB7XG4gICAgICB2YXIgbmF0aXZlQXBwbHlDb25zdHJhaW50cyA9IE1lZGlhU3RyZWFtVHJhY2sucHJvdG90eXBlLmFwcGx5Q29uc3RyYWludHM7XG4gICAgICBNZWRpYVN0cmVhbVRyYWNrLnByb3RvdHlwZS5hcHBseUNvbnN0cmFpbnRzID0gZnVuY3Rpb24oYykge1xuICAgICAgICBpZiAodGhpcy5raW5kID09PSAnYXVkaW8nICYmIHR5cGVvZiBjID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgIGMgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGMpKTtcbiAgICAgICAgICByZW1hcChjLCAnYXV0b0dhaW5Db250cm9sJywgJ21vekF1dG9HYWluQ29udHJvbCcpO1xuICAgICAgICAgIHJlbWFwKGMsICdub2lzZVN1cHByZXNzaW9uJywgJ21vek5vaXNlU3VwcHJlc3Npb24nKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmF0aXZlQXBwbHlDb25zdHJhaW50cy5hcHBseSh0aGlzLCBbY10pO1xuICAgICAgfTtcbiAgICB9XG4gIH1cbiAgbmF2aWdhdG9yLmdldFVzZXJNZWRpYSA9IGZ1bmN0aW9uKGNvbnN0cmFpbnRzLCBvblN1Y2Nlc3MsIG9uRXJyb3IpIHtcbiAgICBpZiAoYnJvd3NlckRldGFpbHMudmVyc2lvbiA8IDQ0KSB7XG4gICAgICByZXR1cm4gZ2V0VXNlck1lZGlhXyhjb25zdHJhaW50cywgb25TdWNjZXNzLCBvbkVycm9yKTtcbiAgICB9XG4gICAgLy8gUmVwbGFjZSBGaXJlZm94IDQ0KydzIGRlcHJlY2F0aW9uIHdhcm5pbmcgd2l0aCB1bnByZWZpeGVkIHZlcnNpb24uXG4gICAgdXRpbHMuZGVwcmVjYXRlZCgnbmF2aWdhdG9yLmdldFVzZXJNZWRpYScsXG4gICAgICAgICduYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYScpO1xuICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzKS50aGVuKG9uU3VjY2Vzcywgb25FcnJvcik7XG4gIH07XG59O1xuIiwiLypcbiAqICBDb3B5cmlnaHQgKGMpIDIwMTYgVGhlIFdlYlJUQyBwcm9qZWN0IGF1dGhvcnMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGEgQlNELXN0eWxlIGxpY2Vuc2VcbiAqICB0aGF0IGNhbiBiZSBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGluIHRoZSByb290IG9mIHRoZSBzb3VyY2VcbiAqICB0cmVlLlxuICovXG4ndXNlIHN0cmljdCc7XG52YXIgdXRpbHMgPSByZXF1aXJlKCcuLi91dGlscycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgc2hpbUxvY2FsU3RyZWFtc0FQSTogZnVuY3Rpb24od2luZG93KSB7XG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICdvYmplY3QnIHx8ICF3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKCEoJ2dldExvY2FsU3RyZWFtcycgaW4gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSkpIHtcbiAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuZ2V0TG9jYWxTdHJlYW1zID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICghdGhpcy5fbG9jYWxTdHJlYW1zKSB7XG4gICAgICAgICAgdGhpcy5fbG9jYWxTdHJlYW1zID0gW107XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX2xvY2FsU3RyZWFtcztcbiAgICAgIH07XG4gICAgfVxuICAgIGlmICghKCdnZXRTdHJlYW1CeUlkJyBpbiB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlKSkge1xuICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5nZXRTdHJlYW1CeUlkID0gZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IG51bGw7XG4gICAgICAgIGlmICh0aGlzLl9sb2NhbFN0cmVhbXMpIHtcbiAgICAgICAgICB0aGlzLl9sb2NhbFN0cmVhbXMuZm9yRWFjaChmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgICAgIGlmIChzdHJlYW0uaWQgPT09IGlkKSB7XG4gICAgICAgICAgICAgIHJlc3VsdCA9IHN0cmVhbTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5fcmVtb3RlU3RyZWFtcykge1xuICAgICAgICAgIHRoaXMuX3JlbW90ZVN0cmVhbXMuZm9yRWFjaChmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgICAgIGlmIChzdHJlYW0uaWQgPT09IGlkKSB7XG4gICAgICAgICAgICAgIHJlc3VsdCA9IHN0cmVhbTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfTtcbiAgICB9XG4gICAgaWYgKCEoJ2FkZFN0cmVhbScgaW4gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSkpIHtcbiAgICAgIHZhciBfYWRkVHJhY2sgPSB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmFkZFRyYWNrO1xuICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5hZGRTdHJlYW0gPSBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgaWYgKCF0aGlzLl9sb2NhbFN0cmVhbXMpIHtcbiAgICAgICAgICB0aGlzLl9sb2NhbFN0cmVhbXMgPSBbXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5fbG9jYWxTdHJlYW1zLmluZGV4T2Yoc3RyZWFtKSA9PT0gLTEpIHtcbiAgICAgICAgICB0aGlzLl9sb2NhbFN0cmVhbXMucHVzaChzdHJlYW0pO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwYyA9IHRoaXM7XG4gICAgICAgIHN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKGZ1bmN0aW9uKHRyYWNrKSB7XG4gICAgICAgICAgX2FkZFRyYWNrLmNhbGwocGMsIHRyYWNrLCBzdHJlYW0pO1xuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuYWRkVHJhY2sgPSBmdW5jdGlvbih0cmFjaywgc3RyZWFtKSB7XG4gICAgICAgIGlmIChzdHJlYW0pIHtcbiAgICAgICAgICBpZiAoIXRoaXMuX2xvY2FsU3RyZWFtcykge1xuICAgICAgICAgICAgdGhpcy5fbG9jYWxTdHJlYW1zID0gW3N0cmVhbV07XG4gICAgICAgICAgfSBlbHNlIGlmICh0aGlzLl9sb2NhbFN0cmVhbXMuaW5kZXhPZihzdHJlYW0pID09PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5fbG9jYWxTdHJlYW1zLnB1c2goc3RyZWFtKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIF9hZGRUcmFjay5jYWxsKHRoaXMsIHRyYWNrLCBzdHJlYW0pO1xuICAgICAgfTtcbiAgICB9XG4gICAgaWYgKCEoJ3JlbW92ZVN0cmVhbScgaW4gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSkpIHtcbiAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUucmVtb3ZlU3RyZWFtID0gZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICAgIGlmICghdGhpcy5fbG9jYWxTdHJlYW1zKSB7XG4gICAgICAgICAgdGhpcy5fbG9jYWxTdHJlYW1zID0gW107XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGluZGV4ID0gdGhpcy5fbG9jYWxTdHJlYW1zLmluZGV4T2Yoc3RyZWFtKTtcbiAgICAgICAgaWYgKGluZGV4ID09PSAtMSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9sb2NhbFN0cmVhbXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgdmFyIHBjID0gdGhpcztcbiAgICAgICAgdmFyIHRyYWNrcyA9IHN0cmVhbS5nZXRUcmFja3MoKTtcbiAgICAgICAgdGhpcy5nZXRTZW5kZXJzKCkuZm9yRWFjaChmdW5jdGlvbihzZW5kZXIpIHtcbiAgICAgICAgICBpZiAodHJhY2tzLmluZGV4T2Yoc2VuZGVyLnRyYWNrKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHBjLnJlbW92ZVRyYWNrKHNlbmRlcik7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgfVxuICB9LFxuICBzaGltUmVtb3RlU3RyZWFtc0FQSTogZnVuY3Rpb24od2luZG93KSB7XG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICdvYmplY3QnIHx8ICF3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKCEoJ2dldFJlbW90ZVN0cmVhbXMnIGluIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUpKSB7XG4gICAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmdldFJlbW90ZVN0cmVhbXMgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3JlbW90ZVN0cmVhbXMgPyB0aGlzLl9yZW1vdGVTdHJlYW1zIDogW107XG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAoISgnb25hZGRzdHJlYW0nIGluIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUpKSB7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkod2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSwgJ29uYWRkc3RyZWFtJywge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHJldHVybiB0aGlzLl9vbmFkZHN0cmVhbTtcbiAgICAgICAgfSxcbiAgICAgICAgc2V0OiBmdW5jdGlvbihmKSB7XG4gICAgICAgICAgdmFyIHBjID0gdGhpcztcbiAgICAgICAgICBpZiAodGhpcy5fb25hZGRzdHJlYW0pIHtcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcignYWRkc3RyZWFtJywgdGhpcy5fb25hZGRzdHJlYW0pO1xuICAgICAgICAgICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKCd0cmFjaycsIHRoaXMuX29uYWRkc3RyZWFtcG9seSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcignYWRkc3RyZWFtJywgdGhpcy5fb25hZGRzdHJlYW0gPSBmKTtcbiAgICAgICAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ3RyYWNrJywgdGhpcy5fb25hZGRzdHJlYW1wb2x5ID0gZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgZS5zdHJlYW1zLmZvckVhY2goZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICAgICAgICAgIGlmICghcGMuX3JlbW90ZVN0cmVhbXMpIHtcbiAgICAgICAgICAgICAgICBwYy5fcmVtb3RlU3RyZWFtcyA9IFtdO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChwYy5fcmVtb3RlU3RyZWFtcy5pbmRleE9mKHN0cmVhbSkgPj0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBwYy5fcmVtb3RlU3RyZWFtcy5wdXNoKHN0cmVhbSk7XG4gICAgICAgICAgICAgIHZhciBldmVudCA9IG5ldyBFdmVudCgnYWRkc3RyZWFtJyk7XG4gICAgICAgICAgICAgIGV2ZW50LnN0cmVhbSA9IHN0cmVhbTtcbiAgICAgICAgICAgICAgcGMuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9LFxuICBzaGltQ2FsbGJhY2tzQVBJOiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ29iamVjdCcgfHwgIXdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB2YXIgcHJvdG90eXBlID0gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZTtcbiAgICB2YXIgY3JlYXRlT2ZmZXIgPSBwcm90b3R5cGUuY3JlYXRlT2ZmZXI7XG4gICAgdmFyIGNyZWF0ZUFuc3dlciA9IHByb3RvdHlwZS5jcmVhdGVBbnN3ZXI7XG4gICAgdmFyIHNldExvY2FsRGVzY3JpcHRpb24gPSBwcm90b3R5cGUuc2V0TG9jYWxEZXNjcmlwdGlvbjtcbiAgICB2YXIgc2V0UmVtb3RlRGVzY3JpcHRpb24gPSBwcm90b3R5cGUuc2V0UmVtb3RlRGVzY3JpcHRpb247XG4gICAgdmFyIGFkZEljZUNhbmRpZGF0ZSA9IHByb3RvdHlwZS5hZGRJY2VDYW5kaWRhdGU7XG5cbiAgICBwcm90b3R5cGUuY3JlYXRlT2ZmZXIgPSBmdW5jdGlvbihzdWNjZXNzQ2FsbGJhY2ssIGZhaWx1cmVDYWxsYmFjaykge1xuICAgICAgdmFyIG9wdGlvbnMgPSAoYXJndW1lbnRzLmxlbmd0aCA+PSAyKSA/IGFyZ3VtZW50c1syXSA6IGFyZ3VtZW50c1swXTtcbiAgICAgIHZhciBwcm9taXNlID0gY3JlYXRlT2ZmZXIuYXBwbHkodGhpcywgW29wdGlvbnNdKTtcbiAgICAgIGlmICghZmFpbHVyZUNhbGxiYWNrKSB7XG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgICAgfVxuICAgICAgcHJvbWlzZS50aGVuKHN1Y2Nlc3NDYWxsYmFjaywgZmFpbHVyZUNhbGxiYWNrKTtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9O1xuXG4gICAgcHJvdG90eXBlLmNyZWF0ZUFuc3dlciA9IGZ1bmN0aW9uKHN1Y2Nlc3NDYWxsYmFjaywgZmFpbHVyZUNhbGxiYWNrKSB7XG4gICAgICB2YXIgb3B0aW9ucyA9IChhcmd1bWVudHMubGVuZ3RoID49IDIpID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzBdO1xuICAgICAgdmFyIHByb21pc2UgPSBjcmVhdGVBbnN3ZXIuYXBwbHkodGhpcywgW29wdGlvbnNdKTtcbiAgICAgIGlmICghZmFpbHVyZUNhbGxiYWNrKSB7XG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgICAgfVxuICAgICAgcHJvbWlzZS50aGVuKHN1Y2Nlc3NDYWxsYmFjaywgZmFpbHVyZUNhbGxiYWNrKTtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9O1xuXG4gICAgdmFyIHdpdGhDYWxsYmFjayA9IGZ1bmN0aW9uKGRlc2NyaXB0aW9uLCBzdWNjZXNzQ2FsbGJhY2ssIGZhaWx1cmVDYWxsYmFjaykge1xuICAgICAgdmFyIHByb21pc2UgPSBzZXRMb2NhbERlc2NyaXB0aW9uLmFwcGx5KHRoaXMsIFtkZXNjcmlwdGlvbl0pO1xuICAgICAgaWYgKCFmYWlsdXJlQ2FsbGJhY2spIHtcbiAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgICB9XG4gICAgICBwcm9taXNlLnRoZW4oc3VjY2Vzc0NhbGxiYWNrLCBmYWlsdXJlQ2FsbGJhY2spO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH07XG4gICAgcHJvdG90eXBlLnNldExvY2FsRGVzY3JpcHRpb24gPSB3aXRoQ2FsbGJhY2s7XG5cbiAgICB3aXRoQ2FsbGJhY2sgPSBmdW5jdGlvbihkZXNjcmlwdGlvbiwgc3VjY2Vzc0NhbGxiYWNrLCBmYWlsdXJlQ2FsbGJhY2spIHtcbiAgICAgIHZhciBwcm9taXNlID0gc2V0UmVtb3RlRGVzY3JpcHRpb24uYXBwbHkodGhpcywgW2Rlc2NyaXB0aW9uXSk7XG4gICAgICBpZiAoIWZhaWx1cmVDYWxsYmFjaykge1xuICAgICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICAgIH1cbiAgICAgIHByb21pc2UudGhlbihzdWNjZXNzQ2FsbGJhY2ssIGZhaWx1cmVDYWxsYmFjayk7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfTtcbiAgICBwcm90b3R5cGUuc2V0UmVtb3RlRGVzY3JpcHRpb24gPSB3aXRoQ2FsbGJhY2s7XG5cbiAgICB3aXRoQ2FsbGJhY2sgPSBmdW5jdGlvbihjYW5kaWRhdGUsIHN1Y2Nlc3NDYWxsYmFjaywgZmFpbHVyZUNhbGxiYWNrKSB7XG4gICAgICB2YXIgcHJvbWlzZSA9IGFkZEljZUNhbmRpZGF0ZS5hcHBseSh0aGlzLCBbY2FuZGlkYXRlXSk7XG4gICAgICBpZiAoIWZhaWx1cmVDYWxsYmFjaykge1xuICAgICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICAgIH1cbiAgICAgIHByb21pc2UudGhlbihzdWNjZXNzQ2FsbGJhY2ssIGZhaWx1cmVDYWxsYmFjayk7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfTtcbiAgICBwcm90b3R5cGUuYWRkSWNlQ2FuZGlkYXRlID0gd2l0aENhbGxiYWNrO1xuICB9LFxuICBzaGltR2V0VXNlck1lZGlhOiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICB2YXIgbmF2aWdhdG9yID0gd2luZG93ICYmIHdpbmRvdy5uYXZpZ2F0b3I7XG5cbiAgICBpZiAoIW5hdmlnYXRvci5nZXRVc2VyTWVkaWEpIHtcbiAgICAgIGlmIChuYXZpZ2F0b3Iud2Via2l0R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIG5hdmlnYXRvci5nZXRVc2VyTWVkaWEgPSBuYXZpZ2F0b3Iud2Via2l0R2V0VXNlck1lZGlhLmJpbmQobmF2aWdhdG9yKTtcbiAgICAgIH0gZWxzZSBpZiAobmF2aWdhdG9yLm1lZGlhRGV2aWNlcyAmJlxuICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKSB7XG4gICAgICAgIG5hdmlnYXRvci5nZXRVc2VyTWVkaWEgPSBmdW5jdGlvbihjb25zdHJhaW50cywgY2IsIGVycmNiKSB7XG4gICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoY29uc3RyYWludHMpXG4gICAgICAgICAgLnRoZW4oY2IsIGVycmNiKTtcbiAgICAgICAgfS5iaW5kKG5hdmlnYXRvcik7XG4gICAgICB9XG4gICAgfVxuICB9LFxuICBzaGltUlRDSWNlU2VydmVyVXJsczogZnVuY3Rpb24od2luZG93KSB7XG4gICAgLy8gbWlncmF0ZSBmcm9tIG5vbi1zcGVjIFJUQ0ljZVNlcnZlci51cmwgdG8gUlRDSWNlU2VydmVyLnVybHNcbiAgICB2YXIgT3JpZ1BlZXJDb25uZWN0aW9uID0gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uO1xuICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiA9IGZ1bmN0aW9uKHBjQ29uZmlnLCBwY0NvbnN0cmFpbnRzKSB7XG4gICAgICBpZiAocGNDb25maWcgJiYgcGNDb25maWcuaWNlU2VydmVycykge1xuICAgICAgICB2YXIgbmV3SWNlU2VydmVycyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBjQ29uZmlnLmljZVNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICB2YXIgc2VydmVyID0gcGNDb25maWcuaWNlU2VydmVyc1tpXTtcbiAgICAgICAgICBpZiAoIXNlcnZlci5oYXNPd25Qcm9wZXJ0eSgndXJscycpICYmXG4gICAgICAgICAgICAgIHNlcnZlci5oYXNPd25Qcm9wZXJ0eSgndXJsJykpIHtcbiAgICAgICAgICAgIHV0aWxzLmRlcHJlY2F0ZWQoJ1JUQ0ljZVNlcnZlci51cmwnLCAnUlRDSWNlU2VydmVyLnVybHMnKTtcbiAgICAgICAgICAgIHNlcnZlciA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoc2VydmVyKSk7XG4gICAgICAgICAgICBzZXJ2ZXIudXJscyA9IHNlcnZlci51cmw7XG4gICAgICAgICAgICBkZWxldGUgc2VydmVyLnVybDtcbiAgICAgICAgICAgIG5ld0ljZVNlcnZlcnMucHVzaChzZXJ2ZXIpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBuZXdJY2VTZXJ2ZXJzLnB1c2gocGNDb25maWcuaWNlU2VydmVyc1tpXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHBjQ29uZmlnLmljZVNlcnZlcnMgPSBuZXdJY2VTZXJ2ZXJzO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG5ldyBPcmlnUGVlckNvbm5lY3Rpb24ocGNDb25maWcsIHBjQ29uc3RyYWludHMpO1xuICAgIH07XG4gICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSA9IE9yaWdQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGU7XG4gICAgLy8gd3JhcCBzdGF0aWMgbWV0aG9kcy4gQ3VycmVudGx5IGp1c3QgZ2VuZXJhdGVDZXJ0aWZpY2F0ZS5cbiAgICBpZiAoJ2dlbmVyYXRlQ2VydGlmaWNhdGUnIGluIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbikge1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiwgJ2dlbmVyYXRlQ2VydGlmaWNhdGUnLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIE9yaWdQZWVyQ29ubmVjdGlvbi5nZW5lcmF0ZUNlcnRpZmljYXRlO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH0sXG4gIHNoaW1UcmFja0V2ZW50VHJhbnNjZWl2ZXI6IGZ1bmN0aW9uKHdpbmRvdykge1xuICAgIC8vIEFkZCBldmVudC50cmFuc2NlaXZlciBtZW1iZXIgb3ZlciBkZXByZWNhdGVkIGV2ZW50LnJlY2VpdmVyXG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgPT09ICdvYmplY3QnICYmIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiAmJlxuICAgICAgICAoJ3JlY2VpdmVyJyBpbiB3aW5kb3cuUlRDVHJhY2tFdmVudC5wcm90b3R5cGUpICYmXG4gICAgICAgIC8vIGNhbid0IGNoZWNrICd0cmFuc2NlaXZlcicgaW4gd2luZG93LlJUQ1RyYWNrRXZlbnQucHJvdG90eXBlLCBhcyBpdCBpc1xuICAgICAgICAvLyBkZWZpbmVkIGZvciBzb21lIHJlYXNvbiBldmVuIHdoZW4gd2luZG93LlJUQ1RyYW5zY2VpdmVyIGlzIG5vdC5cbiAgICAgICAgIXdpbmRvdy5SVENUcmFuc2NlaXZlcikge1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHdpbmRvdy5SVENUcmFja0V2ZW50LnByb3RvdHlwZSwgJ3RyYW5zY2VpdmVyJywge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHJldHVybiB7cmVjZWl2ZXI6IHRoaXMucmVjZWl2ZXJ9O1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH0sXG5cbiAgc2hpbUNyZWF0ZU9mZmVyTGVnYWN5OiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICB2YXIgb3JpZ0NyZWF0ZU9mZmVyID0gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5jcmVhdGVPZmZlcjtcbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmNyZWF0ZU9mZmVyID0gZnVuY3Rpb24ob2ZmZXJPcHRpb25zKSB7XG4gICAgICB2YXIgcGMgPSB0aGlzO1xuICAgICAgaWYgKG9mZmVyT3B0aW9ucykge1xuICAgICAgICB2YXIgYXVkaW9UcmFuc2NlaXZlciA9IHBjLmdldFRyYW5zY2VpdmVycygpLmZpbmQoZnVuY3Rpb24odHJhbnNjZWl2ZXIpIHtcbiAgICAgICAgICByZXR1cm4gdHJhbnNjZWl2ZXIuc2VuZGVyLnRyYWNrICYmXG4gICAgICAgICAgICAgIHRyYW5zY2VpdmVyLnNlbmRlci50cmFjay5raW5kID09PSAnYXVkaW8nO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKG9mZmVyT3B0aW9ucy5vZmZlclRvUmVjZWl2ZUF1ZGlvID09PSBmYWxzZSAmJiBhdWRpb1RyYW5zY2VpdmVyKSB7XG4gICAgICAgICAgaWYgKGF1ZGlvVHJhbnNjZWl2ZXIuZGlyZWN0aW9uID09PSAnc2VuZHJlY3YnKSB7XG4gICAgICAgICAgICBpZiAoYXVkaW9UcmFuc2NlaXZlci5zZXREaXJlY3Rpb24pIHtcbiAgICAgICAgICAgICAgYXVkaW9UcmFuc2NlaXZlci5zZXREaXJlY3Rpb24oJ3NlbmRvbmx5Jyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBhdWRpb1RyYW5zY2VpdmVyLmRpcmVjdGlvbiA9ICdzZW5kb25seSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIGlmIChhdWRpb1RyYW5zY2VpdmVyLmRpcmVjdGlvbiA9PT0gJ3JlY3Zvbmx5Jykge1xuICAgICAgICAgICAgaWYgKGF1ZGlvVHJhbnNjZWl2ZXIuc2V0RGlyZWN0aW9uKSB7XG4gICAgICAgICAgICAgIGF1ZGlvVHJhbnNjZWl2ZXIuc2V0RGlyZWN0aW9uKCdpbmFjdGl2ZScpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgYXVkaW9UcmFuc2NlaXZlci5kaXJlY3Rpb24gPSAnaW5hY3RpdmUnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChvZmZlck9wdGlvbnMub2ZmZXJUb1JlY2VpdmVBdWRpbyA9PT0gdHJ1ZSAmJlxuICAgICAgICAgICAgIWF1ZGlvVHJhbnNjZWl2ZXIpIHtcbiAgICAgICAgICBwYy5hZGRUcmFuc2NlaXZlcignYXVkaW8nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB2aWRlb1RyYW5zY2VpdmVyID0gcGMuZ2V0VHJhbnNjZWl2ZXJzKCkuZmluZChmdW5jdGlvbih0cmFuc2NlaXZlcikge1xuICAgICAgICAgIHJldHVybiB0cmFuc2NlaXZlci5zZW5kZXIudHJhY2sgJiZcbiAgICAgICAgICAgICAgdHJhbnNjZWl2ZXIuc2VuZGVyLnRyYWNrLmtpbmQgPT09ICd2aWRlbyc7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAob2ZmZXJPcHRpb25zLm9mZmVyVG9SZWNlaXZlVmlkZW8gPT09IGZhbHNlICYmIHZpZGVvVHJhbnNjZWl2ZXIpIHtcbiAgICAgICAgICBpZiAodmlkZW9UcmFuc2NlaXZlci5kaXJlY3Rpb24gPT09ICdzZW5kcmVjdicpIHtcbiAgICAgICAgICAgIHZpZGVvVHJhbnNjZWl2ZXIuc2V0RGlyZWN0aW9uKCdzZW5kb25seScpO1xuICAgICAgICAgIH0gZWxzZSBpZiAodmlkZW9UcmFuc2NlaXZlci5kaXJlY3Rpb24gPT09ICdyZWN2b25seScpIHtcbiAgICAgICAgICAgIHZpZGVvVHJhbnNjZWl2ZXIuc2V0RGlyZWN0aW9uKCdpbmFjdGl2ZScpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChvZmZlck9wdGlvbnMub2ZmZXJUb1JlY2VpdmVWaWRlbyA9PT0gdHJ1ZSAmJlxuICAgICAgICAgICAgIXZpZGVvVHJhbnNjZWl2ZXIpIHtcbiAgICAgICAgICBwYy5hZGRUcmFuc2NlaXZlcigndmlkZW8nKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIG9yaWdDcmVhdGVPZmZlci5hcHBseShwYywgYXJndW1lbnRzKTtcbiAgICB9O1xuICB9XG59O1xuIiwiLypcbiAqICBDb3B5cmlnaHQgKGMpIDIwMTYgVGhlIFdlYlJUQyBwcm9qZWN0IGF1dGhvcnMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGEgQlNELXN0eWxlIGxpY2Vuc2VcbiAqICB0aGF0IGNhbiBiZSBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGluIHRoZSByb290IG9mIHRoZSBzb3VyY2VcbiAqICB0cmVlLlxuICovXG4gLyogZXNsaW50LWVudiBub2RlICovXG4ndXNlIHN0cmljdCc7XG5cbnZhciBsb2dEaXNhYmxlZF8gPSB0cnVlO1xudmFyIGRlcHJlY2F0aW9uV2FybmluZ3NfID0gdHJ1ZTtcblxuLyoqXG4gKiBFeHRyYWN0IGJyb3dzZXIgdmVyc2lvbiBvdXQgb2YgdGhlIHByb3ZpZGVkIHVzZXIgYWdlbnQgc3RyaW5nLlxuICpcbiAqIEBwYXJhbSB7IXN0cmluZ30gdWFzdHJpbmcgdXNlckFnZW50IHN0cmluZy5cbiAqIEBwYXJhbSB7IXN0cmluZ30gZXhwciBSZWd1bGFyIGV4cHJlc3Npb24gdXNlZCBhcyBtYXRjaCBjcml0ZXJpYS5cbiAqIEBwYXJhbSB7IW51bWJlcn0gcG9zIHBvc2l0aW9uIGluIHRoZSB2ZXJzaW9uIHN0cmluZyB0byBiZSByZXR1cm5lZC5cbiAqIEByZXR1cm4geyFudW1iZXJ9IGJyb3dzZXIgdmVyc2lvbi5cbiAqL1xuZnVuY3Rpb24gZXh0cmFjdFZlcnNpb24odWFzdHJpbmcsIGV4cHIsIHBvcykge1xuICB2YXIgbWF0Y2ggPSB1YXN0cmluZy5tYXRjaChleHByKTtcbiAgcmV0dXJuIG1hdGNoICYmIG1hdGNoLmxlbmd0aCA+PSBwb3MgJiYgcGFyc2VJbnQobWF0Y2hbcG9zXSwgMTApO1xufVxuXG4vLyBXcmFwcyB0aGUgcGVlcmNvbm5lY3Rpb24gZXZlbnQgZXZlbnROYW1lVG9XcmFwIGluIGEgZnVuY3Rpb25cbi8vIHdoaWNoIHJldHVybnMgdGhlIG1vZGlmaWVkIGV2ZW50IG9iamVjdC5cbmZ1bmN0aW9uIHdyYXBQZWVyQ29ubmVjdGlvbkV2ZW50KHdpbmRvdywgZXZlbnROYW1lVG9XcmFwLCB3cmFwcGVyKSB7XG4gIGlmICghd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHZhciBwcm90byA9IHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGU7XG4gIHZhciBuYXRpdmVBZGRFdmVudExpc3RlbmVyID0gcHJvdG8uYWRkRXZlbnRMaXN0ZW5lcjtcbiAgcHJvdG8uYWRkRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uKG5hdGl2ZUV2ZW50TmFtZSwgY2IpIHtcbiAgICBpZiAobmF0aXZlRXZlbnROYW1lICE9PSBldmVudE5hbWVUb1dyYXApIHtcbiAgICAgIHJldHVybiBuYXRpdmVBZGRFdmVudExpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICAgIHZhciB3cmFwcGVkQ2FsbGJhY2sgPSBmdW5jdGlvbihlKSB7XG4gICAgICBjYih3cmFwcGVyKGUpKTtcbiAgICB9O1xuICAgIHRoaXMuX2V2ZW50TWFwID0gdGhpcy5fZXZlbnRNYXAgfHwge307XG4gICAgdGhpcy5fZXZlbnRNYXBbY2JdID0gd3JhcHBlZENhbGxiYWNrO1xuICAgIHJldHVybiBuYXRpdmVBZGRFdmVudExpc3RlbmVyLmFwcGx5KHRoaXMsIFtuYXRpdmVFdmVudE5hbWUsXG4gICAgICB3cmFwcGVkQ2FsbGJhY2tdKTtcbiAgfTtcblxuICB2YXIgbmF0aXZlUmVtb3ZlRXZlbnRMaXN0ZW5lciA9IHByb3RvLnJlbW92ZUV2ZW50TGlzdGVuZXI7XG4gIHByb3RvLnJlbW92ZUV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbihuYXRpdmVFdmVudE5hbWUsIGNiKSB7XG4gICAgaWYgKG5hdGl2ZUV2ZW50TmFtZSAhPT0gZXZlbnROYW1lVG9XcmFwIHx8ICF0aGlzLl9ldmVudE1hcFxuICAgICAgICB8fCAhdGhpcy5fZXZlbnRNYXBbY2JdKSB7XG4gICAgICByZXR1cm4gbmF0aXZlUmVtb3ZlRXZlbnRMaXN0ZW5lci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgICB2YXIgdW53cmFwcGVkQ2IgPSB0aGlzLl9ldmVudE1hcFtjYl07XG4gICAgZGVsZXRlIHRoaXMuX2V2ZW50TWFwW2NiXTtcbiAgICByZXR1cm4gbmF0aXZlUmVtb3ZlRXZlbnRMaXN0ZW5lci5hcHBseSh0aGlzLCBbbmF0aXZlRXZlbnROYW1lLFxuICAgICAgdW53cmFwcGVkQ2JdKTtcbiAgfTtcblxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkocHJvdG8sICdvbicgKyBldmVudE5hbWVUb1dyYXAsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXNbJ19vbicgKyBldmVudE5hbWVUb1dyYXBdO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbihjYikge1xuICAgICAgaWYgKHRoaXNbJ19vbicgKyBldmVudE5hbWVUb1dyYXBdKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE5hbWVUb1dyYXAsXG4gICAgICAgICAgICB0aGlzWydfb24nICsgZXZlbnROYW1lVG9XcmFwXSk7XG4gICAgICAgIGRlbGV0ZSB0aGlzWydfb24nICsgZXZlbnROYW1lVG9XcmFwXTtcbiAgICAgIH1cbiAgICAgIGlmIChjYikge1xuICAgICAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoZXZlbnROYW1lVG9XcmFwLFxuICAgICAgICAgICAgdGhpc1snX29uJyArIGV2ZW50TmFtZVRvV3JhcF0gPSBjYik7XG4gICAgICB9XG4gICAgfVxuICB9KTtcbn1cblxuLy8gVXRpbGl0eSBtZXRob2RzLlxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGV4dHJhY3RWZXJzaW9uOiBleHRyYWN0VmVyc2lvbixcbiAgd3JhcFBlZXJDb25uZWN0aW9uRXZlbnQ6IHdyYXBQZWVyQ29ubmVjdGlvbkV2ZW50LFxuICBkaXNhYmxlTG9nOiBmdW5jdGlvbihib29sKSB7XG4gICAgaWYgKHR5cGVvZiBib29sICE9PSAnYm9vbGVhbicpIHtcbiAgICAgIHJldHVybiBuZXcgRXJyb3IoJ0FyZ3VtZW50IHR5cGU6ICcgKyB0eXBlb2YgYm9vbCArXG4gICAgICAgICAgJy4gUGxlYXNlIHVzZSBhIGJvb2xlYW4uJyk7XG4gICAgfVxuICAgIGxvZ0Rpc2FibGVkXyA9IGJvb2w7XG4gICAgcmV0dXJuIChib29sKSA/ICdhZGFwdGVyLmpzIGxvZ2dpbmcgZGlzYWJsZWQnIDpcbiAgICAgICAgJ2FkYXB0ZXIuanMgbG9nZ2luZyBlbmFibGVkJztcbiAgfSxcblxuICAvKipcbiAgICogRGlzYWJsZSBvciBlbmFibGUgZGVwcmVjYXRpb24gd2FybmluZ3NcbiAgICogQHBhcmFtIHshYm9vbGVhbn0gYm9vbCBzZXQgdG8gdHJ1ZSB0byBkaXNhYmxlIHdhcm5pbmdzLlxuICAgKi9cbiAgZGlzYWJsZVdhcm5pbmdzOiBmdW5jdGlvbihib29sKSB7XG4gICAgaWYgKHR5cGVvZiBib29sICE9PSAnYm9vbGVhbicpIHtcbiAgICAgIHJldHVybiBuZXcgRXJyb3IoJ0FyZ3VtZW50IHR5cGU6ICcgKyB0eXBlb2YgYm9vbCArXG4gICAgICAgICAgJy4gUGxlYXNlIHVzZSBhIGJvb2xlYW4uJyk7XG4gICAgfVxuICAgIGRlcHJlY2F0aW9uV2FybmluZ3NfID0gIWJvb2w7XG4gICAgcmV0dXJuICdhZGFwdGVyLmpzIGRlcHJlY2F0aW9uIHdhcm5pbmdzICcgKyAoYm9vbCA/ICdkaXNhYmxlZCcgOiAnZW5hYmxlZCcpO1xuICB9LFxuXG4gIGxvZzogZnVuY3Rpb24oKSB7XG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgPT09ICdvYmplY3QnKSB7XG4gICAgICBpZiAobG9nRGlzYWJsZWRfKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgY29uc29sZSAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGNvbnNvbGUubG9nID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGNvbnNvbGUubG9nLmFwcGx5KGNvbnNvbGUsIGFyZ3VtZW50cyk7XG4gICAgICB9XG4gICAgfVxuICB9LFxuXG4gIC8qKlxuICAgKiBTaG93cyBhIGRlcHJlY2F0aW9uIHdhcm5pbmcgc3VnZ2VzdGluZyB0aGUgbW9kZXJuIGFuZCBzcGVjLWNvbXBhdGlibGUgQVBJLlxuICAgKi9cbiAgZGVwcmVjYXRlZDogZnVuY3Rpb24ob2xkTWV0aG9kLCBuZXdNZXRob2QpIHtcbiAgICBpZiAoIWRlcHJlY2F0aW9uV2FybmluZ3NfKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnNvbGUud2FybihvbGRNZXRob2QgKyAnIGlzIGRlcHJlY2F0ZWQsIHBsZWFzZSB1c2UgJyArIG5ld01ldGhvZCArXG4gICAgICAgICcgaW5zdGVhZC4nKTtcbiAgfSxcblxuICAvKipcbiAgICogQnJvd3NlciBkZXRlY3Rvci5cbiAgICpcbiAgICogQHJldHVybiB7b2JqZWN0fSByZXN1bHQgY29udGFpbmluZyBicm93c2VyIGFuZCB2ZXJzaW9uXG4gICAqICAgICBwcm9wZXJ0aWVzLlxuICAgKi9cbiAgZGV0ZWN0QnJvd3NlcjogZnVuY3Rpb24od2luZG93KSB7XG4gICAgdmFyIG5hdmlnYXRvciA9IHdpbmRvdyAmJiB3aW5kb3cubmF2aWdhdG9yO1xuXG4gICAgLy8gUmV0dXJuZWQgcmVzdWx0IG9iamVjdC5cbiAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgcmVzdWx0LmJyb3dzZXIgPSBudWxsO1xuICAgIHJlc3VsdC52ZXJzaW9uID0gbnVsbDtcblxuICAgIC8vIEZhaWwgZWFybHkgaWYgaXQncyBub3QgYSBicm93c2VyXG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnIHx8ICF3aW5kb3cubmF2aWdhdG9yKSB7XG4gICAgICByZXN1bHQuYnJvd3NlciA9ICdOb3QgYSBicm93c2VyLic7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGlmIChuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7IC8vIEZpcmVmb3guXG4gICAgICByZXN1bHQuYnJvd3NlciA9ICdmaXJlZm94JztcbiAgICAgIHJlc3VsdC52ZXJzaW9uID0gZXh0cmFjdFZlcnNpb24obmF2aWdhdG9yLnVzZXJBZ2VudCxcbiAgICAgICAgICAvRmlyZWZveFxcLyhcXGQrKVxcLi8sIDEpO1xuICAgIH0gZWxzZSBpZiAobmF2aWdhdG9yLndlYmtpdEdldFVzZXJNZWRpYSkge1xuICAgICAgLy8gQ2hyb21lLCBDaHJvbWl1bSwgV2VidmlldywgT3BlcmEuXG4gICAgICAvLyBWZXJzaW9uIG1hdGNoZXMgQ2hyb21lL1dlYlJUQyB2ZXJzaW9uLlxuICAgICAgcmVzdWx0LmJyb3dzZXIgPSAnY2hyb21lJztcbiAgICAgIHJlc3VsdC52ZXJzaW9uID0gZXh0cmFjdFZlcnNpb24obmF2aWdhdG9yLnVzZXJBZ2VudCxcbiAgICAgICAgICAvQ2hyb20oZXxpdW0pXFwvKFxcZCspXFwuLywgMik7XG4gICAgfSBlbHNlIGlmIChuYXZpZ2F0b3IubWVkaWFEZXZpY2VzICYmXG4gICAgICAgIG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goL0VkZ2VcXC8oXFxkKykuKFxcZCspJC8pKSB7IC8vIEVkZ2UuXG4gICAgICByZXN1bHQuYnJvd3NlciA9ICdlZGdlJztcbiAgICAgIHJlc3VsdC52ZXJzaW9uID0gZXh0cmFjdFZlcnNpb24obmF2aWdhdG9yLnVzZXJBZ2VudCxcbiAgICAgICAgICAvRWRnZVxcLyhcXGQrKS4oXFxkKykkLywgMik7XG4gICAgfSBlbHNlIGlmIChuYXZpZ2F0b3IubWVkaWFEZXZpY2VzICYmXG4gICAgICAgIG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goL0FwcGxlV2ViS2l0XFwvKFxcZCspXFwuLykpIHsgLy8gU2FmYXJpLlxuICAgICAgcmVzdWx0LmJyb3dzZXIgPSAnc2FmYXJpJztcbiAgICAgIHJlc3VsdC52ZXJzaW9uID0gZXh0cmFjdFZlcnNpb24obmF2aWdhdG9yLnVzZXJBZ2VudCxcbiAgICAgICAgICAvQXBwbGVXZWJLaXRcXC8oXFxkKylcXC4vLCAxKTtcbiAgICB9IGVsc2UgeyAvLyBEZWZhdWx0IGZhbGx0aHJvdWdoOiBub3Qgc3VwcG9ydGVkLlxuICAgICAgcmVzdWx0LmJyb3dzZXIgPSAnTm90IGEgc3VwcG9ydGVkIGJyb3dzZXIuJztcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufTtcbiIsIi8qXHJcbldpbGRFbWl0dGVyLmpzIGlzIGEgc2xpbSBsaXR0bGUgZXZlbnQgZW1pdHRlciBieSBAaGVucmlram9yZXRlZyBsYXJnZWx5IGJhc2VkXHJcbm9uIEB2aXNpb25tZWRpYSdzIEVtaXR0ZXIgZnJvbSBVSSBLaXQuXHJcblxyXG5XaHk/IEkgd2FudGVkIGl0IHN0YW5kYWxvbmUuXHJcblxyXG5JIGFsc28gd2FudGVkIHN1cHBvcnQgZm9yIHdpbGRjYXJkIGVtaXR0ZXJzIGxpa2UgdGhpczpcclxuXHJcbmVtaXR0ZXIub24oJyonLCBmdW5jdGlvbiAoZXZlbnROYW1lLCBvdGhlciwgZXZlbnQsIHBheWxvYWRzKSB7XHJcblxyXG59KTtcclxuXHJcbmVtaXR0ZXIub24oJ3NvbWVuYW1lc3BhY2UqJywgZnVuY3Rpb24gKGV2ZW50TmFtZSwgcGF5bG9hZHMpIHtcclxuXHJcbn0pO1xyXG5cclxuUGxlYXNlIG5vdGUgdGhhdCBjYWxsYmFja3MgdHJpZ2dlcmVkIGJ5IHdpbGRjYXJkIHJlZ2lzdGVyZWQgZXZlbnRzIGFsc28gZ2V0XHJcbnRoZSBldmVudCBuYW1lIGFzIHRoZSBmaXJzdCBhcmd1bWVudC5cclxuKi9cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gV2lsZEVtaXR0ZXI7XHJcblxyXG5mdW5jdGlvbiBXaWxkRW1pdHRlcigpIHsgfVxyXG5cclxuV2lsZEVtaXR0ZXIubWl4aW4gPSBmdW5jdGlvbiAoY29uc3RydWN0b3IpIHtcclxuICAgIHZhciBwcm90b3R5cGUgPSBjb25zdHJ1Y3Rvci5wcm90b3R5cGUgfHwgY29uc3RydWN0b3I7XHJcblxyXG4gICAgcHJvdG90eXBlLmlzV2lsZEVtaXR0ZXI9IHRydWU7XHJcblxyXG4gICAgLy8gTGlzdGVuIG9uIHRoZSBnaXZlbiBgZXZlbnRgIHdpdGggYGZuYC4gU3RvcmUgYSBncm91cCBuYW1lIGlmIHByZXNlbnQuXHJcbiAgICBwcm90b3R5cGUub24gPSBmdW5jdGlvbiAoZXZlbnQsIGdyb3VwTmFtZSwgZm4pIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcclxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xyXG4gICAgICAgIGZ1bmMuX2dyb3VwTmFtZSA9IGdyb3VwO1xyXG4gICAgICAgICh0aGlzLmNhbGxiYWNrc1tldmVudF0gPSB0aGlzLmNhbGxiYWNrc1tldmVudF0gfHwgW10pLnB1c2goZnVuYyk7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIEFkZHMgYW4gYGV2ZW50YCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBhIHNpbmdsZVxyXG4gICAgLy8gdGltZSB0aGVuIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZC5cclxuICAgIHByb3RvdHlwZS5vbmNlID0gZnVuY3Rpb24gKGV2ZW50LCBncm91cE5hbWUsIGZuKSB7XHJcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzLFxyXG4gICAgICAgICAgICBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcclxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xyXG4gICAgICAgIGZ1bmN0aW9uIG9uKCkge1xyXG4gICAgICAgICAgICBzZWxmLm9mZihldmVudCwgb24pO1xyXG4gICAgICAgICAgICBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMub24oZXZlbnQsIGdyb3VwLCBvbik7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFVuYmluZHMgYW4gZW50aXJlIGdyb3VwXHJcbiAgICBwcm90b3R5cGUucmVsZWFzZUdyb3VwID0gZnVuY3Rpb24gKGdyb3VwTmFtZSkge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGl0ZW0sIGksIGxlbiwgaGFuZGxlcnM7XHJcbiAgICAgICAgZm9yIChpdGVtIGluIHRoaXMuY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGhhbmRsZXJzID0gdGhpcy5jYWxsYmFja3NbaXRlbV07XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGhhbmRsZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoaGFuZGxlcnNbaV0uX2dyb3VwTmFtZSA9PT0gZ3JvdXBOYW1lKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmxvZygncmVtb3ZpbmcnKTtcclxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXQgYW5kIHNob3J0ZW4gdGhlIGFycmF5IHdlJ3JlIGxvb3BpbmcgdGhyb3VnaFxyXG4gICAgICAgICAgICAgICAgICAgIGhhbmRsZXJzLnNwbGljZShpLCAxKTtcclxuICAgICAgICAgICAgICAgICAgICBpLS07XHJcbiAgICAgICAgICAgICAgICAgICAgbGVuLS07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFJlbW92ZSB0aGUgZ2l2ZW4gY2FsbGJhY2sgZm9yIGBldmVudGAgb3IgYWxsXHJcbiAgICAvLyByZWdpc3RlcmVkIGNhbGxiYWNrcy5cclxuICAgIHByb3RvdHlwZS5vZmYgPSBmdW5jdGlvbiAoZXZlbnQsIGZuKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxyXG4gICAgICAgICAgICBpO1xyXG5cclxuICAgICAgICBpZiAoIWNhbGxiYWNrcykgcmV0dXJuIHRoaXM7XHJcblxyXG4gICAgICAgIC8vIHJlbW92ZSBhbGwgaGFuZGxlcnNcclxuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xyXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5jYWxsYmFja3NbZXZlbnRdO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIHJlbW92ZSBzcGVjaWZpYyBoYW5kbGVyXHJcbiAgICAgICAgaSA9IGNhbGxiYWNrcy5pbmRleE9mKGZuKTtcclxuICAgICAgICBjYWxsYmFja3Muc3BsaWNlKGksIDEpO1xyXG4gICAgICAgIGlmIChjYWxsYmFja3MubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tldmVudF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLy8gRW1pdCBgZXZlbnRgIHdpdGggdGhlIGdpdmVuIGFyZ3MuXHJcbiAgICAvLyBhbHNvIGNhbGxzIGFueSBgKmAgaGFuZGxlcnNcclxuICAgIHByb3RvdHlwZS5lbWl0ID0gZnVuY3Rpb24gKGV2ZW50KSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSxcclxuICAgICAgICAgICAgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxyXG4gICAgICAgICAgICBzcGVjaWFsQ2FsbGJhY2tzID0gdGhpcy5nZXRXaWxkY2FyZENhbGxiYWNrcyhldmVudCksXHJcbiAgICAgICAgICAgIGksXHJcbiAgICAgICAgICAgIGxlbixcclxuICAgICAgICAgICAgaXRlbSxcclxuICAgICAgICAgICAgbGlzdGVuZXJzO1xyXG5cclxuICAgICAgICBpZiAoY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IGNhbGxiYWNrcy5zbGljZSgpO1xyXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcclxuICAgICAgICAgICAgICAgIGlmICghbGlzdGVuZXJzW2ldKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkodGhpcywgYXJncyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChzcGVjaWFsQ2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGxlbiA9IHNwZWNpYWxDYWxsYmFja3MubGVuZ3RoO1xyXG4gICAgICAgICAgICBsaXN0ZW5lcnMgPSBzcGVjaWFsQ2FsbGJhY2tzLnNsaWNlKCk7XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFsaXN0ZW5lcnNbaV0pIHtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBbZXZlbnRdLmNvbmNhdChhcmdzKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBIZWxwZXIgZm9yIGZvciBmaW5kaW5nIHNwZWNpYWwgd2lsZGNhcmQgZXZlbnQgaGFuZGxlcnMgdGhhdCBtYXRjaCB0aGUgZXZlbnRcclxuICAgIHByb3RvdHlwZS5nZXRXaWxkY2FyZENhbGxiYWNrcyA9IGZ1bmN0aW9uIChldmVudE5hbWUpIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBpdGVtLFxyXG4gICAgICAgICAgICBzcGxpdCxcclxuICAgICAgICAgICAgcmVzdWx0ID0gW107XHJcblxyXG4gICAgICAgIGZvciAoaXRlbSBpbiB0aGlzLmNhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBzcGxpdCA9IGl0ZW0uc3BsaXQoJyonKTtcclxuICAgICAgICAgICAgaWYgKGl0ZW0gPT09ICcqJyB8fCAoc3BsaXQubGVuZ3RoID09PSAyICYmIGV2ZW50TmFtZS5zbGljZSgwLCBzcGxpdFswXS5sZW5ndGgpID09PSBzcGxpdFswXSkpIHtcclxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5jb25jYXQodGhpcy5jYWxsYmFja3NbaXRlbV0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICB9O1xyXG5cclxufTtcclxuXHJcbldpbGRFbWl0dGVyLm1peGluKFdpbGRFbWl0dGVyKTtcclxuIiwiLyohXG4gKiBFdmVudEVtaXR0ZXIgdjUuMi40IC0gZ2l0LmlvL2VlXG4gKiBVbmxpY2Vuc2UgLSBodHRwOi8vdW5saWNlbnNlLm9yZy9cbiAqIE9saXZlciBDYWxkd2VsbCAtIGh0dHA6Ly9vbGkubWUudWsvXG4gKiBAcHJlc2VydmVcbiAqL1xuXG47KGZ1bmN0aW9uIChleHBvcnRzKSB7XG4gICAgJ3VzZSBzdHJpY3QnO1xuXG4gICAgLyoqXG4gICAgICogQ2xhc3MgZm9yIG1hbmFnaW5nIGV2ZW50cy5cbiAgICAgKiBDYW4gYmUgZXh0ZW5kZWQgdG8gcHJvdmlkZSBldmVudCBmdW5jdGlvbmFsaXR5IGluIG90aGVyIGNsYXNzZXMuXG4gICAgICpcbiAgICAgKiBAY2xhc3MgRXZlbnRFbWl0dGVyIE1hbmFnZXMgZXZlbnQgcmVnaXN0ZXJpbmcgYW5kIGVtaXR0aW5nLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHt9XG5cbiAgICAvLyBTaG9ydGN1dHMgdG8gaW1wcm92ZSBzcGVlZCBhbmQgc2l6ZVxuICAgIHZhciBwcm90byA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGU7XG4gICAgdmFyIG9yaWdpbmFsR2xvYmFsVmFsdWUgPSBleHBvcnRzLkV2ZW50RW1pdHRlcjtcblxuICAgIC8qKlxuICAgICAqIEZpbmRzIHRoZSBpbmRleCBvZiB0aGUgbGlzdGVuZXIgZm9yIHRoZSBldmVudCBpbiBpdHMgc3RvcmFnZSBhcnJheS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gbGlzdGVuZXJzIEFycmF5IG9mIGxpc3RlbmVycyB0byBzZWFyY2ggdGhyb3VnaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gbG9vayBmb3IuXG4gICAgICogQHJldHVybiB7TnVtYmVyfSBJbmRleCBvZiB0aGUgc3BlY2lmaWVkIGxpc3RlbmVyLCAtMSBpZiBub3QgZm91bmRcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzLCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNbaV0ubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWxpYXMgYSBtZXRob2Qgd2hpbGUga2VlcGluZyB0aGUgY29udGV4dCBjb3JyZWN0LCB0byBhbGxvdyBmb3Igb3ZlcndyaXRpbmcgb2YgdGFyZ2V0IG1ldGhvZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSB0YXJnZXQgbWV0aG9kLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBUaGUgYWxpYXNlZCBtZXRob2RcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhbGlhcyhuYW1lKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBhbGlhc0Nsb3N1cmUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpc1tuYW1lXS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGxpc3RlbmVyIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdpbGwgaW5pdGlhbGlzZSB0aGUgZXZlbnQgb2JqZWN0IGFuZCBsaXN0ZW5lciBhcnJheXMgaWYgcmVxdWlyZWQuXG4gICAgICogV2lsbCByZXR1cm4gYW4gb2JqZWN0IGlmIHlvdSB1c2UgYSByZWdleCBzZWFyY2guIFRoZSBvYmplY3QgY29udGFpbnMga2V5cyBmb3IgZWFjaCBtYXRjaGVkIGV2ZW50LiBTbyAvYmFbcnpdLyBtaWdodCByZXR1cm4gYW4gb2JqZWN0IGNvbnRhaW5pbmcgYmFyIGFuZCBiYXouIEJ1dCBvbmx5IGlmIHlvdSBoYXZlIGVpdGhlciBkZWZpbmVkIHRoZW0gd2l0aCBkZWZpbmVFdmVudCBvciBhZGRlZCBzb21lIGxpc3RlbmVycyB0byB0aGVtLlxuICAgICAqIEVhY2ggcHJvcGVydHkgaW4gdGhlIG9iamVjdCByZXNwb25zZSBpcyBhbiBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZXR1cm4gdGhlIGxpc3RlbmVycyBmcm9tLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9uW118T2JqZWN0fSBBbGwgbGlzdGVuZXIgZnVuY3Rpb25zIGZvciB0aGUgZXZlbnQuXG4gICAgICovXG4gICAgcHJvdG8uZ2V0TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TGlzdGVuZXJzKGV2dCkge1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciByZXNwb25zZTtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICAvLyBSZXR1cm4gYSBjb25jYXRlbmF0ZWQgYXJyYXkgb2YgYWxsIG1hdGNoaW5nIGV2ZW50cyBpZlxuICAgICAgICAvLyB0aGUgc2VsZWN0b3IgaXMgYSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAgICAgIGlmIChldnQgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICAgICAgICBmb3IgKGtleSBpbiBldmVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnRzLmhhc093blByb3BlcnR5KGtleSkgJiYgZXZ0LnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICByZXNwb25zZVtrZXldID0gZXZlbnRzW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSBldmVudHNbZXZ0XSB8fCAoZXZlbnRzW2V2dF0gPSBbXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFRha2VzIGEgbGlzdCBvZiBsaXN0ZW5lciBvYmplY3RzIGFuZCBmbGF0dGVucyBpdCBpbnRvIGEgbGlzdCBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdFtdfSBsaXN0ZW5lcnMgUmF3IGxpc3RlbmVyIG9iamVjdHMuXG4gICAgICogQHJldHVybiB7RnVuY3Rpb25bXX0gSnVzdCB0aGUgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqL1xuICAgIHByb3RvLmZsYXR0ZW5MaXN0ZW5lcnMgPSBmdW5jdGlvbiBmbGF0dGVuTGlzdGVuZXJzKGxpc3RlbmVycykge1xuICAgICAgICB2YXIgZmxhdExpc3RlbmVycyA9IFtdO1xuICAgICAgICB2YXIgaTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBmbGF0TGlzdGVuZXJzLnB1c2gobGlzdGVuZXJzW2ldLmxpc3RlbmVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmbGF0TGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSByZXF1ZXN0ZWQgbGlzdGVuZXJzIHZpYSBnZXRMaXN0ZW5lcnMgYnV0IHdpbGwgYWx3YXlzIHJldHVybiB0aGUgcmVzdWx0cyBpbnNpZGUgYW4gb2JqZWN0LiBUaGlzIGlzIG1haW5seSBmb3IgaW50ZXJuYWwgdXNlIGJ1dCBvdGhlcnMgbWF5IGZpbmQgaXQgdXNlZnVsLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmV0dXJuIHRoZSBsaXN0ZW5lcnMgZnJvbS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEFsbCBsaXN0ZW5lciBmdW5jdGlvbnMgZm9yIGFuIGV2ZW50IGluIGFuIG9iamVjdC5cbiAgICAgKi9cbiAgICBwcm90by5nZXRMaXN0ZW5lcnNBc09iamVjdCA9IGZ1bmN0aW9uIGdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCkge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnMoZXZ0KTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuXG4gICAgICAgIGlmIChsaXN0ZW5lcnMgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSB7fTtcbiAgICAgICAgICAgIHJlc3BvbnNlW2V2dF0gPSBsaXN0ZW5lcnM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2UgfHwgbGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBpc1ZhbGlkTGlzdGVuZXIgKGxpc3RlbmVyKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXIgPT09ICdmdW5jdGlvbicgfHwgbGlzdGVuZXIgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgIH0gZWxzZSBpZiAobGlzdGVuZXIgJiYgdHlwZW9mIGxpc3RlbmVyID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmV0dXJuIGlzVmFsaWRMaXN0ZW5lcihsaXN0ZW5lci5saXN0ZW5lcilcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIHRvIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogVGhlIGxpc3RlbmVyIHdpbGwgbm90IGJlIGFkZGVkIGlmIGl0IGlzIGEgZHVwbGljYXRlLlxuICAgICAqIElmIHRoZSBsaXN0ZW5lciByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgaXQgaXMgY2FsbGVkLlxuICAgICAqIElmIHlvdSBwYXNzIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lIHRoZW4gdGhlIGxpc3RlbmVyIHdpbGwgYmUgYWRkZWQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gYXR0YWNoIHRoZSBsaXN0ZW5lciB0by5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWQuIElmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgY2FsbGluZy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKCFpc1ZhbGlkTGlzdGVuZXIobGlzdGVuZXIpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcklzV3JhcHBlZCA9IHR5cGVvZiBsaXN0ZW5lciA9PT0gJ29iamVjdCc7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmhhc093blByb3BlcnR5KGtleSkgJiYgaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVyc1trZXldLCBsaXN0ZW5lcikgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0ucHVzaChsaXN0ZW5lcklzV3JhcHBlZCA/IGxpc3RlbmVyIDoge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICAgICAgICAgIG9uY2U6IGZhbHNlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgYWRkTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vbiA9IGFsaWFzKCdhZGRMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogU2VtaS1hbGlhcyBvZiBhZGRMaXN0ZW5lci4gSXQgd2lsbCBhZGQgYSBsaXN0ZW5lciB0aGF0IHdpbGwgYmVcbiAgICAgKiBhdXRvbWF0aWNhbGx5IHJlbW92ZWQgYWZ0ZXIgaXRzIGZpcnN0IGV4ZWN1dGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGF0dGFjaCB0aGUgbGlzdGVuZXIgdG8uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyBlbWl0dGVkLiBJZiB0aGUgZnVuY3Rpb24gcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGNhbGxpbmcuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkT25jZUxpc3RlbmVyID0gZnVuY3Rpb24gYWRkT25jZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWRkTGlzdGVuZXIoZXZ0LCB7XG4gICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICBvbmNlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBhZGRPbmNlTGlzdGVuZXIuXG4gICAgICovXG4gICAgcHJvdG8ub25jZSA9IGFsaWFzKCdhZGRPbmNlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIERlZmluZXMgYW4gZXZlbnQgbmFtZS4gVGhpcyBpcyByZXF1aXJlZCBpZiB5b3Ugd2FudCB0byB1c2UgYSByZWdleCB0byBhZGQgYSBsaXN0ZW5lciB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gSWYgeW91IGRvbid0IGRvIHRoaXMgdGhlbiBob3cgZG8geW91IGV4cGVjdCBpdCB0byBrbm93IHdoYXQgZXZlbnQgdG8gYWRkIHRvPyBTaG91bGQgaXQganVzdCBhZGQgdG8gZXZlcnkgcG9zc2libGUgbWF0Y2ggZm9yIGEgcmVnZXg/IE5vLiBUaGF0IGlzIHNjYXJ5IGFuZCBiYWQuXG4gICAgICogWW91IG5lZWQgdG8gdGVsbCBpdCB3aGF0IGV2ZW50IG5hbWVzIHNob3VsZCBiZSBtYXRjaGVkIGJ5IGEgcmVnZXguXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGNyZWF0ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5kZWZpbmVFdmVudCA9IGZ1bmN0aW9uIGRlZmluZUV2ZW50KGV2dCkge1xuICAgICAgICB0aGlzLmdldExpc3RlbmVycyhldnQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVXNlcyBkZWZpbmVFdmVudCB0byBkZWZpbmUgbXVsdGlwbGUgZXZlbnRzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmdbXX0gZXZ0cyBBbiBhcnJheSBvZiBldmVudCBuYW1lcyB0byBkZWZpbmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZGVmaW5lRXZlbnRzID0gZnVuY3Rpb24gZGVmaW5lRXZlbnRzKGV2dHMpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBldnRzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICB0aGlzLmRlZmluZUV2ZW50KGV2dHNbaV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGEgbGlzdGVuZXIgZnVuY3Rpb24gZnJvbSB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdoZW4gcGFzc2VkIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lLCBpdCB3aWxsIHJlbW92ZSB0aGUgbGlzdGVuZXIgZnJvbSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZW1vdmUgdGhlIGxpc3RlbmVyIGZyb20uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIHJlbW92ZSBmcm9tIHRoZSBldmVudC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lciA9IGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGluZGV4O1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVycykge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgaW5kZXggPSBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzW2tleV0sIGxpc3RlbmVyKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0uc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vZmYgPSBhbGlhcygncmVtb3ZlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy4gWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIGFkZGVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIGFkZCB0aGUgYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKiBZZWFoLCB0aGlzIGZ1bmN0aW9uIGRvZXMgcXVpdGUgYSBiaXQuIFRoYXQncyBwcm9iYWJseSBhIGJhZCB0aGluZy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gYWRkLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZExpc3RlbmVycyA9IGZ1bmN0aW9uIGFkZExpc3RlbmVycyhldnQsIGxpc3RlbmVycykge1xuICAgICAgICAvLyBQYXNzIHRocm91Z2ggdG8gbWFuaXB1bGF0ZUxpc3RlbmVyc1xuICAgICAgICByZXR1cm4gdGhpcy5tYW5pcHVsYXRlTGlzdGVuZXJzKGZhbHNlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiByZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSByZW1vdmVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXJzIGZyb20gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIHJlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lcnMgPSBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcnMoZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gUGFzcyB0aHJvdWdoIHRvIG1hbmlwdWxhdGVMaXN0ZW5lcnNcbiAgICAgICAgcmV0dXJuIHRoaXMubWFuaXB1bGF0ZUxpc3RlbmVycyh0cnVlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEVkaXRzIGxpc3RlbmVycyBpbiBidWxrLiBUaGUgYWRkTGlzdGVuZXJzIGFuZCByZW1vdmVMaXN0ZW5lcnMgbWV0aG9kcyBib3RoIHVzZSB0aGlzIHRvIGRvIHRoZWlyIGpvYi4gWW91IHNob3VsZCByZWFsbHkgdXNlIHRob3NlIGluc3RlYWQsIHRoaXMgaXMgYSBsaXR0bGUgbG93ZXIgbGV2ZWwuXG4gICAgICogVGhlIGZpcnN0IGFyZ3VtZW50IHdpbGwgZGV0ZXJtaW5lIGlmIHRoZSBsaXN0ZW5lcnMgYXJlIHJlbW92ZWQgKHRydWUpIG9yIGFkZGVkIChmYWxzZSkuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBzZWNvbmQgYXJndW1lbnQgeW91IGNhbiBhZGQvcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgYWRkZWQvcmVtb3ZlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBtYW5pcHVsYXRlIHRoZSBsaXN0ZW5lcnMgb2YgYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtCb29sZWFufSByZW1vdmUgVHJ1ZSBpZiB5b3Ugd2FudCB0byByZW1vdmUgbGlzdGVuZXJzLCBmYWxzZSBpZiB5b3Ugd2FudCB0byBhZGQuXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIGFkZC9yZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byBhZGQvcmVtb3ZlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLm1hbmlwdWxhdGVMaXN0ZW5lcnMgPSBmdW5jdGlvbiBtYW5pcHVsYXRlTGlzdGVuZXJzKHJlbW92ZSwgZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciB2YWx1ZTtcbiAgICAgICAgdmFyIHNpbmdsZSA9IHJlbW92ZSA/IHRoaXMucmVtb3ZlTGlzdGVuZXIgOiB0aGlzLmFkZExpc3RlbmVyO1xuICAgICAgICB2YXIgbXVsdGlwbGUgPSByZW1vdmUgPyB0aGlzLnJlbW92ZUxpc3RlbmVycyA6IHRoaXMuYWRkTGlzdGVuZXJzO1xuXG4gICAgICAgIC8vIElmIGV2dCBpcyBhbiBvYmplY3QgdGhlbiBwYXNzIGVhY2ggb2YgaXRzIHByb3BlcnRpZXMgdG8gdGhpcyBtZXRob2RcbiAgICAgICAgaWYgKHR5cGVvZiBldnQgPT09ICdvYmplY3QnICYmICEoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSkge1xuICAgICAgICAgICAgZm9yIChpIGluIGV2dCkge1xuICAgICAgICAgICAgICAgIGlmIChldnQuaGFzT3duUHJvcGVydHkoaSkgJiYgKHZhbHVlID0gZXZ0W2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBQYXNzIHRoZSBzaW5nbGUgbGlzdGVuZXIgc3RyYWlnaHQgdGhyb3VnaCB0byB0aGUgc2luZ3VsYXIgbWV0aG9kXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbmdsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBwYXNzIGJhY2sgdG8gdGhlIG11bHRpcGxlIGZ1bmN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXBsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFNvIGV2dCBtdXN0IGJlIGEgc3RyaW5nXG4gICAgICAgICAgICAvLyBBbmQgbGlzdGVuZXJzIG11c3QgYmUgYW4gYXJyYXkgb2YgbGlzdGVuZXJzXG4gICAgICAgICAgICAvLyBMb29wIG92ZXIgaXQgYW5kIHBhc3MgZWFjaCBvbmUgdG8gdGhlIG11bHRpcGxlIG1ldGhvZFxuICAgICAgICAgICAgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgc2luZ2xlLmNhbGwodGhpcywgZXZ0LCBsaXN0ZW5lcnNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGxpc3RlbmVycyBmcm9tIGEgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIElmIHlvdSBkbyBub3Qgc3BlY2lmeSBhbiBldmVudCB0aGVuIGFsbCBsaXN0ZW5lcnMgd2lsbCBiZSByZW1vdmVkLlxuICAgICAqIFRoYXQgbWVhbnMgZXZlcnkgZXZlbnQgd2lsbCBiZSBlbXB0aWVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGEgcmVnZXggdG8gcmVtb3ZlIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gW2V2dF0gT3B0aW9uYWwgbmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIGFsbCBsaXN0ZW5lcnMgZm9yLiBXaWxsIHJlbW92ZSBmcm9tIGV2ZXJ5IGV2ZW50IGlmIG5vdCBwYXNzZWQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlRXZlbnQgPSBmdW5jdGlvbiByZW1vdmVFdmVudChldnQpIHtcbiAgICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgZXZ0O1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgLy8gUmVtb3ZlIGRpZmZlcmVudCB0aGluZ3MgZGVwZW5kaW5nIG9uIHRoZSBzdGF0ZSBvZiBldnRcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGxpc3RlbmVycyBmb3IgdGhlIHNwZWNpZmllZCBldmVudFxuICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1tldnRdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBldmVudHMgbWF0Y2hpbmcgdGhlIHJlZ2V4LlxuICAgICAgICAgICAgZm9yIChrZXkgaW4gZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGV2dC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgbGlzdGVuZXJzIGluIGFsbCBldmVudHNcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlRXZlbnQuXG4gICAgICpcbiAgICAgKiBBZGRlZCB0byBtaXJyb3IgdGhlIG5vZGUgQVBJLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUFsbExpc3RlbmVycyA9IGFsaWFzKCdyZW1vdmVFdmVudCcpO1xuXG4gICAgLyoqXG4gICAgICogRW1pdHMgYW4gZXZlbnQgb2YgeW91ciBjaG9pY2UuXG4gICAgICogV2hlbiBlbWl0dGVkLCBldmVyeSBsaXN0ZW5lciBhdHRhY2hlZCB0byB0aGF0IGV2ZW50IHdpbGwgYmUgZXhlY3V0ZWQuXG4gICAgICogSWYgeW91IHBhc3MgdGhlIG9wdGlvbmFsIGFyZ3VtZW50IGFycmF5IHRoZW4gdGhvc2UgYXJndW1lbnRzIHdpbGwgYmUgcGFzc2VkIHRvIGV2ZXJ5IGxpc3RlbmVyIHVwb24gZXhlY3V0aW9uLlxuICAgICAqIEJlY2F1c2UgaXQgdXNlcyBgYXBwbHlgLCB5b3VyIGFycmF5IG9mIGFyZ3VtZW50cyB3aWxsIGJlIHBhc3NlZCBhcyBpZiB5b3Ugd3JvdGUgdGhlbSBvdXQgc2VwYXJhdGVseS5cbiAgICAgKiBTbyB0aGV5IHdpbGwgbm90IGFycml2ZSB3aXRoaW4gdGhlIGFycmF5IG9uIHRoZSBvdGhlciBzaWRlLCB0aGV5IHdpbGwgYmUgc2VwYXJhdGUuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2FyZ3NdIE9wdGlvbmFsIGFycmF5IG9mIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0RXZlbnQgPSBmdW5jdGlvbiBlbWl0RXZlbnQoZXZ0LCBhcmdzKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnNNYXAgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcnM7XG4gICAgICAgIHZhciBsaXN0ZW5lcjtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIHZhciByZXNwb25zZTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnNNYXApIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNNYXAuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVycyA9IGxpc3RlbmVyc01hcFtrZXldLnNsaWNlKDApO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgbGlzdGVuZXIgcmV0dXJucyB0cnVlIHRoZW4gaXQgc2hhbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBldmVudFxuICAgICAgICAgICAgICAgICAgICAvLyBUaGUgZnVuY3Rpb24gaXMgZXhlY3V0ZWQgZWl0aGVyIHdpdGggYSBiYXNpYyBjYWxsIG9yIGFuIGFwcGx5IGlmIHRoZXJlIGlzIGFuIGFyZ3MgYXJyYXlcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxpc3RlbmVyLm9uY2UgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9IGxpc3RlbmVyLmxpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3MgfHwgW10pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZSA9PT0gdGhpcy5fZ2V0T25jZVJldHVyblZhbHVlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgZW1pdEV2ZW50XG4gICAgICovXG4gICAgcHJvdG8udHJpZ2dlciA9IGFsaWFzKCdlbWl0RXZlbnQnKTtcblxuICAgIC8qKlxuICAgICAqIFN1YnRseSBkaWZmZXJlbnQgZnJvbSBlbWl0RXZlbnQgaW4gdGhhdCBpdCB3aWxsIHBhc3MgaXRzIGFyZ3VtZW50cyBvbiB0byB0aGUgbGlzdGVuZXJzLCBhcyBvcHBvc2VkIHRvIHRha2luZyBhIHNpbmdsZSBhcnJheSBvZiBhcmd1bWVudHMgdG8gcGFzcyBvbi5cbiAgICAgKiBBcyB3aXRoIGVtaXRFdmVudCwgeW91IGNhbiBwYXNzIGEgcmVnZXggaW4gcGxhY2Ugb2YgdGhlIGV2ZW50IG5hbWUgdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHsuLi4qfSBPcHRpb25hbCBhZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0ID0gZnVuY3Rpb24gZW1pdChldnQpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICByZXR1cm4gdGhpcy5lbWl0RXZlbnQoZXZ0LCBhcmdzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBhZ2FpbnN0IHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy4gSWYgYVxuICAgICAqIGxpc3RlbmVycyByZXR1cm4gdmFsdWUgbWF0Y2hlcyB0aGUgb25lIHNldCBoZXJlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkXG4gICAgICogYWZ0ZXIgZXhlY3V0aW9uLiBUaGlzIHZhbHVlIGRlZmF1bHRzIHRvIHRydWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUgdG8gY2hlY2sgZm9yIHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5zZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBzZXRPbmNlUmV0dXJuVmFsdWUodmFsdWUpIHtcbiAgICAgICAgdGhpcy5fb25jZVJldHVyblZhbHVlID0gdmFsdWU7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGFnYWluc3Qgd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLiBJZlxuICAgICAqIHRoZSBsaXN0ZW5lcnMgcmV0dXJuIHZhbHVlIG1hdGNoZXMgdGhpcyBvbmUgdGhlbiBpdCBzaG91bGQgYmUgcmVtb3ZlZFxuICAgICAqIGF1dG9tYXRpY2FsbHkuIEl0IHdpbGwgcmV0dXJuIHRydWUgYnkgZGVmYXVsdC5cbiAgICAgKlxuICAgICAqIEByZXR1cm4geyp8Qm9vbGVhbn0gVGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgZm9yIG9yIHRoZSBkZWZhdWx0LCB0cnVlLlxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIHByb3RvLl9nZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBfZ2V0T25jZVJldHVyblZhbHVlKCkge1xuICAgICAgICBpZiAodGhpcy5oYXNPd25Qcm9wZXJ0eSgnX29uY2VSZXR1cm5WYWx1ZScpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb25jZVJldHVyblZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgZXZlbnRzIG9iamVjdCBhbmQgY3JlYXRlcyBvbmUgaWYgcmVxdWlyZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IFRoZSBldmVudHMgc3RvcmFnZSBvYmplY3QuXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgcHJvdG8uX2dldEV2ZW50cyA9IGZ1bmN0aW9uIF9nZXRFdmVudHMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9ldmVudHMgfHwgKHRoaXMuX2V2ZW50cyA9IHt9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmV2ZXJ0cyB0aGUgZ2xvYmFsIHtAbGluayBFdmVudEVtaXR0ZXJ9IHRvIGl0cyBwcmV2aW91cyB2YWx1ZSBhbmQgcmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGlzIHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gTm9uIGNvbmZsaWN0aW5nIEV2ZW50RW1pdHRlciBjbGFzcy5cbiAgICAgKi9cbiAgICBFdmVudEVtaXR0ZXIubm9Db25mbGljdCA9IGZ1bmN0aW9uIG5vQ29uZmxpY3QoKSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gb3JpZ2luYWxHbG9iYWxWYWx1ZTtcbiAgICAgICAgcmV0dXJuIEV2ZW50RW1pdHRlcjtcbiAgICB9O1xuXG4gICAgLy8gRXhwb3NlIHRoZSBjbGFzcyBlaXRoZXIgdmlhIEFNRCwgQ29tbW9uSlMgb3IgdGhlIGdsb2JhbCBvYmplY3RcbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gRXZlbnRFbWl0dGVyO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMpe1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuICAgIH1cbn0odGhpcyB8fCB7fSkpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vLyBMYXN0IFVwZGF0ZWQgT246IDIwMTctMTItMDkgMjoyOToyMiBQTSBVVENcblxuLy8gX19fX19fX19fX19fX19fX1xuLy8gRGV0ZWN0UlRDIHYxLjMuNlxuXG4vLyBPcGVuLVNvdXJjZWQ6IGh0dHBzOi8vZ2l0aHViLmNvbS9tdWF6LWtoYW4vRGV0ZWN0UlRDXG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBNdWF6IEtoYW4gICAgIC0gd3d3Lk11YXpLaGFuLmNvbVxuLy8gTUlUIExpY2Vuc2UgICAtIHd3dy5XZWJSVEMtRXhwZXJpbWVudC5jb20vbGljZW5jZVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuKGZ1bmN0aW9uKCkge1xuXG4gICAgdmFyIGJyb3dzZXJGYWtlVXNlckFnZW50ID0gJ0Zha2UvNS4wIChGYWtlT1MpIEFwcGxlV2ViS2l0LzEyMyAoS0hUTUwsIGxpa2UgR2Vja28pIEZha2UvMTIuMy40NTY3Ljg5IEZha2UvMTIzLjQ1JztcblxuICAgIHZhciBpc05vZGVqcyA9IHR5cGVvZiBwcm9jZXNzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgcHJvY2Vzcy52ZXJzaW9ucyA9PT0gJ29iamVjdCcgJiYgcHJvY2Vzcy52ZXJzaW9ucy5ub2RlICYmIC8qbm9kZS1wcm9jZXNzKi8gIXByb2Nlc3MuYnJvd3NlcjtcbiAgICBpZiAoaXNOb2RlanMpIHtcbiAgICAgICAgdmFyIHZlcnNpb24gPSBwcm9jZXNzLnZlcnNpb25zLm5vZGUudG9TdHJpbmcoKS5yZXBsYWNlKCd2JywgJycpO1xuICAgICAgICBicm93c2VyRmFrZVVzZXJBZ2VudCA9ICdOb2RlanMvJyArIHZlcnNpb24gKyAnIChOb2RlT1MpIEFwcGxlV2ViS2l0LycgKyB2ZXJzaW9uICsgJyAoS0hUTUwsIGxpa2UgR2Vja28pIE5vZGVqcy8nICsgdmVyc2lvbiArICcgTm9kZWpzLycgKyB2ZXJzaW9uXG4gICAgfVxuXG4gICAgKGZ1bmN0aW9uKHRoYXQpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIGdsb2JhbC5uYXZpZ2F0b3IgPSB7XG4gICAgICAgICAgICAgICAgdXNlckFnZW50OiBicm93c2VyRmFrZVVzZXJBZ2VudCxcbiAgICAgICAgICAgICAgICBnZXRVc2VyTWVkaWE6IGZ1bmN0aW9uKCkge31cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8qZ2xvYmFsIHdpbmRvdzp0cnVlICovXG4gICAgICAgICAgICB0aGF0LndpbmRvdyA9IGdsb2JhbDtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgLy8gd2luZG93ID0gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgbG9jYXRpb24gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAvKmdsb2JhbCBsb2NhdGlvbjp0cnVlICovXG4gICAgICAgICAgICB0aGF0LmxvY2F0aW9uID0ge1xuICAgICAgICAgICAgICAgIHByb3RvY29sOiAnZmlsZTonLFxuICAgICAgICAgICAgICAgIGhyZWY6ICcnLFxuICAgICAgICAgICAgICAgIGhhc2g6ICcnXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBzY3JlZW4gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAvKmdsb2JhbCBzY3JlZW46dHJ1ZSAqL1xuICAgICAgICAgICAgdGhhdC5zY3JlZW4gPSB7XG4gICAgICAgICAgICAgICAgd2lkdGg6IDAsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiAwXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfSkodHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcgPyBnbG9iYWwgOiB3aW5kb3cpO1xuXG4gICAgLypnbG9iYWwgbmF2aWdhdG9yOnRydWUgKi9cbiAgICB2YXIgbmF2aWdhdG9yID0gd2luZG93Lm5hdmlnYXRvcjtcblxuICAgIGlmICh0eXBlb2YgbmF2aWdhdG9yICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBpZiAodHlwZW9mIG5hdmlnYXRvci53ZWJraXRHZXRVc2VyTWVkaWEgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBuYXZpZ2F0b3IuZ2V0VXNlck1lZGlhID0gbmF2aWdhdG9yLndlYmtpdEdldFVzZXJNZWRpYTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgbmF2aWdhdG9yLm1vekdldFVzZXJNZWRpYSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIG5hdmlnYXRvci5nZXRVc2VyTWVkaWEgPSBuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbmF2aWdhdG9yID0ge1xuICAgICAgICAgICAgZ2V0VXNlck1lZGlhOiBmdW5jdGlvbigpIHt9LFxuICAgICAgICAgICAgdXNlckFnZW50OiBicm93c2VyRmFrZVVzZXJBZ2VudFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHZhciBpc01vYmlsZURldmljZSA9ICEhKC9BbmRyb2lkfHdlYk9TfGlQaG9uZXxpUGFkfGlQb2R8QkIxMHxCbGFja0JlcnJ5fElFTW9iaWxlfE9wZXJhIE1pbml8TW9iaWxlfG1vYmlsZS9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCB8fCAnJykpO1xuXG4gICAgdmFyIGlzRWRnZSA9IG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignRWRnZScpICE9PSAtMSAmJiAoISFuYXZpZ2F0b3IubXNTYXZlT3JPcGVuQmxvYiB8fCAhIW5hdmlnYXRvci5tc1NhdmVCbG9iKTtcblxuICAgIHZhciBpc09wZXJhID0gISF3aW5kb3cub3BlcmEgfHwgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCcgT1BSLycpID49IDA7XG4gICAgdmFyIGlzRmlyZWZveCA9IHR5cGVvZiB3aW5kb3cuSW5zdGFsbFRyaWdnZXIgIT09ICd1bmRlZmluZWQnO1xuICAgIHZhciBpc1NhZmFyaSA9IC9eKCg/IWNocm9tZXxhbmRyb2lkKS4pKnNhZmFyaS9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gICAgdmFyIGlzQ2hyb21lID0gISF3aW5kb3cuY2hyb21lICYmICFpc09wZXJhO1xuICAgIHZhciBpc0lFID0gdHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJyAmJiAhIWRvY3VtZW50LmRvY3VtZW50TW9kZSAmJiAhaXNFZGdlO1xuXG4gICAgLy8gdGhpcyBvbmUgY2FuIGFsc28gYmUgdXNlZDpcbiAgICAvLyBodHRwczovL3d3dy53ZWJzb2NrZXQub3JnL2pzL3N0dWZmLmpzIChEZXRlY3RCcm93c2VyLmpzKVxuXG4gICAgZnVuY3Rpb24gZ2V0QnJvd3NlckluZm8oKSB7XG4gICAgICAgIHZhciBuVmVyID0gbmF2aWdhdG9yLmFwcFZlcnNpb247XG4gICAgICAgIHZhciBuQWd0ID0gbmF2aWdhdG9yLnVzZXJBZ2VudDtcbiAgICAgICAgdmFyIGJyb3dzZXJOYW1lID0gbmF2aWdhdG9yLmFwcE5hbWU7XG4gICAgICAgIHZhciBmdWxsVmVyc2lvbiA9ICcnICsgcGFyc2VGbG9hdChuYXZpZ2F0b3IuYXBwVmVyc2lvbik7XG4gICAgICAgIHZhciBtYWpvclZlcnNpb24gPSBwYXJzZUludChuYXZpZ2F0b3IuYXBwVmVyc2lvbiwgMTApO1xuICAgICAgICB2YXIgbmFtZU9mZnNldCwgdmVyT2Zmc2V0LCBpeDtcblxuICAgICAgICAvLyBJbiBPcGVyYSwgdGhlIHRydWUgdmVyc2lvbiBpcyBhZnRlciAnT3BlcmEnIG9yIGFmdGVyICdWZXJzaW9uJ1xuICAgICAgICBpZiAoaXNPcGVyYSkge1xuICAgICAgICAgICAgYnJvd3Nlck5hbWUgPSAnT3BlcmEnO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBmdWxsVmVyc2lvbiA9IG5hdmlnYXRvci51c2VyQWdlbnQuc3BsaXQoJ09QUi8nKVsxXS5zcGxpdCgnICcpWzBdO1xuICAgICAgICAgICAgICAgIG1ham9yVmVyc2lvbiA9IGZ1bGxWZXJzaW9uLnNwbGl0KCcuJylbMF07XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgZnVsbFZlcnNpb24gPSAnMC4wLjAuMCc7XG4gICAgICAgICAgICAgICAgbWFqb3JWZXJzaW9uID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBJbiBNU0lFIHZlcnNpb24gPD0xMCwgdGhlIHRydWUgdmVyc2lvbiBpcyBhZnRlciAnTVNJRScgaW4gdXNlckFnZW50XG4gICAgICAgIC8vIEluIElFIDExLCBsb29rIGZvciB0aGUgc3RyaW5nIGFmdGVyICdydjonXG4gICAgICAgIGVsc2UgaWYgKGlzSUUpIHtcbiAgICAgICAgICAgIHZlck9mZnNldCA9IG5BZ3QuaW5kZXhPZigncnY6Jyk7XG4gICAgICAgICAgICBpZiAodmVyT2Zmc2V0ID4gMCkgeyAvL0lFIDExXG4gICAgICAgICAgICAgICAgZnVsbFZlcnNpb24gPSBuQWd0LnN1YnN0cmluZyh2ZXJPZmZzZXQgKyAzKTtcbiAgICAgICAgICAgIH0gZWxzZSB7IC8vSUUgMTAgb3IgZWFybGllclxuICAgICAgICAgICAgICAgIHZlck9mZnNldCA9IG5BZ3QuaW5kZXhPZignTVNJRScpO1xuICAgICAgICAgICAgICAgIGZ1bGxWZXJzaW9uID0gbkFndC5zdWJzdHJpbmcodmVyT2Zmc2V0ICsgNSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicm93c2VyTmFtZSA9ICdJRSc7XG4gICAgICAgIH1cbiAgICAgICAgLy8gSW4gQ2hyb21lLCB0aGUgdHJ1ZSB2ZXJzaW9uIGlzIGFmdGVyICdDaHJvbWUnIFxuICAgICAgICBlbHNlIGlmIChpc0Nocm9tZSkge1xuICAgICAgICAgICAgdmVyT2Zmc2V0ID0gbkFndC5pbmRleE9mKCdDaHJvbWUnKTtcbiAgICAgICAgICAgIGJyb3dzZXJOYW1lID0gJ0Nocm9tZSc7XG4gICAgICAgICAgICBmdWxsVmVyc2lvbiA9IG5BZ3Quc3Vic3RyaW5nKHZlck9mZnNldCArIDcpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEluIFNhZmFyaSwgdGhlIHRydWUgdmVyc2lvbiBpcyBhZnRlciAnU2FmYXJpJyBvciBhZnRlciAnVmVyc2lvbicgXG4gICAgICAgIGVsc2UgaWYgKGlzU2FmYXJpKSB7XG4gICAgICAgICAgICB2ZXJPZmZzZXQgPSBuQWd0LmluZGV4T2YoJ1NhZmFyaScpO1xuXG4gICAgICAgICAgICBicm93c2VyTmFtZSA9ICdTYWZhcmknO1xuICAgICAgICAgICAgZnVsbFZlcnNpb24gPSBuQWd0LnN1YnN0cmluZyh2ZXJPZmZzZXQgKyA3KTtcblxuICAgICAgICAgICAgaWYgKCh2ZXJPZmZzZXQgPSBuQWd0LmluZGV4T2YoJ1ZlcnNpb24nKSkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgZnVsbFZlcnNpb24gPSBuQWd0LnN1YnN0cmluZyh2ZXJPZmZzZXQgKyA4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignVmVyc2lvbi8nKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBmdWxsVmVyc2lvbiA9IG5hdmlnYXRvci51c2VyQWdlbnQuc3BsaXQoJ1ZlcnNpb24vJylbMV0uc3BsaXQoJyAnKVswXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBJbiBGaXJlZm94LCB0aGUgdHJ1ZSB2ZXJzaW9uIGlzIGFmdGVyICdGaXJlZm94JyBcbiAgICAgICAgZWxzZSBpZiAoaXNGaXJlZm94KSB7XG4gICAgICAgICAgICB2ZXJPZmZzZXQgPSBuQWd0LmluZGV4T2YoJ0ZpcmVmb3gnKTtcbiAgICAgICAgICAgIGJyb3dzZXJOYW1lID0gJ0ZpcmVmb3gnO1xuICAgICAgICAgICAgZnVsbFZlcnNpb24gPSBuQWd0LnN1YnN0cmluZyh2ZXJPZmZzZXQgKyA4KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEluIG1vc3Qgb3RoZXIgYnJvd3NlcnMsICduYW1lL3ZlcnNpb24nIGlzIGF0IHRoZSBlbmQgb2YgdXNlckFnZW50IFxuICAgICAgICBlbHNlIGlmICgobmFtZU9mZnNldCA9IG5BZ3QubGFzdEluZGV4T2YoJyAnKSArIDEpIDwgKHZlck9mZnNldCA9IG5BZ3QubGFzdEluZGV4T2YoJy8nKSkpIHtcbiAgICAgICAgICAgIGJyb3dzZXJOYW1lID0gbkFndC5zdWJzdHJpbmcobmFtZU9mZnNldCwgdmVyT2Zmc2V0KTtcbiAgICAgICAgICAgIGZ1bGxWZXJzaW9uID0gbkFndC5zdWJzdHJpbmcodmVyT2Zmc2V0ICsgMSk7XG5cbiAgICAgICAgICAgIGlmIChicm93c2VyTmFtZS50b0xvd2VyQ2FzZSgpID09PSBicm93c2VyTmFtZS50b1VwcGVyQ2FzZSgpKSB7XG4gICAgICAgICAgICAgICAgYnJvd3Nlck5hbWUgPSBuYXZpZ2F0b3IuYXBwTmFtZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc0VkZ2UpIHtcbiAgICAgICAgICAgIGJyb3dzZXJOYW1lID0gJ0VkZ2UnO1xuICAgICAgICAgICAgZnVsbFZlcnNpb24gPSBuYXZpZ2F0b3IudXNlckFnZW50LnNwbGl0KCdFZGdlLycpWzFdO1xuICAgICAgICAgICAgLy8gZnVsbFZlcnNpb24gPSBwYXJzZUludChuYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKC9FZGdlXFwvKFxcZCspLihcXGQrKSQvKVsyXSwgMTApLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0cmltIHRoZSBmdWxsVmVyc2lvbiBzdHJpbmcgYXQgc2VtaWNvbG9uL3NwYWNlL2JyYWNrZXQgaWYgcHJlc2VudFxuICAgICAgICBpZiAoKGl4ID0gZnVsbFZlcnNpb24uc2VhcmNoKC9bOyBcXCldLykpICE9PSAtMSkge1xuICAgICAgICAgICAgZnVsbFZlcnNpb24gPSBmdWxsVmVyc2lvbi5zdWJzdHJpbmcoMCwgaXgpO1xuICAgICAgICB9XG5cbiAgICAgICAgbWFqb3JWZXJzaW9uID0gcGFyc2VJbnQoJycgKyBmdWxsVmVyc2lvbiwgMTApO1xuXG4gICAgICAgIGlmIChpc05hTihtYWpvclZlcnNpb24pKSB7XG4gICAgICAgICAgICBmdWxsVmVyc2lvbiA9ICcnICsgcGFyc2VGbG9hdChuYXZpZ2F0b3IuYXBwVmVyc2lvbik7XG4gICAgICAgICAgICBtYWpvclZlcnNpb24gPSBwYXJzZUludChuYXZpZ2F0b3IuYXBwVmVyc2lvbiwgMTApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGZ1bGxWZXJzaW9uOiBmdWxsVmVyc2lvbixcbiAgICAgICAgICAgIHZlcnNpb246IG1ham9yVmVyc2lvbixcbiAgICAgICAgICAgIG5hbWU6IGJyb3dzZXJOYW1lLFxuICAgICAgICAgICAgaXNQcml2YXRlQnJvd3Npbmc6IGZhbHNlXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gdmlhOiBodHRwczovL2dpc3QuZ2l0aHViLmNvbS9jb3U5MjkvNzk3Mzk1NlxuXG4gICAgZnVuY3Rpb24gcmV0cnkoaXNEb25lLCBuZXh0KSB7XG4gICAgICAgIHZhciBjdXJyZW50VHJpYWwgPSAwLFxuICAgICAgICAgICAgbWF4UmV0cnkgPSA1MCxcbiAgICAgICAgICAgIGludGVydmFsID0gMTAsXG4gICAgICAgICAgICBpc1RpbWVvdXQgPSBmYWxzZTtcbiAgICAgICAgdmFyIGlkID0gd2luZG93LnNldEludGVydmFsKFxuICAgICAgICAgICAgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzRG9uZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5jbGVhckludGVydmFsKGlkKTtcbiAgICAgICAgICAgICAgICAgICAgbmV4dChpc1RpbWVvdXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudFRyaWFsKysgPiBtYXhSZXRyeSkge1xuICAgICAgICAgICAgICAgICAgICB3aW5kb3cuY2xlYXJJbnRlcnZhbChpZCk7XG4gICAgICAgICAgICAgICAgICAgIGlzVGltZW91dCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIG5leHQoaXNUaW1lb3V0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgMTBcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc0lFMTBPckxhdGVyKHVzZXJBZ2VudCkge1xuICAgICAgICB2YXIgdWEgPSB1c2VyQWdlbnQudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgaWYgKHVhLmluZGV4T2YoJ21zaWUnKSA9PT0gMCAmJiB1YS5pbmRleE9mKCd0cmlkZW50JykgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbWF0Y2ggPSAvKD86bXNpZXxydjopXFxzPyhbXFxkXFwuXSspLy5leGVjKHVhKTtcbiAgICAgICAgaWYgKG1hdGNoICYmIHBhcnNlSW50KG1hdGNoWzFdLCAxMCkgPj0gMTApIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkZXRlY3RQcml2YXRlTW9kZShjYWxsYmFjaykge1xuICAgICAgICB2YXIgaXNQcml2YXRlO1xuXG4gICAgICAgIHRyeSB7XG5cbiAgICAgICAgICAgIGlmICh3aW5kb3cud2Via2l0UmVxdWVzdEZpbGVTeXN0ZW0pIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cud2Via2l0UmVxdWVzdEZpbGVTeXN0ZW0oXG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5URU1QT1JBUlksIDEsXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaXNQcml2YXRlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzUHJpdmF0ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh3aW5kb3cuaW5kZXhlZERCICYmIC9GaXJlZm94Ly50ZXN0KHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50KSkge1xuICAgICAgICAgICAgICAgIHZhciBkYjtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBkYiA9IHdpbmRvdy5pbmRleGVkREIub3BlbigndGVzdCcpO1xuICAgICAgICAgICAgICAgICAgICBkYi5vbmVycm9yID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlzUHJpdmF0ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBpc1ByaXZhdGUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHJ5KFxuICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gaXNEb25lKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkYi5yZWFkeVN0YXRlID09PSAnZG9uZScgPyB0cnVlIDogZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gbmV4dChpc1RpbWVvdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVGltZW91dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1ByaXZhdGUgPSBkYi5yZXN1bHQgPyBmYWxzZSA6IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNJRTEwT3JMYXRlcih3aW5kb3cubmF2aWdhdG9yLnVzZXJBZ2VudCkpIHtcbiAgICAgICAgICAgICAgICBpc1ByaXZhdGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXdpbmRvdy5pbmRleGVkREIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzUHJpdmF0ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlzUHJpdmF0ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmICh3aW5kb3cubG9jYWxTdG9yYWdlICYmIC9TYWZhcmkvLnRlc3Qod2luZG93Lm5hdmlnYXRvci51c2VyQWdlbnQpKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgd2luZG93LmxvY2FsU3RvcmFnZS5zZXRJdGVtKCd0ZXN0JywgMSk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICBpc1ByaXZhdGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaXNQcml2YXRlID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBpc1ByaXZhdGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgd2luZG93LmxvY2FsU3RvcmFnZS5yZW1vdmVJdGVtKCd0ZXN0Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGlzUHJpdmF0ZSA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0cnkoXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0RvbmUoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBpc1ByaXZhdGUgIT09ICd1bmRlZmluZWQnID8gdHJ1ZSA6IGZhbHNlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZ1bmN0aW9uIG5leHQoaXNUaW1lb3V0KSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soaXNQcml2YXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICB2YXIgaXNNb2JpbGUgPSB7XG4gICAgICAgIEFuZHJvaWQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goL0FuZHJvaWQvaSk7XG4gICAgICAgIH0sXG4gICAgICAgIEJsYWNrQmVycnk6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goL0JsYWNrQmVycnl8QkIxMC9pKTtcbiAgICAgICAgfSxcbiAgICAgICAgaU9TOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiBuYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKC9pUGhvbmV8aVBhZHxpUG9kL2kpO1xuICAgICAgICB9LFxuICAgICAgICBPcGVyYTogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gbmF2aWdhdG9yLnVzZXJBZ2VudC5tYXRjaCgvT3BlcmEgTWluaS9pKTtcbiAgICAgICAgfSxcbiAgICAgICAgV2luZG93czogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gbmF2aWdhdG9yLnVzZXJBZ2VudC5tYXRjaCgvSUVNb2JpbGUvaSk7XG4gICAgICAgIH0sXG4gICAgICAgIGFueTogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gKGlzTW9iaWxlLkFuZHJvaWQoKSB8fCBpc01vYmlsZS5CbGFja0JlcnJ5KCkgfHwgaXNNb2JpbGUuaU9TKCkgfHwgaXNNb2JpbGUuT3BlcmEoKSB8fCBpc01vYmlsZS5XaW5kb3dzKCkpO1xuICAgICAgICB9LFxuICAgICAgICBnZXRPc05hbWU6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIG9zTmFtZSA9ICdVbmtub3duIE9TJztcbiAgICAgICAgICAgIGlmIChpc01vYmlsZS5BbmRyb2lkKCkpIHtcbiAgICAgICAgICAgICAgICBvc05hbWUgPSAnQW5kcm9pZCc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChpc01vYmlsZS5CbGFja0JlcnJ5KCkpIHtcbiAgICAgICAgICAgICAgICBvc05hbWUgPSAnQmxhY2tCZXJyeSc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChpc01vYmlsZS5pT1MoKSkge1xuICAgICAgICAgICAgICAgIG9zTmFtZSA9ICdpT1MnO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoaXNNb2JpbGUuT3BlcmEoKSkge1xuICAgICAgICAgICAgICAgIG9zTmFtZSA9ICdPcGVyYSBNaW5pJztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGlzTW9iaWxlLldpbmRvd3MoKSkge1xuICAgICAgICAgICAgICAgIG9zTmFtZSA9ICdXaW5kb3dzJztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIG9zTmFtZTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvLyB2aWE6IGh0dHA6Ly9qc2ZpZGRsZS5uZXQvQ2hyaXN0aWFuTC9BVnlORC9cbiAgICBmdW5jdGlvbiBkZXRlY3REZXNrdG9wT1MoKSB7XG4gICAgICAgIHZhciB1bmtub3duID0gJy0nO1xuXG4gICAgICAgIHZhciBuVmVyID0gbmF2aWdhdG9yLmFwcFZlcnNpb247XG4gICAgICAgIHZhciBuQWd0ID0gbmF2aWdhdG9yLnVzZXJBZ2VudDtcblxuICAgICAgICB2YXIgb3MgPSB1bmtub3duO1xuICAgICAgICB2YXIgY2xpZW50U3RyaW5ncyA9IFt7XG4gICAgICAgICAgICBzOiAnV2luZG93cyAxMCcsXG4gICAgICAgICAgICByOiAvKFdpbmRvd3MgMTAuMHxXaW5kb3dzIE5UIDEwLjApL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnV2luZG93cyA4LjEnLFxuICAgICAgICAgICAgcjogLyhXaW5kb3dzIDguMXxXaW5kb3dzIE5UIDYuMykvXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHM6ICdXaW5kb3dzIDgnLFxuICAgICAgICAgICAgcjogLyhXaW5kb3dzIDh8V2luZG93cyBOVCA2LjIpL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnV2luZG93cyA3JyxcbiAgICAgICAgICAgIHI6IC8oV2luZG93cyA3fFdpbmRvd3MgTlQgNi4xKS9cbiAgICAgICAgfSwge1xuICAgICAgICAgICAgczogJ1dpbmRvd3MgVmlzdGEnLFxuICAgICAgICAgICAgcjogL1dpbmRvd3MgTlQgNi4wL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnV2luZG93cyBTZXJ2ZXIgMjAwMycsXG4gICAgICAgICAgICByOiAvV2luZG93cyBOVCA1LjIvXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHM6ICdXaW5kb3dzIFhQJyxcbiAgICAgICAgICAgIHI6IC8oV2luZG93cyBOVCA1LjF8V2luZG93cyBYUCkvXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHM6ICdXaW5kb3dzIDIwMDAnLFxuICAgICAgICAgICAgcjogLyhXaW5kb3dzIE5UIDUuMHxXaW5kb3dzIDIwMDApL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnV2luZG93cyBNRScsXG4gICAgICAgICAgICByOiAvKFdpbiA5eCA0LjkwfFdpbmRvd3MgTUUpL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnV2luZG93cyA5OCcsXG4gICAgICAgICAgICByOiAvKFdpbmRvd3MgOTh8V2luOTgpL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnV2luZG93cyA5NScsXG4gICAgICAgICAgICByOiAvKFdpbmRvd3MgOTV8V2luOTV8V2luZG93c185NSkvXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHM6ICdXaW5kb3dzIE5UIDQuMCcsXG4gICAgICAgICAgICByOiAvKFdpbmRvd3MgTlQgNC4wfFdpbk5UNC4wfFdpbk5UfFdpbmRvd3MgTlQpL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnV2luZG93cyBDRScsXG4gICAgICAgICAgICByOiAvV2luZG93cyBDRS9cbiAgICAgICAgfSwge1xuICAgICAgICAgICAgczogJ1dpbmRvd3MgMy4xMScsXG4gICAgICAgICAgICByOiAvV2luMTYvXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHM6ICdBbmRyb2lkJyxcbiAgICAgICAgICAgIHI6IC9BbmRyb2lkL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnT3BlbiBCU0QnLFxuICAgICAgICAgICAgcjogL09wZW5CU0QvXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHM6ICdTdW4gT1MnLFxuICAgICAgICAgICAgcjogL1N1bk9TL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnTGludXgnLFxuICAgICAgICAgICAgcjogLyhMaW51eHxYMTEpL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnaU9TJyxcbiAgICAgICAgICAgIHI6IC8oaVBob25lfGlQYWR8aVBvZCkvXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHM6ICdNYWMgT1MgWCcsXG4gICAgICAgICAgICByOiAvTWFjIE9TIFgvXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHM6ICdNYWMgT1MnLFxuICAgICAgICAgICAgcjogLyhNYWNQUEN8TWFjSW50ZWx8TWFjX1Bvd2VyUEN8TWFjaW50b3NoKS9cbiAgICAgICAgfSwge1xuICAgICAgICAgICAgczogJ1FOWCcsXG4gICAgICAgICAgICByOiAvUU5YL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnVU5JWCcsXG4gICAgICAgICAgICByOiAvVU5JWC9cbiAgICAgICAgfSwge1xuICAgICAgICAgICAgczogJ0JlT1MnLFxuICAgICAgICAgICAgcjogL0JlT1MvXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHM6ICdPUy8yJyxcbiAgICAgICAgICAgIHI6IC9PU1xcLzIvXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHM6ICdTZWFyY2ggQm90JyxcbiAgICAgICAgICAgIHI6IC8obnVoa3xHb29nbGVib3R8WWFtbXlib3R8T3BlbmJvdHxTbHVycHxNU05Cb3R8QXNrIEplZXZlc1xcL1Rlb21hfGlhX2FyY2hpdmVyKS9cbiAgICAgICAgfV07XG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBjczsgY3MgPSBjbGllbnRTdHJpbmdzW2ldOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChjcy5yLnRlc3QobkFndCkpIHtcbiAgICAgICAgICAgICAgICBvcyA9IGNzLnM7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgb3NWZXJzaW9uID0gdW5rbm93bjtcblxuICAgICAgICBpZiAoL1dpbmRvd3MvLnRlc3Qob3MpKSB7XG4gICAgICAgICAgICBpZiAoL1dpbmRvd3MgKC4qKS8udGVzdChvcykpIHtcbiAgICAgICAgICAgICAgICBvc1ZlcnNpb24gPSAvV2luZG93cyAoLiopLy5leGVjKG9zKVsxXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG9zID0gJ1dpbmRvd3MnO1xuICAgICAgICB9XG5cbiAgICAgICAgc3dpdGNoIChvcykge1xuICAgICAgICAgICAgY2FzZSAnTWFjIE9TIFgnOlxuICAgICAgICAgICAgICAgIGlmICgvTWFjIE9TIFggKDEwW1xcLlxcX1xcZF0rKS8udGVzdChuQWd0KSkge1xuICAgICAgICAgICAgICAgICAgICBvc1ZlcnNpb24gPSAvTWFjIE9TIFggKDEwW1xcLlxcX1xcZF0rKS8uZXhlYyhuQWd0KVsxXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdBbmRyb2lkJzpcbiAgICAgICAgICAgICAgICBpZiAoL0FuZHJvaWQgKFtcXC5cXF9cXGRdKykvLnRlc3QobkFndCkpIHtcbiAgICAgICAgICAgICAgICAgICAgb3NWZXJzaW9uID0gL0FuZHJvaWQgKFtcXC5cXF9cXGRdKykvLmV4ZWMobkFndClbMV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnaU9TJzpcbiAgICAgICAgICAgICAgICBpZiAoL09TIChcXGQrKV8oXFxkKylfPyhcXGQrKT8vLnRlc3QobkFndCkpIHtcbiAgICAgICAgICAgICAgICAgICAgb3NWZXJzaW9uID0gL09TIChcXGQrKV8oXFxkKylfPyhcXGQrKT8vLmV4ZWMoblZlcik7XG4gICAgICAgICAgICAgICAgICAgIG9zVmVyc2lvbiA9IG9zVmVyc2lvblsxXSArICcuJyArIG9zVmVyc2lvblsyXSArICcuJyArIChvc1ZlcnNpb25bM10gfCAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgb3NOYW1lOiBvcyxcbiAgICAgICAgICAgIG9zVmVyc2lvbjogb3NWZXJzaW9uXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIG9zTmFtZSA9ICdVbmtub3duIE9TJztcbiAgICB2YXIgb3NWZXJzaW9uID0gJ1Vua25vd24gT1MgVmVyc2lvbic7XG5cbiAgICBmdW5jdGlvbiBnZXRBbmRyb2lkVmVyc2lvbih1YSkge1xuICAgICAgICB1YSA9ICh1YSB8fCBuYXZpZ2F0b3IudXNlckFnZW50KS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICB2YXIgbWF0Y2ggPSB1YS5tYXRjaCgvYW5kcm9pZFxccyhbMC05XFwuXSopLyk7XG4gICAgICAgIHJldHVybiBtYXRjaCA/IG1hdGNoWzFdIDogZmFsc2U7XG4gICAgfVxuXG4gICAgdmFyIG9zSW5mbyA9IGRldGVjdERlc2t0b3BPUygpO1xuXG4gICAgaWYgKG9zSW5mbyAmJiBvc0luZm8ub3NOYW1lICYmIG9zSW5mby5vc05hbWUgIT0gJy0nKSB7XG4gICAgICAgIG9zTmFtZSA9IG9zSW5mby5vc05hbWU7XG4gICAgICAgIG9zVmVyc2lvbiA9IG9zSW5mby5vc1ZlcnNpb247XG4gICAgfSBlbHNlIGlmIChpc01vYmlsZS5hbnkoKSkge1xuICAgICAgICBvc05hbWUgPSBpc01vYmlsZS5nZXRPc05hbWUoKTtcblxuICAgICAgICBpZiAob3NOYW1lID09ICdBbmRyb2lkJykge1xuICAgICAgICAgICAgb3NWZXJzaW9uID0gZ2V0QW5kcm9pZFZlcnNpb24oKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBpc05vZGVqcyA9IHR5cGVvZiBwcm9jZXNzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgcHJvY2Vzcy52ZXJzaW9ucyA9PT0gJ29iamVjdCcgJiYgcHJvY2Vzcy52ZXJzaW9ucy5ub2RlO1xuXG4gICAgaWYgKG9zTmFtZSA9PT0gJ1Vua25vd24gT1MnICYmIGlzTm9kZWpzKSB7XG4gICAgICAgIG9zTmFtZSA9ICdOb2RlanMnO1xuICAgICAgICBvc1ZlcnNpb24gPSBwcm9jZXNzLnZlcnNpb25zLm5vZGUudG9TdHJpbmcoKS5yZXBsYWNlKCd2JywgJycpO1xuICAgIH1cblxuICAgIHZhciBpc0NhbnZhc1N1cHBvcnRzU3RyZWFtQ2FwdHVyaW5nID0gZmFsc2U7XG4gICAgdmFyIGlzVmlkZW9TdXBwb3J0c1N0cmVhbUNhcHR1cmluZyA9IGZhbHNlO1xuICAgIFsnY2FwdHVyZVN0cmVhbScsICdtb3pDYXB0dXJlU3RyZWFtJywgJ3dlYmtpdENhcHR1cmVTdHJlYW0nXS5mb3JFYWNoKGZ1bmN0aW9uKGl0ZW0pIHtcbiAgICAgICAgaWYgKHR5cGVvZiBkb2N1bWVudCA9PT0gJ3VuZGVmaW5lZCcgfHwgdHlwZW9mIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghaXNDYW52YXNTdXBwb3J0c1N0cmVhbUNhcHR1cmluZyAmJiBpdGVtIGluIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpKSB7XG4gICAgICAgICAgICBpc0NhbnZhc1N1cHBvcnRzU3RyZWFtQ2FwdHVyaW5nID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghaXNWaWRlb1N1cHBvcnRzU3RyZWFtQ2FwdHVyaW5nICYmIGl0ZW0gaW4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKSkge1xuICAgICAgICAgICAgaXNWaWRlb1N1cHBvcnRzU3RyZWFtQ2FwdHVyaW5nID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gdmlhOiBodHRwczovL2dpdGh1Yi5jb20vZGlhZnlnaS93ZWJydGMtaXBzXG4gICAgZnVuY3Rpb24gRGV0ZWN0TG9jYWxJUEFkZHJlc3MoY2FsbGJhY2ssIHN0cmVhbSkge1xuICAgICAgICBpZiAoIURldGVjdFJUQy5pc1dlYlJUQ1N1cHBvcnRlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2V0SVBzKGZ1bmN0aW9uKGlwKSB7XG4gICAgICAgICAgICBpZiAoaXAubWF0Y2goL14oMTkyXFwuMTY4XFwufDE2OVxcLjI1NFxcLnwxMFxcLnwxNzJcXC4oMVs2LTldfDJcXGR8M1swMV0pKS8pKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soJ0xvY2FsOiAnICsgaXApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygnUHVibGljOiAnICsgaXApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCBzdHJlYW0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldElQcyhjYWxsYmFjaywgc3RyZWFtKSB7XG4gICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgPT09ICd1bmRlZmluZWQnIHx8IHR5cGVvZiBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGlwRHVwbGljYXRlcyA9IHt9O1xuXG4gICAgICAgIHZhciBSVENQZWVyQ29ubmVjdGlvbiA9IHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiB8fCB3aW5kb3cubW96UlRDUGVlckNvbm5lY3Rpb24gfHwgd2luZG93LndlYmtpdFJUQ1BlZXJDb25uZWN0aW9uO1xuXG4gICAgICAgIGlmICghUlRDUGVlckNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIHZhciBpZnJhbWUgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnaWZyYW1lJyk7XG4gICAgICAgICAgICBpZiAoIWlmcmFtZSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciB3aW4gPSBpZnJhbWUuY29udGVudFdpbmRvdztcbiAgICAgICAgICAgIFJUQ1BlZXJDb25uZWN0aW9uID0gd2luLlJUQ1BlZXJDb25uZWN0aW9uIHx8IHdpbi5tb3pSVENQZWVyQ29ubmVjdGlvbiB8fCB3aW4ud2Via2l0UlRDUGVlckNvbm5lY3Rpb247XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIVJUQ1BlZXJDb25uZWN0aW9uKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcGVlckNvbmZpZyA9IG51bGw7XG5cbiAgICAgICAgaWYgKERldGVjdFJUQy5icm93c2VyID09PSAnQ2hyb21lJyAmJiBEZXRlY3RSVEMuYnJvd3Nlci52ZXJzaW9uIDwgNTgpIHtcbiAgICAgICAgICAgIC8vIHRvZG86IGFkZCBzdXBwb3J0IGZvciBvbGRlciBPcGVyYVxuICAgICAgICAgICAgcGVlckNvbmZpZyA9IHtcbiAgICAgICAgICAgICAgICBvcHRpb25hbDogW3tcbiAgICAgICAgICAgICAgICAgICAgUnRwRGF0YUNoYW5uZWxzOiB0cnVlXG4gICAgICAgICAgICAgICAgfV1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc2VydmVycyA9IHtcbiAgICAgICAgICAgIGljZVNlcnZlcnM6IFt7XG4gICAgICAgICAgICAgICAgdXJsczogJ3N0dW46c3R1bi5sLmdvb2dsZS5jb206MTkzMDInXG4gICAgICAgICAgICB9XVxuICAgICAgICB9O1xuXG4gICAgICAgIHZhciBwYyA9IG5ldyBSVENQZWVyQ29ubmVjdGlvbihzZXJ2ZXJzLCBwZWVyQ29uZmlnKTtcblxuICAgICAgICBpZiAoc3RyZWFtKSB7XG4gICAgICAgICAgICBpZiAocGMuYWRkU3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgcGMuYWRkU3RyZWFtKHN0cmVhbSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHBjLmFkZFRyYWNrICYmIHN0cmVhbS5nZXRUcmFja3MoKVswXSkge1xuICAgICAgICAgICAgICAgIHBjLmFkZFRyYWNrKHN0cmVhbS5nZXRUcmFja3MoKVswXSwgc3RyZWFtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGhhbmRsZUNhbmRpZGF0ZShjYW5kaWRhdGUpIHtcbiAgICAgICAgICAgIHZhciBpcFJlZ2V4ID0gLyhbMC05XXsxLDN9KFxcLlswLTldezEsM30pezN9KS87XG4gICAgICAgICAgICB2YXIgbWF0Y2ggPSBpcFJlZ2V4LmV4ZWMoY2FuZGlkYXRlKTtcbiAgICAgICAgICAgIGlmICghbWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgaXBBZGRyZXNzID0gbWF0Y2hbMV07XG5cbiAgICAgICAgICAgIGlmIChpcER1cGxpY2F0ZXNbaXBBZGRyZXNzXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soaXBBZGRyZXNzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaXBEdXBsaWNhdGVzW2lwQWRkcmVzc10gPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gbGlzdGVuIGZvciBjYW5kaWRhdGUgZXZlbnRzXG4gICAgICAgIHBjLm9uaWNlY2FuZGlkYXRlID0gZnVuY3Rpb24oaWNlKSB7XG4gICAgICAgICAgICBpZiAoaWNlLmNhbmRpZGF0ZSkge1xuICAgICAgICAgICAgICAgIGhhbmRsZUNhbmRpZGF0ZShpY2UuY2FuZGlkYXRlLmNhbmRpZGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gY3JlYXRlIGRhdGEgY2hhbm5lbFxuICAgICAgICBpZiAoIXN0cmVhbSkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBwYy5jcmVhdGVEYXRhQ2hhbm5lbCgnc2N0cCcsIHt9KTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjcmVhdGUgYW4gb2ZmZXIgc2RwXG4gICAgICAgIGlmIChEZXRlY3RSVEMuaXNQcm9taXNlc1N1cHBvcnRlZCkge1xuICAgICAgICAgICAgcGMuY3JlYXRlT2ZmZXIoKS50aGVuKGZ1bmN0aW9uKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgIHBjLnNldExvY2FsRGVzY3JpcHRpb24ocmVzdWx0KS50aGVuKGFmdGVyQ3JlYXRlT2ZmZXIpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwYy5jcmVhdGVPZmZlcihmdW5jdGlvbihyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICBwYy5zZXRMb2NhbERlc2NyaXB0aW9uKHJlc3VsdCwgYWZ0ZXJDcmVhdGVPZmZlciwgZnVuY3Rpb24oKSB7fSk7XG4gICAgICAgICAgICB9LCBmdW5jdGlvbigpIHt9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGFmdGVyQ3JlYXRlT2ZmZXIoKSB7XG4gICAgICAgICAgICB2YXIgbGluZXMgPSBwYy5sb2NhbERlc2NyaXB0aW9uLnNkcC5zcGxpdCgnXFxuJyk7XG5cbiAgICAgICAgICAgIGxpbmVzLmZvckVhY2goZnVuY3Rpb24obGluZSkge1xuICAgICAgICAgICAgICAgIGlmIChsaW5lLmluZGV4T2YoJ2E9Y2FuZGlkYXRlOicpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhbmRsZUNhbmRpZGF0ZShsaW5lKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBNZWRpYURldmljZXMgPSBbXTtcblxuICAgIHZhciBhdWRpb0lucHV0RGV2aWNlcyA9IFtdO1xuICAgIHZhciBhdWRpb091dHB1dERldmljZXMgPSBbXTtcbiAgICB2YXIgdmlkZW9JbnB1dERldmljZXMgPSBbXTtcblxuICAgIGlmIChuYXZpZ2F0b3IubWVkaWFEZXZpY2VzICYmIG5hdmlnYXRvci5tZWRpYURldmljZXMuZW51bWVyYXRlRGV2aWNlcykge1xuICAgICAgICAvLyBGaXJlZm94IDM4KyBzZWVtcyBoYXZpbmcgc3VwcG9ydCBvZiBlbnVtZXJhdGVEZXZpY2VzXG4gICAgICAgIC8vIFRoYW5rcyBAeGR1bWFpbmUvZW51bWVyYXRlRGV2aWNlc1xuICAgICAgICBuYXZpZ2F0b3IuZW51bWVyYXRlRGV2aWNlcyA9IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICB2YXIgZW51bWVyYXRlRGV2aWNlcyA9IG5hdmlnYXRvci5tZWRpYURldmljZXMuZW51bWVyYXRlRGV2aWNlcygpO1xuICAgICAgICAgICAgaWYgKGVudW1lcmF0ZURldmljZXMgJiYgZW51bWVyYXRlRGV2aWNlcy50aGVuKSB7XG4gICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKCkudGhlbihjYWxsYmFjaykuY2F0Y2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKFtdKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIE1lZGlhIERldmljZXMgZGV0ZWN0aW9uXG4gICAgdmFyIGNhbkVudW1lcmF0ZSA9IGZhbHNlO1xuXG4gICAgLypnbG9iYWwgTWVkaWFTdHJlYW1UcmFjazp0cnVlICovXG4gICAgaWYgKHR5cGVvZiBNZWRpYVN0cmVhbVRyYWNrICE9PSAndW5kZWZpbmVkJyAmJiAnZ2V0U291cmNlcycgaW4gTWVkaWFTdHJlYW1UcmFjaykge1xuICAgICAgICBjYW5FbnVtZXJhdGUgPSB0cnVlO1xuICAgIH0gZWxzZSBpZiAobmF2aWdhdG9yLm1lZGlhRGV2aWNlcyAmJiAhIW5hdmlnYXRvci5tZWRpYURldmljZXMuZW51bWVyYXRlRGV2aWNlcykge1xuICAgICAgICBjYW5FbnVtZXJhdGUgPSB0cnVlO1xuICAgIH1cblxuICAgIHZhciBoYXNNaWNyb3Bob25lID0gZmFsc2U7XG4gICAgdmFyIGhhc1NwZWFrZXJzID0gZmFsc2U7XG4gICAgdmFyIGhhc1dlYmNhbSA9IGZhbHNlO1xuXG4gICAgdmFyIGlzV2Vic2l0ZUhhc01pY3JvcGhvbmVQZXJtaXNzaW9ucyA9IGZhbHNlO1xuICAgIHZhciBpc1dlYnNpdGVIYXNXZWJjYW1QZXJtaXNzaW9ucyA9IGZhbHNlO1xuXG4gICAgLy8gaHR0cDovL2Rldi53My5vcmcvMjAxMS93ZWJydGMvZWRpdG9yL2dldHVzZXJtZWRpYS5odG1sI21lZGlhZGV2aWNlc1xuICAgIGZ1bmN0aW9uIGNoZWNrRGV2aWNlU3VwcG9ydChjYWxsYmFjaykge1xuICAgICAgICBpZiAoIWNhbkVudW1lcmF0ZSkge1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghbmF2aWdhdG9yLmVudW1lcmF0ZURldmljZXMgJiYgd2luZG93Lk1lZGlhU3RyZWFtVHJhY2sgJiYgd2luZG93Lk1lZGlhU3RyZWFtVHJhY2suZ2V0U291cmNlcykge1xuICAgICAgICAgICAgbmF2aWdhdG9yLmVudW1lcmF0ZURldmljZXMgPSB3aW5kb3cuTWVkaWFTdHJlYW1UcmFjay5nZXRTb3VyY2VzLmJpbmQod2luZG93Lk1lZGlhU3RyZWFtVHJhY2spO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFuYXZpZ2F0b3IuZW51bWVyYXRlRGV2aWNlcyAmJiBuYXZpZ2F0b3IuZW51bWVyYXRlRGV2aWNlcykge1xuICAgICAgICAgICAgbmF2aWdhdG9yLmVudW1lcmF0ZURldmljZXMgPSBuYXZpZ2F0b3IuZW51bWVyYXRlRGV2aWNlcy5iaW5kKG5hdmlnYXRvcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIW5hdmlnYXRvci5lbnVtZXJhdGVEZXZpY2VzKSB7XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgTWVkaWFEZXZpY2VzID0gW107XG5cbiAgICAgICAgYXVkaW9JbnB1dERldmljZXMgPSBbXTtcbiAgICAgICAgYXVkaW9PdXRwdXREZXZpY2VzID0gW107XG4gICAgICAgIHZpZGVvSW5wdXREZXZpY2VzID0gW107XG5cbiAgICAgICAgaGFzTWljcm9waG9uZSA9IGZhbHNlO1xuICAgICAgICBoYXNTcGVha2VycyA9IGZhbHNlO1xuICAgICAgICBoYXNXZWJjYW0gPSBmYWxzZTtcblxuICAgICAgICBpc1dlYnNpdGVIYXNNaWNyb3Bob25lUGVybWlzc2lvbnMgPSBmYWxzZTtcbiAgICAgICAgaXNXZWJzaXRlSGFzV2ViY2FtUGVybWlzc2lvbnMgPSBmYWxzZTtcblxuICAgICAgICAvLyB0byBwcmV2ZW50IGR1cGxpY2F0aW9uXG4gICAgICAgIHZhciBhbHJlYWR5VXNlZERldmljZXMgPSB7fTtcblxuICAgICAgICBuYXZpZ2F0b3IuZW51bWVyYXRlRGV2aWNlcyhmdW5jdGlvbihkZXZpY2VzKSB7XG4gICAgICAgICAgICBkZXZpY2VzLmZvckVhY2goZnVuY3Rpb24oX2RldmljZSkge1xuICAgICAgICAgICAgICAgIHZhciBkZXZpY2UgPSB7fTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBkIGluIF9kZXZpY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgX2RldmljZVtkXSAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRldmljZVtkXSA9IF9kZXZpY2VbZF07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFscmVhZHlVc2VkRGV2aWNlc1tkZXZpY2UuZGV2aWNlSWQgKyBkZXZpY2UubGFiZWwgKyBkZXZpY2Uua2luZF0pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGlmIGl0IGlzIE1lZGlhU3RyZWFtVHJhY2suZ2V0U291cmNlc1xuICAgICAgICAgICAgICAgIGlmIChkZXZpY2Uua2luZCA9PT0gJ2F1ZGlvJykge1xuICAgICAgICAgICAgICAgICAgICBkZXZpY2Uua2luZCA9ICdhdWRpb2lucHV0JztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoZGV2aWNlLmtpbmQgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgZGV2aWNlLmtpbmQgPSAndmlkZW9pbnB1dCc7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFkZXZpY2UuZGV2aWNlSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgZGV2aWNlLmRldmljZUlkID0gZGV2aWNlLmlkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghZGV2aWNlLmlkKSB7XG4gICAgICAgICAgICAgICAgICAgIGRldmljZS5pZCA9IGRldmljZS5kZXZpY2VJZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIWRldmljZS5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICBkZXZpY2UuaXNDdXN0b21MYWJlbCA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGRldmljZS5raW5kID09PSAndmlkZW9pbnB1dCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRldmljZS5sYWJlbCA9ICdDYW1lcmEgJyArICh2aWRlb0lucHV0RGV2aWNlcy5sZW5ndGggKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkZXZpY2Uua2luZCA9PT0gJ2F1ZGlvaW5wdXQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXZpY2UubGFiZWwgPSAnTWljcm9waG9uZSAnICsgKGF1ZGlvSW5wdXREZXZpY2VzLmxlbmd0aCArIDEpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRldmljZS5raW5kID09PSAnYXVkaW9vdXRwdXQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXZpY2UubGFiZWwgPSAnU3BlYWtlciAnICsgKGF1ZGlvT3V0cHV0RGV2aWNlcy5sZW5ndGggKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRldmljZS5sYWJlbCA9ICdQbGVhc2UgaW52b2tlIGdldFVzZXJNZWRpYSBvbmNlLic7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIERldGVjdFJUQyAhPT0gJ3VuZGVmaW5lZCcgJiYgRGV0ZWN0UlRDLmJyb3dzZXIuaXNDaHJvbWUgJiYgRGV0ZWN0UlRDLmJyb3dzZXIudmVyc2lvbiA+PSA0NiAmJiAhL14oaHR0cHM6fGNocm9tZS1leHRlbnNpb246KSQvZy50ZXN0KGxvY2F0aW9uLnByb3RvY29sIHx8ICcnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGRvY3VtZW50LmRvbWFpbiA9PT0gJ3N0cmluZycgJiYgZG9jdW1lbnQuZG9tYWluLnNlYXJjaCAmJiBkb2N1bWVudC5kb21haW4uc2VhcmNoKC9sb2NhbGhvc3R8MTI3LjAuL2cpID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRldmljZS5sYWJlbCA9ICdIVFRQcyBpcyByZXF1aXJlZCB0byBnZXQgbGFiZWwgb2YgdGhpcyAnICsgZGV2aWNlLmtpbmQgKyAnIGRldmljZS4nO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCBvbiBBbmRyb2lkIHN0aWxsIHJldHVybnMgZW1wdHkgbGFiZWxcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRldmljZS5raW5kID09PSAndmlkZW9pbnB1dCcgJiYgIWlzV2Vic2l0ZUhhc1dlYmNhbVBlcm1pc3Npb25zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc1dlYnNpdGVIYXNXZWJjYW1QZXJtaXNzaW9ucyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoZGV2aWNlLmtpbmQgPT09ICdhdWRpb2lucHV0JyAmJiAhaXNXZWJzaXRlSGFzTWljcm9waG9uZVBlcm1pc3Npb25zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc1dlYnNpdGVIYXNNaWNyb3Bob25lUGVybWlzc2lvbnMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGRldmljZS5raW5kID09PSAnYXVkaW9pbnB1dCcpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzTWljcm9waG9uZSA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGF1ZGlvSW5wdXREZXZpY2VzLmluZGV4T2YoZGV2aWNlKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvSW5wdXREZXZpY2VzLnB1c2goZGV2aWNlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChkZXZpY2Uua2luZCA9PT0gJ2F1ZGlvb3V0cHV0Jykge1xuICAgICAgICAgICAgICAgICAgICBoYXNTcGVha2VycyA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGF1ZGlvT3V0cHV0RGV2aWNlcy5pbmRleE9mKGRldmljZSkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhdWRpb091dHB1dERldmljZXMucHVzaChkZXZpY2UpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGRldmljZS5raW5kID09PSAndmlkZW9pbnB1dCcpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzV2ViY2FtID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodmlkZW9JbnB1dERldmljZXMuaW5kZXhPZihkZXZpY2UpID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmlkZW9JbnB1dERldmljZXMucHVzaChkZXZpY2UpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gdGhlcmUgaXMgbm8gJ3ZpZGVvb3VwdXQnIGluIHRoZSBzcGVjLlxuICAgICAgICAgICAgICAgIE1lZGlhRGV2aWNlcy5wdXNoKGRldmljZSk7XG5cbiAgICAgICAgICAgICAgICBhbHJlYWR5VXNlZERldmljZXNbZGV2aWNlLmRldmljZUlkICsgZGV2aWNlLmxhYmVsICsgZGV2aWNlLmtpbmRdID0gZGV2aWNlO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgRGV0ZWN0UlRDICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIC8vIHRvIHN5bmMgbGF0ZXN0IG91dHB1dHNcbiAgICAgICAgICAgICAgICBEZXRlY3RSVEMuTWVkaWFEZXZpY2VzID0gTWVkaWFEZXZpY2VzO1xuICAgICAgICAgICAgICAgIERldGVjdFJUQy5oYXNNaWNyb3Bob25lID0gaGFzTWljcm9waG9uZTtcbiAgICAgICAgICAgICAgICBEZXRlY3RSVEMuaGFzU3BlYWtlcnMgPSBoYXNTcGVha2VycztcbiAgICAgICAgICAgICAgICBEZXRlY3RSVEMuaGFzV2ViY2FtID0gaGFzV2ViY2FtO1xuXG4gICAgICAgICAgICAgICAgRGV0ZWN0UlRDLmlzV2Vic2l0ZUhhc1dlYmNhbVBlcm1pc3Npb25zID0gaXNXZWJzaXRlSGFzV2ViY2FtUGVybWlzc2lvbnM7XG4gICAgICAgICAgICAgICAgRGV0ZWN0UlRDLmlzV2Vic2l0ZUhhc01pY3JvcGhvbmVQZXJtaXNzaW9ucyA9IGlzV2Vic2l0ZUhhc01pY3JvcGhvbmVQZXJtaXNzaW9ucztcblxuICAgICAgICAgICAgICAgIERldGVjdFJUQy5hdWRpb0lucHV0RGV2aWNlcyA9IGF1ZGlvSW5wdXREZXZpY2VzO1xuICAgICAgICAgICAgICAgIERldGVjdFJUQy5hdWRpb091dHB1dERldmljZXMgPSBhdWRpb091dHB1dERldmljZXM7XG4gICAgICAgICAgICAgICAgRGV0ZWN0UlRDLnZpZGVvSW5wdXREZXZpY2VzID0gdmlkZW9JbnB1dERldmljZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHZhciBEZXRlY3RSVEMgPSB3aW5kb3cuRGV0ZWN0UlRDIHx8IHt9O1xuXG4gICAgLy8gLS0tLS0tLS0tLVxuICAgIC8vIERldGVjdFJUQy5icm93c2VyLm5hbWUgfHwgRGV0ZWN0UlRDLmJyb3dzZXIudmVyc2lvbiB8fCBEZXRlY3RSVEMuYnJvd3Nlci5mdWxsVmVyc2lvblxuICAgIERldGVjdFJUQy5icm93c2VyID0gZ2V0QnJvd3NlckluZm8oKTtcblxuICAgIGRldGVjdFByaXZhdGVNb2RlKGZ1bmN0aW9uKGlzUHJpdmF0ZUJyb3dzaW5nKSB7XG4gICAgICAgIERldGVjdFJUQy5icm93c2VyLmlzUHJpdmF0ZUJyb3dzaW5nID0gISFpc1ByaXZhdGVCcm93c2luZztcbiAgICB9KTtcblxuICAgIC8vIERldGVjdFJUQy5pc0Nocm9tZSB8fCBEZXRlY3RSVEMuaXNGaXJlZm94IHx8IERldGVjdFJUQy5pc0VkZ2VcbiAgICBEZXRlY3RSVEMuYnJvd3NlclsnaXMnICsgRGV0ZWN0UlRDLmJyb3dzZXIubmFtZV0gPSB0cnVlO1xuXG4gICAgLy8gLS0tLS0tLS0tLS1cbiAgICBEZXRlY3RSVEMub3NOYW1lID0gb3NOYW1lO1xuICAgIERldGVjdFJUQy5vc1ZlcnNpb24gPSBvc1ZlcnNpb247XG5cbiAgICB2YXIgaXNOb2RlV2Via2l0ID0gdHlwZW9mIHByb2Nlc3MgPT09ICdvYmplY3QnICYmIHR5cGVvZiBwcm9jZXNzLnZlcnNpb25zID09PSAnb2JqZWN0JyAmJiBwcm9jZXNzLnZlcnNpb25zWydub2RlLXdlYmtpdCddO1xuXG4gICAgLy8gLS0tLS0tLS0tIERldGVjdCBpZiBzeXN0ZW0gc3VwcG9ydHMgV2ViUlRDIDEuMCBvciBXZWJSVEMgMS4xLlxuICAgIHZhciBpc1dlYlJUQ1N1cHBvcnRlZCA9IGZhbHNlO1xuICAgIFsnUlRDUGVlckNvbm5lY3Rpb24nLCAnd2Via2l0UlRDUGVlckNvbm5lY3Rpb24nLCAnbW96UlRDUGVlckNvbm5lY3Rpb24nLCAnUlRDSWNlR2F0aGVyZXInXS5mb3JFYWNoKGZ1bmN0aW9uKGl0ZW0pIHtcbiAgICAgICAgaWYgKGlzV2ViUlRDU3VwcG9ydGVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaXRlbSBpbiB3aW5kb3cpIHtcbiAgICAgICAgICAgIGlzV2ViUlRDU3VwcG9ydGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIERldGVjdFJUQy5pc1dlYlJUQ1N1cHBvcnRlZCA9IGlzV2ViUlRDU3VwcG9ydGVkO1xuXG4gICAgLy8tLS0tLS0tXG4gICAgRGV0ZWN0UlRDLmlzT1JUQ1N1cHBvcnRlZCA9IHR5cGVvZiBSVENJY2VHYXRoZXJlciAhPT0gJ3VuZGVmaW5lZCc7XG5cbiAgICAvLyAtLS0tLS0tLS0gRGV0ZWN0IGlmIFdlYkF1ZGlvIEFQSSBhcmUgc3VwcG9ydGVkXG4gICAgdmFyIHdlYkF1ZGlvID0ge1xuICAgICAgICBpc1N1cHBvcnRlZDogZmFsc2UsXG4gICAgICAgIGlzQ3JlYXRlTWVkaWFTdHJlYW1Tb3VyY2VTdXBwb3J0ZWQ6IGZhbHNlXG4gICAgfTtcblxuICAgIFsnQXVkaW9Db250ZXh0JywgJ3dlYmtpdEF1ZGlvQ29udGV4dCcsICdtb3pBdWRpb0NvbnRleHQnLCAnbXNBdWRpb0NvbnRleHQnXS5mb3JFYWNoKGZ1bmN0aW9uKGl0ZW0pIHtcbiAgICAgICAgaWYgKHdlYkF1ZGlvLmlzU3VwcG9ydGVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaXRlbSBpbiB3aW5kb3cpIHtcbiAgICAgICAgICAgIHdlYkF1ZGlvLmlzU3VwcG9ydGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgaWYgKHdpbmRvd1tpdGVtXSAmJiAnY3JlYXRlTWVkaWFTdHJlYW1Tb3VyY2UnIGluIHdpbmRvd1tpdGVtXS5wcm90b3R5cGUpIHtcbiAgICAgICAgICAgICAgICB3ZWJBdWRpby5pc0NyZWF0ZU1lZGlhU3RyZWFtU291cmNlU3VwcG9ydGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xuICAgIERldGVjdFJUQy5pc0F1ZGlvQ29udGV4dFN1cHBvcnRlZCA9IHdlYkF1ZGlvLmlzU3VwcG9ydGVkO1xuICAgIERldGVjdFJUQy5pc0NyZWF0ZU1lZGlhU3RyZWFtU291cmNlU3VwcG9ydGVkID0gd2ViQXVkaW8uaXNDcmVhdGVNZWRpYVN0cmVhbVNvdXJjZVN1cHBvcnRlZDtcblxuICAgIC8vIC0tLS0tLS0tLS0gRGV0ZWN0IGlmIFNDVFAvUlRQIGNoYW5uZWxzIGFyZSBzdXBwb3J0ZWQuXG5cbiAgICB2YXIgaXNSdHBEYXRhQ2hhbm5lbHNTdXBwb3J0ZWQgPSBmYWxzZTtcbiAgICBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIuaXNDaHJvbWUgJiYgRGV0ZWN0UlRDLmJyb3dzZXIudmVyc2lvbiA+IDMxKSB7XG4gICAgICAgIGlzUnRwRGF0YUNoYW5uZWxzU3VwcG9ydGVkID0gdHJ1ZTtcbiAgICB9XG4gICAgRGV0ZWN0UlRDLmlzUnRwRGF0YUNoYW5uZWxzU3VwcG9ydGVkID0gaXNSdHBEYXRhQ2hhbm5lbHNTdXBwb3J0ZWQ7XG5cbiAgICB2YXIgaXNTQ1RQU3VwcG9ydGQgPSBmYWxzZTtcbiAgICBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIuaXNGaXJlZm94ICYmIERldGVjdFJUQy5icm93c2VyLnZlcnNpb24gPiAyOCkge1xuICAgICAgICBpc1NDVFBTdXBwb3J0ZCA9IHRydWU7XG4gICAgfSBlbHNlIGlmIChEZXRlY3RSVEMuYnJvd3Nlci5pc0Nocm9tZSAmJiBEZXRlY3RSVEMuYnJvd3Nlci52ZXJzaW9uID4gMjUpIHtcbiAgICAgICAgaXNTQ1RQU3VwcG9ydGQgPSB0cnVlO1xuICAgIH0gZWxzZSBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIuaXNPcGVyYSAmJiBEZXRlY3RSVEMuYnJvd3Nlci52ZXJzaW9uID49IDExKSB7XG4gICAgICAgIGlzU0NUUFN1cHBvcnRkID0gdHJ1ZTtcbiAgICB9XG4gICAgRGV0ZWN0UlRDLmlzU2N0cERhdGFDaGFubmVsc1N1cHBvcnRlZCA9IGlzU0NUUFN1cHBvcnRkO1xuXG4gICAgLy8gLS0tLS0tLS0tXG5cbiAgICBEZXRlY3RSVEMuaXNNb2JpbGVEZXZpY2UgPSBpc01vYmlsZURldmljZTsgLy8gXCJpc01vYmlsZURldmljZVwiIGJvb2xlYW4gaXMgZGVmaW5lZCBpbiBcImdldEJyb3dzZXJJbmZvLmpzXCJcblxuICAgIC8vIC0tLS0tLVxuICAgIHZhciBpc0dldFVzZXJNZWRpYVN1cHBvcnRlZCA9IGZhbHNlO1xuICAgIGlmIChuYXZpZ2F0b3IuZ2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGlzR2V0VXNlck1lZGlhU3VwcG9ydGVkID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKG5hdmlnYXRvci5tZWRpYURldmljZXMgJiYgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEpIHtcbiAgICAgICAgaXNHZXRVc2VyTWVkaWFTdXBwb3J0ZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIGlmIChEZXRlY3RSVEMuYnJvd3Nlci5pc0Nocm9tZSAmJiBEZXRlY3RSVEMuYnJvd3Nlci52ZXJzaW9uID49IDQ2ICYmICEvXihodHRwczp8Y2hyb21lLWV4dGVuc2lvbjopJC9nLnRlc3QobG9jYXRpb24ucHJvdG9jb2wgfHwgJycpKSB7XG4gICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBkb2N1bWVudC5kb21haW4gPT09ICdzdHJpbmcnICYmIGRvY3VtZW50LmRvbWFpbi5zZWFyY2ggJiYgZG9jdW1lbnQuZG9tYWluLnNlYXJjaCgvbG9jYWxob3N0fDEyNy4wLi9nKSA9PT0gLTEpIHtcbiAgICAgICAgICAgIGlzR2V0VXNlck1lZGlhU3VwcG9ydGVkID0gJ1JlcXVpcmVzIEhUVFBzJztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmIChEZXRlY3RSVEMub3NOYW1lID09PSAnTm9kZWpzJykge1xuICAgICAgICBpc0dldFVzZXJNZWRpYVN1cHBvcnRlZCA9IGZhbHNlO1xuICAgIH1cbiAgICBEZXRlY3RSVEMuaXNHZXRVc2VyTWVkaWFTdXBwb3J0ZWQgPSBpc0dldFVzZXJNZWRpYVN1cHBvcnRlZDtcblxuICAgIHZhciBkaXNwbGF5UmVzb2x1dGlvbiA9ICcnO1xuICAgIGlmIChzY3JlZW4ud2lkdGgpIHtcbiAgICAgICAgdmFyIHdpZHRoID0gKHNjcmVlbi53aWR0aCkgPyBzY3JlZW4ud2lkdGggOiAnJztcbiAgICAgICAgdmFyIGhlaWdodCA9IChzY3JlZW4uaGVpZ2h0KSA/IHNjcmVlbi5oZWlnaHQgOiAnJztcbiAgICAgICAgZGlzcGxheVJlc29sdXRpb24gKz0gJycgKyB3aWR0aCArICcgeCAnICsgaGVpZ2h0O1xuICAgIH1cbiAgICBEZXRlY3RSVEMuZGlzcGxheVJlc29sdXRpb24gPSBkaXNwbGF5UmVzb2x1dGlvbjtcblxuICAgIGZ1bmN0aW9uIGdldEFzcGVjdFJhdGlvKHcsIGgpIHtcbiAgICAgICAgZnVuY3Rpb24gZ2NkKGEsIGIpIHtcbiAgICAgICAgICAgIHJldHVybiAoYiA9PSAwKSA/IGEgOiBnY2QoYiwgYSAlIGIpO1xuICAgICAgICB9XG4gICAgICAgIHZhciByID0gZ2NkKHcsIGgpO1xuICAgICAgICByZXR1cm4gKHcgLyByKSAvIChoIC8gcik7XG4gICAgfVxuXG4gICAgRGV0ZWN0UlRDLmRpc3BsYXlBc3BlY3RSYXRpbyA9IGdldEFzcGVjdFJhdGlvKHNjcmVlbi53aWR0aCwgc2NyZWVuLmhlaWdodCkudG9GaXhlZCgyKTtcblxuICAgIC8vIC0tLS0tLS0tLS1cbiAgICBEZXRlY3RSVEMuaXNDYW52YXNTdXBwb3J0c1N0cmVhbUNhcHR1cmluZyA9IGlzQ2FudmFzU3VwcG9ydHNTdHJlYW1DYXB0dXJpbmc7XG4gICAgRGV0ZWN0UlRDLmlzVmlkZW9TdXBwb3J0c1N0cmVhbUNhcHR1cmluZyA9IGlzVmlkZW9TdXBwb3J0c1N0cmVhbUNhcHR1cmluZztcblxuICAgIGlmIChEZXRlY3RSVEMuYnJvd3Nlci5uYW1lID09ICdDaHJvbWUnICYmIERldGVjdFJUQy5icm93c2VyLnZlcnNpb24gPj0gNTMpIHtcbiAgICAgICAgaWYgKCFEZXRlY3RSVEMuaXNDYW52YXNTdXBwb3J0c1N0cmVhbUNhcHR1cmluZykge1xuICAgICAgICAgICAgRGV0ZWN0UlRDLmlzQ2FudmFzU3VwcG9ydHNTdHJlYW1DYXB0dXJpbmcgPSAnUmVxdWlyZXMgY2hyb21lIGZsYWc6IGVuYWJsZS1leHBlcmltZW50YWwtd2ViLXBsYXRmb3JtLWZlYXR1cmVzJztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghRGV0ZWN0UlRDLmlzVmlkZW9TdXBwb3J0c1N0cmVhbUNhcHR1cmluZykge1xuICAgICAgICAgICAgRGV0ZWN0UlRDLmlzVmlkZW9TdXBwb3J0c1N0cmVhbUNhcHR1cmluZyA9ICdSZXF1aXJlcyBjaHJvbWUgZmxhZzogZW5hYmxlLWV4cGVyaW1lbnRhbC13ZWItcGxhdGZvcm0tZmVhdHVyZXMnO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gLS0tLS0tXG4gICAgRGV0ZWN0UlRDLkRldGVjdExvY2FsSVBBZGRyZXNzID0gRGV0ZWN0TG9jYWxJUEFkZHJlc3M7XG5cbiAgICBEZXRlY3RSVEMuaXNXZWJTb2NrZXRzU3VwcG9ydGVkID0gJ1dlYlNvY2tldCcgaW4gd2luZG93ICYmIDIgPT09IHdpbmRvdy5XZWJTb2NrZXQuQ0xPU0lORztcbiAgICBEZXRlY3RSVEMuaXNXZWJTb2NrZXRzQmxvY2tlZCA9ICFEZXRlY3RSVEMuaXNXZWJTb2NrZXRzU3VwcG9ydGVkO1xuXG4gICAgaWYgKERldGVjdFJUQy5vc05hbWUgPT09ICdOb2RlanMnKSB7XG4gICAgICAgIERldGVjdFJUQy5pc1dlYlNvY2tldHNTdXBwb3J0ZWQgPSB0cnVlO1xuICAgICAgICBEZXRlY3RSVEMuaXNXZWJTb2NrZXRzQmxvY2tlZCA9IGZhbHNlO1xuICAgIH1cblxuICAgIERldGVjdFJUQy5jaGVja1dlYlNvY2tldHNTdXBwb3J0ID0gZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICAgICAgY2FsbGJhY2sgPSBjYWxsYmFjayB8fCBmdW5jdGlvbigpIHt9O1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgdmFyIHN0YXJ0dGltZTtcbiAgICAgICAgICAgIHZhciB3ZWJzb2NrZXQgPSBuZXcgV2ViU29ja2V0KCd3c3M6Ly9lY2hvLndlYnNvY2tldC5vcmc6NDQzLycpO1xuICAgICAgICAgICAgd2Vic29ja2V0Lm9ub3BlbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIERldGVjdFJUQy5pc1dlYlNvY2tldHNCbG9ja2VkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgc3RhcnR0aW1lID0gKG5ldyBEYXRlKS5nZXRUaW1lKCk7XG4gICAgICAgICAgICAgICAgd2Vic29ja2V0LnNlbmQoJ3BpbmcnKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB3ZWJzb2NrZXQub25tZXNzYWdlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgRGV0ZWN0UlRDLldlYnNvY2tldExhdGVuY3kgPSAobmV3IERhdGUpLmdldFRpbWUoKSAtIHN0YXJ0dGltZSArICdtcyc7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICB3ZWJzb2NrZXQuY2xvc2UoKTtcbiAgICAgICAgICAgICAgICB3ZWJzb2NrZXQgPSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHdlYnNvY2tldC5vbmVycm9yID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgRGV0ZWN0UlRDLmlzV2ViU29ja2V0c0Jsb2NrZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBEZXRlY3RSVEMuaXNXZWJTb2NrZXRzQmxvY2tlZCA9IHRydWU7XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8vIC0tLS0tLS1cbiAgICBEZXRlY3RSVEMubG9hZCA9IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgfHwgZnVuY3Rpb24oKSB7fTtcbiAgICAgICAgY2hlY2tEZXZpY2VTdXBwb3J0KGNhbGxiYWNrKTtcbiAgICB9O1xuXG4gICAgLy8gY2hlY2sgZm9yIG1pY3JvcGhvbmUvY2FtZXJhIHN1cHBvcnQhXG4gICAgaWYgKHR5cGVvZiBjaGVja0RldmljZVN1cHBvcnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgLy8gY2hlY2tEZXZpY2VTdXBwb3J0KCk7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBNZWRpYURldmljZXMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIERldGVjdFJUQy5NZWRpYURldmljZXMgPSBNZWRpYURldmljZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgRGV0ZWN0UlRDLk1lZGlhRGV2aWNlcyA9IFtdO1xuICAgIH1cblxuICAgIERldGVjdFJUQy5oYXNNaWNyb3Bob25lID0gaGFzTWljcm9waG9uZTtcbiAgICBEZXRlY3RSVEMuaGFzU3BlYWtlcnMgPSBoYXNTcGVha2VycztcbiAgICBEZXRlY3RSVEMuaGFzV2ViY2FtID0gaGFzV2ViY2FtO1xuXG4gICAgRGV0ZWN0UlRDLmlzV2Vic2l0ZUhhc1dlYmNhbVBlcm1pc3Npb25zID0gaXNXZWJzaXRlSGFzV2ViY2FtUGVybWlzc2lvbnM7XG4gICAgRGV0ZWN0UlRDLmlzV2Vic2l0ZUhhc01pY3JvcGhvbmVQZXJtaXNzaW9ucyA9IGlzV2Vic2l0ZUhhc01pY3JvcGhvbmVQZXJtaXNzaW9ucztcblxuICAgIERldGVjdFJUQy5hdWRpb0lucHV0RGV2aWNlcyA9IGF1ZGlvSW5wdXREZXZpY2VzO1xuICAgIERldGVjdFJUQy5hdWRpb091dHB1dERldmljZXMgPSBhdWRpb091dHB1dERldmljZXM7XG4gICAgRGV0ZWN0UlRDLnZpZGVvSW5wdXREZXZpY2VzID0gdmlkZW9JbnB1dERldmljZXM7XG5cbiAgICAvLyAtLS0tLS1cbiAgICB2YXIgaXNTZXRTaW5rSWRTdXBwb3J0ZWQgPSBmYWxzZTtcbiAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgZG9jdW1lbnQuY3JlYXRlRWxlbWVudCA9PT0gJ2Z1bmN0aW9uJyAmJiAnc2V0U2lua0lkJyBpbiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpKSB7XG4gICAgICAgIGlzU2V0U2lua0lkU3VwcG9ydGVkID0gdHJ1ZTtcbiAgICB9XG4gICAgRGV0ZWN0UlRDLmlzU2V0U2lua0lkU3VwcG9ydGVkID0gaXNTZXRTaW5rSWRTdXBwb3J0ZWQ7XG5cbiAgICAvLyAtLS0tLVxuICAgIHZhciBpc1JUUFNlbmRlclJlcGxhY2VUcmFja3NTdXBwb3J0ZWQgPSBmYWxzZTtcbiAgICBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIuaXNGaXJlZm94ICYmIHR5cGVvZiBtb3pSVENQZWVyQ29ubmVjdGlvbiAhPT0gJ3VuZGVmaW5lZCcgLyomJiBEZXRlY3RSVEMuYnJvd3Nlci52ZXJzaW9uID4gMzkqLyApIHtcbiAgICAgICAgLypnbG9iYWwgbW96UlRDUGVlckNvbm5lY3Rpb246dHJ1ZSAqL1xuICAgICAgICBpZiAoJ2dldFNlbmRlcnMnIGluIG1velJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSkge1xuICAgICAgICAgICAgaXNSVFBTZW5kZXJSZXBsYWNlVHJhY2tzU3VwcG9ydGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIuaXNDaHJvbWUgJiYgdHlwZW9mIHdlYmtpdFJUQ1BlZXJDb25uZWN0aW9uICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAvKmdsb2JhbCB3ZWJraXRSVENQZWVyQ29ubmVjdGlvbjp0cnVlICovXG4gICAgICAgIGlmICgnZ2V0U2VuZGVycycgaW4gd2Via2l0UlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlKSB7XG4gICAgICAgICAgICBpc1JUUFNlbmRlclJlcGxhY2VUcmFja3NTdXBwb3J0ZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIERldGVjdFJUQy5pc1JUUFNlbmRlclJlcGxhY2VUcmFja3NTdXBwb3J0ZWQgPSBpc1JUUFNlbmRlclJlcGxhY2VUcmFja3NTdXBwb3J0ZWQ7XG5cbiAgICAvLy0tLS0tLVxuICAgIHZhciBpc1JlbW90ZVN0cmVhbVByb2Nlc3NpbmdTdXBwb3J0ZWQgPSBmYWxzZTtcbiAgICBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIuaXNGaXJlZm94ICYmIERldGVjdFJUQy5icm93c2VyLnZlcnNpb24gPiAzOCkge1xuICAgICAgICBpc1JlbW90ZVN0cmVhbVByb2Nlc3NpbmdTdXBwb3J0ZWQgPSB0cnVlO1xuICAgIH1cbiAgICBEZXRlY3RSVEMuaXNSZW1vdGVTdHJlYW1Qcm9jZXNzaW5nU3VwcG9ydGVkID0gaXNSZW1vdGVTdHJlYW1Qcm9jZXNzaW5nU3VwcG9ydGVkO1xuXG4gICAgLy8tLS0tLS0tXG4gICAgdmFyIGlzQXBwbHlDb25zdHJhaW50c1N1cHBvcnRlZCA9IGZhbHNlO1xuXG4gICAgLypnbG9iYWwgTWVkaWFTdHJlYW1UcmFjazp0cnVlICovXG4gICAgaWYgKHR5cGVvZiBNZWRpYVN0cmVhbVRyYWNrICE9PSAndW5kZWZpbmVkJyAmJiAnYXBwbHlDb25zdHJhaW50cycgaW4gTWVkaWFTdHJlYW1UcmFjay5wcm90b3R5cGUpIHtcbiAgICAgICAgaXNBcHBseUNvbnN0cmFpbnRzU3VwcG9ydGVkID0gdHJ1ZTtcbiAgICB9XG4gICAgRGV0ZWN0UlRDLmlzQXBwbHlDb25zdHJhaW50c1N1cHBvcnRlZCA9IGlzQXBwbHlDb25zdHJhaW50c1N1cHBvcnRlZDtcblxuICAgIC8vLS0tLS0tLVxuICAgIHZhciBpc011bHRpTW9uaXRvclNjcmVlbkNhcHR1cmluZ1N1cHBvcnRlZCA9IGZhbHNlO1xuICAgIGlmIChEZXRlY3RSVEMuYnJvd3Nlci5pc0ZpcmVmb3ggJiYgRGV0ZWN0UlRDLmJyb3dzZXIudmVyc2lvbiA+PSA0Mykge1xuICAgICAgICAvLyB2ZXJzaW9uIDQzIG1lcmVseSBzdXBwb3J0cyBwbGF0Zm9ybXMgZm9yIG11bHRpLW1vbml0b3JzXG4gICAgICAgIC8vIHZlcnNpb24gNDQgd2lsbCBzdXBwb3J0IGV4YWN0IG11bHRpLW1vbml0b3Igc2VsZWN0aW9uIGkuZS4geW91IGNhbiBzZWxlY3QgYW55IG1vbml0b3IgZm9yIHNjcmVlbiBjYXB0dXJpbmcuXG4gICAgICAgIGlzTXVsdGlNb25pdG9yU2NyZWVuQ2FwdHVyaW5nU3VwcG9ydGVkID0gdHJ1ZTtcbiAgICB9XG4gICAgRGV0ZWN0UlRDLmlzTXVsdGlNb25pdG9yU2NyZWVuQ2FwdHVyaW5nU3VwcG9ydGVkID0gaXNNdWx0aU1vbml0b3JTY3JlZW5DYXB0dXJpbmdTdXBwb3J0ZWQ7XG5cbiAgICBEZXRlY3RSVEMuaXNQcm9taXNlc1N1cHBvcnRlZCA9ICEhKCdQcm9taXNlJyBpbiB3aW5kb3cpO1xuXG4gICAgaWYgKHR5cGVvZiBEZXRlY3RSVEMgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHdpbmRvdy5EZXRlY3RSVEMgPSB7fTtcbiAgICB9XG5cbiAgICB2YXIgTWVkaWFTdHJlYW0gPSB3aW5kb3cuTWVkaWFTdHJlYW07XG5cbiAgICBpZiAodHlwZW9mIE1lZGlhU3RyZWFtID09PSAndW5kZWZpbmVkJyAmJiB0eXBlb2Ygd2Via2l0TWVkaWFTdHJlYW0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIE1lZGlhU3RyZWFtID0gd2Via2l0TWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBNZWRpYVN0cmVhbSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgRGV0ZWN0UlRDLk1lZGlhU3RyZWFtID0gT2JqZWN0LmtleXMoTWVkaWFTdHJlYW0ucHJvdG90eXBlKTtcbiAgICB9IGVsc2UgRGV0ZWN0UlRDLk1lZGlhU3RyZWFtID0gZmFsc2U7XG5cbiAgICBpZiAodHlwZW9mIE1lZGlhU3RyZWFtVHJhY2sgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIERldGVjdFJUQy5NZWRpYVN0cmVhbVRyYWNrID0gT2JqZWN0LmtleXMoTWVkaWFTdHJlYW1UcmFjay5wcm90b3R5cGUpO1xuICAgIH0gZWxzZSBEZXRlY3RSVEMuTWVkaWFTdHJlYW1UcmFjayA9IGZhbHNlO1xuXG4gICAgdmFyIFJUQ1BlZXJDb25uZWN0aW9uID0gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uIHx8IHdpbmRvdy5tb3pSVENQZWVyQ29ubmVjdGlvbiB8fCB3aW5kb3cud2Via2l0UlRDUGVlckNvbm5lY3Rpb247XG5cbiAgICBpZiAodHlwZW9mIFJUQ1BlZXJDb25uZWN0aW9uICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBEZXRlY3RSVEMuUlRDUGVlckNvbm5lY3Rpb24gPSBPYmplY3Qua2V5cyhSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUpO1xuICAgIH0gZWxzZSBEZXRlY3RSVEMuUlRDUGVlckNvbm5lY3Rpb24gPSBmYWxzZTtcblxuICAgIHdpbmRvdy5EZXRlY3RSVEMgPSBEZXRlY3RSVEM7XG5cbiAgICBpZiAodHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgLyogJiYgISFtb2R1bGUuZXhwb3J0cyovICkge1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IERldGVjdFJUQztcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZSgnRGV0ZWN0UlRDJywgW10sIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIERldGVjdFJUQztcbiAgICAgICAgfSk7XG4gICAgfVxufSkoKTsiLCJmdW5jdGlvbiBNYXBwZXIoKVxue1xuICB2YXIgc291cmNlcyA9IHt9O1xuXG5cbiAgdGhpcy5mb3JFYWNoID0gZnVuY3Rpb24oY2FsbGJhY2spXG4gIHtcbiAgICBmb3IodmFyIGtleSBpbiBzb3VyY2VzKVxuICAgIHtcbiAgICAgIHZhciBzb3VyY2UgPSBzb3VyY2VzW2tleV07XG5cbiAgICAgIGZvcih2YXIga2V5MiBpbiBzb3VyY2UpXG4gICAgICAgIGNhbGxiYWNrKHNvdXJjZVtrZXkyXSk7XG4gICAgfTtcbiAgfTtcblxuICB0aGlzLmdldCA9IGZ1bmN0aW9uKGlkLCBzb3VyY2UpXG4gIHtcbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuXG4gICAgcmV0dXJuIGlkc1tpZF07XG4gIH07XG5cbiAgdGhpcy5yZW1vdmUgPSBmdW5jdGlvbihpZCwgc291cmNlKVxuICB7XG4gICAgdmFyIGlkcyA9IHNvdXJjZXNbc291cmNlXTtcbiAgICBpZihpZHMgPT0gdW5kZWZpbmVkKVxuICAgICAgcmV0dXJuO1xuXG4gICAgZGVsZXRlIGlkc1tpZF07XG5cbiAgICAvLyBDaGVjayBpdCdzIGVtcHR5XG4gICAgZm9yKHZhciBpIGluIGlkcyl7cmV0dXJuIGZhbHNlfVxuXG4gICAgZGVsZXRlIHNvdXJjZXNbc291cmNlXTtcbiAgfTtcblxuICB0aGlzLnNldCA9IGZ1bmN0aW9uKHZhbHVlLCBpZCwgc291cmNlKVxuICB7XG4gICAgaWYodmFsdWUgPT0gdW5kZWZpbmVkKVxuICAgICAgcmV0dXJuIHRoaXMucmVtb3ZlKGlkLCBzb3VyY2UpO1xuXG4gICAgdmFyIGlkcyA9IHNvdXJjZXNbc291cmNlXTtcbiAgICBpZihpZHMgPT0gdW5kZWZpbmVkKVxuICAgICAgc291cmNlc1tzb3VyY2VdID0gaWRzID0ge307XG5cbiAgICBpZHNbaWRdID0gdmFsdWU7XG4gIH07XG59O1xuXG5cbk1hcHBlci5wcm90b3R5cGUucG9wID0gZnVuY3Rpb24oaWQsIHNvdXJjZSlcbntcbiAgdmFyIHZhbHVlID0gdGhpcy5nZXQoaWQsIHNvdXJjZSk7XG4gIGlmKHZhbHVlID09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuXG4gIHRoaXMucmVtb3ZlKGlkLCBzb3VyY2UpO1xuXG4gIHJldHVybiB2YWx1ZTtcbn07XG5cblxubW9kdWxlLmV4cG9ydHMgPSBNYXBwZXI7XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIEpzb25ScGNDbGllbnQgID0gcmVxdWlyZSgnLi9qc29ucnBjY2xpZW50Jyk7XG5cblxuZXhwb3J0cy5Kc29uUnBjQ2xpZW50ICA9IEpzb25ScGNDbGllbnQ7IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBScGNCdWlsZGVyID0gcmVxdWlyZSgnLi4vJyk7XG52YXIgV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbiA9IHJlcXVpcmUoJy4vdHJhbnNwb3J0cy93ZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uJyk7XG5cbkRhdGUubm93ID0gRGF0ZS5ub3cgfHwgZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuICtuZXcgRGF0ZTtcbn07XG5cbnZhciBQSU5HX0lOVEVSVkFMID0gNTAwMDtcblxudmFyIFJFQ09OTkVDVElORyA9ICdSRUNPTk5FQ1RJTkcnO1xudmFyIENPTk5FQ1RFRCA9ICdDT05ORUNURUQnO1xudmFyIERJU0NPTk5FQ1RFRCA9ICdESVNDT05ORUNURUQnO1xuXG52YXIgTG9nZ2VyID0gY29uc29sZTtcblxuLyoqXG4gKlxuICogaGVhcnRiZWF0OiBpbnRlcnZhbCBpbiBtcyBmb3IgZWFjaCBoZWFydGJlYXQgbWVzc2FnZSxcbiAqIHNlbmRDbG9zZU1lc3NhZ2UgOiB0cnVlIC8gZmFsc2UsIGJlZm9yZSBjbG9zaW5nIHRoZSBjb25uZWN0aW9uLCBpdCBzZW5kcyBhIGNsb3NlU2Vzc2lvbiBtZXNzYWdlXG4gKiA8cHJlPlxuICogd3MgOiB7XG4gKiBcdHVyaSA6IFVSSSB0byBjb25udGVjdCB0byxcbiAqICB1c2VTb2NrSlMgOiB0cnVlICh1c2UgU29ja0pTKSAvIGZhbHNlICh1c2UgV2ViU29ja2V0KSBieSBkZWZhdWx0LFxuICogXHRvbmNvbm5lY3RlZCA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiBjb25uZWN0aW9uIGlzIHN1Y2Nlc3NmdWwsXG4gKiBcdG9uZGlzY29ubmVjdCA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY29ubmVjdGlvbiBpcyBsb3N0LFxuICogXHRvbnJlY29ubmVjdGluZyA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY2xpZW50IGlzIHJlY29ubmVjdGluZyxcbiAqIFx0b25yZWNvbm5lY3RlZCA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY2xpZW50IHN1Y2Nlc2Z1bGx5IHJlY29ubmVjdHMsXG4gKiBcdG9uZXJyb3IgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlcmUgaXMgYW4gZXJyb3JcbiAqIH0sXG4gKiBycGMgOiB7XG4gKiBcdHJlcXVlc3RUaW1lb3V0IDogdGltZW91dCBmb3IgYSByZXF1ZXN0LFxuICogXHRzZXNzaW9uU3RhdHVzQ2hhbmdlZDogY2FsbGJhY2sgbWV0aG9kIGZvciBjaGFuZ2VzIGluIHNlc3Npb24gc3RhdHVzLFxuICogXHRtZWRpYVJlbmVnb3RpYXRpb246IG1lZGlhUmVuZWdvdGlhdGlvblxuICogfVxuICogPC9wcmU+XG4gKi9cbmZ1bmN0aW9uIEpzb25ScGNDbGllbnQoY29uZmlndXJhdGlvbikge1xuXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdmFyIHdzQ29uZmlnID0gY29uZmlndXJhdGlvbi53cztcblxuICAgIHZhciBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gLTE7XG5cbiAgICB2YXIgcGluZ05leHROdW0gPSAwO1xuICAgIHZhciBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgIHZhciBwaW5nUG9uZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICB2YXIgcGluZ0ludGVydmFsO1xuXG4gICAgdmFyIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgIHZhciBvbnJlY29ubmVjdGluZyA9IHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nO1xuICAgIHZhciBvbnJlY29ubmVjdGVkID0gd3NDb25maWcub25yZWNvbm5lY3RlZDtcbiAgICB2YXIgb25jb25uZWN0ZWQgPSB3c0NvbmZpZy5vbmNvbm5lY3RlZDtcbiAgICB2YXIgb25lcnJvciA9IHdzQ29uZmlnLm9uZXJyb3I7XG5cbiAgICBjb25maWd1cmF0aW9uLnJwYy5wdWxsID0gZnVuY3Rpb24ocGFyYW1zLCByZXF1ZXN0KSB7XG4gICAgICAgIHJlcXVlc3QucmVwbHkobnVsbCwgXCJwdXNoXCIpO1xuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTlJFQ09OTkVDVElORyAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gUkVDT05ORUNUSU5HKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBSRUNPTk5FQ1RJTkcgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05SRUNPTk5FQ1RJTkcgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBzdGF0dXMgPSBSRUNPTk5FQ1RJTkc7XG4gICAgICAgIGlmIChvbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgb25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0ZWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OUkVDT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OUkVDT05ORUNURUQgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdHVzID0gQ09OTkVDVEVEO1xuXG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKTtcbiAgICAgICAgdXNlUGluZygpO1xuXG4gICAgICAgIGlmIChvbnJlY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbnJlY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbmNvbm5lY3RlZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05DT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OQ09OTkVDVEVEIG1lc3NhZ2UuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHN0YXR1cyA9IENPTk5FQ1RFRDtcblxuICAgICAgICBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgICAgICB1c2VQaW5nKCk7XG5cbiAgICAgICAgaWYgKG9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbmNvbm5lY3RlZCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25lcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTkVSUk9SIC0tLS0tLS0tLS0tXCIpO1xuXG4gICAgICAgIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgICAgICBpZiAob25lcnJvcikge1xuICAgICAgICAgICAgb25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgd3MgPSBuZXcgV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbih3c0NvbmZpZyk7XG5cbiAgICBMb2dnZXIuZGVidWcoJ0Nvbm5lY3Rpbmcgd2Vic29ja2V0IHRvIFVSSTogJyArIHdzQ29uZmlnLnVyaSk7XG5cbiAgICB2YXIgcnBjQnVpbGRlck9wdGlvbnMgPSB7XG4gICAgICAgIHJlcXVlc3RfdGltZW91dDogY29uZmlndXJhdGlvbi5ycGMucmVxdWVzdFRpbWVvdXQsXG4gICAgICAgIHBpbmdfcmVxdWVzdF90aW1lb3V0OiBjb25maWd1cmF0aW9uLnJwYy5oZWFydGJlYXRSZXF1ZXN0VGltZW91dFxuICAgIH07XG5cbiAgICB2YXIgcnBjID0gbmV3IFJwY0J1aWxkZXIoUnBjQnVpbGRlci5wYWNrZXJzLkpzb25SUEMsIHJwY0J1aWxkZXJPcHRpb25zLCB3cyxcbiAgICAgICAgZnVuY3Rpb24ocmVxdWVzdCkge1xuXG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlY2VpdmVkIHJlcXVlc3Q6ICcgKyBKU09OLnN0cmluZ2lmeShyZXF1ZXN0KSk7XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdmFyIGZ1bmMgPSBjb25maWd1cmF0aW9uLnJwY1tyZXF1ZXN0Lm1ldGhvZF07XG5cbiAgICAgICAgICAgICAgICBpZiAoZnVuYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIk1ldGhvZCBcIiArIHJlcXVlc3QubWV0aG9kICsgXCIgbm90IHJlZ2lzdGVyZWQgaW4gY2xpZW50XCIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmMocmVxdWVzdC5wYXJhbXMsIHJlcXVlc3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcignRXhjZXB0aW9uIHByb2Nlc3NpbmcgcmVxdWVzdDogJyArIEpTT04uc3RyaW5naWZ5KHJlcXVlc3QpKTtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZXJyb3IoZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICB0aGlzLnNlbmQgPSBmdW5jdGlvbihtZXRob2QsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKG1ldGhvZCAhPT0gJ3BpbmcnKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlcXVlc3Q6IG1ldGhvZDonICsgbWV0aG9kICsgXCIgcGFyYW1zOlwiICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcmVxdWVzdFRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIHJwYy5lbmNvZGUobWV0aG9kLCBwYXJhbXMsIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SOlwiICsgZXJyb3IubWVzc2FnZSArIFwiIGluIFJlcXVlc3Q6IG1ldGhvZDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgKyBcIiBwYXJhbXM6XCIgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpICsgXCIgcmVxdWVzdDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvci5yZXF1ZXN0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SIERBVEE6XCIgKyBKU09OLnN0cmluZ2lmeShlcnJvci5kYXRhKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICAgICAgICAgIGVycm9yLnJlcXVlc3RUaW1lID0gcmVxdWVzdFRpbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0ICE9IHVuZGVmaW5lZCAmJiByZXN1bHQudmFsdWUgIT09ICdwb25nJykge1xuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1Jlc3BvbnNlOiAnICsgSlNPTi5zdHJpbmdpZnkocmVzdWx0KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gXCIgKyBwaW5nTmV4dE51bSArICcgKG9sZD0nICtcbiAgICAgICAgICAgIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gKyAnKScpO1xuICAgICAgICBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gcGluZ05leHROdW07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2VuZFBpbmcoKSB7XG4gICAgICAgIGlmIChlbmFibGVkUGluZ3MpIHtcbiAgICAgICAgICAgIHZhciBwYXJhbXMgPSBudWxsO1xuICAgICAgICAgICAgaWYgKHBpbmdOZXh0TnVtID09IDAgfHwgcGluZ05leHROdW0gPT0gbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgIHBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJ2YWw6IGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0IHx8IFBJTkdfSU5URVJWQUxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGluZ05leHROdW0rKztcblxuICAgICAgICAgICAgc2VsZi5zZW5kKCdwaW5nJywgcGFyYW1zLCAoZnVuY3Rpb24ocGluZ051bSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiRXJyb3IgaW4gcGluZyByZXF1ZXN0ICNcIiArIHBpbmdOdW0gKyBcIiAoXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yLm1lc3NhZ2UgKyBcIilcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocGluZ051bSA+IG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmFibGVkUGluZ3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU2VydmVyIGRpZCBub3QgcmVzcG9uZCB0byBwaW5nIG1lc3NhZ2UgI1wiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGluZ051bSArIFwiLiBSZWNvbm5lY3RpbmcuLi4gXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdzLnJlY29ubmVjdFdzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KShwaW5nTmV4dE51bSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVHJ5aW5nIHRvIHNlbmQgcGluZywgYnV0IHBpbmcgaXMgbm90IGVuYWJsZWRcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICogSWYgY29uZmlndXJhdGlvbi5oZWFyYmVhdCBoYXMgYW55IHZhbHVlLCB0aGUgcGluZy1wb25nIHdpbGwgd29yayB3aXRoIHRoZSBpbnRlcnZhbFxuICAgICogb2YgY29uZmlndXJhdGlvbi5oZWFyYmVhdFxuICAgICovXG4gICAgZnVuY3Rpb24gdXNlUGluZygpIHtcbiAgICAgICAgaWYgKCFwaW5nUG9uZ1N0YXJ0ZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlN0YXJ0aW5nIHBpbmcgKGlmIGNvbmZpZ3VyZWQpXCIpXG4gICAgICAgICAgICBwaW5nUG9uZ1N0YXJ0ZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBpZiAoY29uZmlndXJhdGlvbi5oZWFydGJlYXQgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcGluZ0ludGVydmFsID0gc2V0SW50ZXJ2YWwoc2VuZFBpbmcsIGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0KTtcbiAgICAgICAgICAgICAgICBzZW5kUGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJDbG9zaW5nIGpzb25ScGNDbGllbnQgZXhwbGljaXRseSBieSBjbGllbnRcIik7XG5cbiAgICAgICAgaWYgKHBpbmdJbnRlcnZhbCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsZWFyaW5nIHBpbmcgaW50ZXJ2YWxcIik7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHBpbmdJbnRlcnZhbCk7XG4gICAgICAgIH1cbiAgICAgICAgcGluZ1BvbmdTdGFydGVkID0gZmFsc2U7XG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuXG4gICAgICAgIGlmIChjb25maWd1cmF0aW9uLnNlbmRDbG9zZU1lc3NhZ2UpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlNlbmRpbmcgY2xvc2UgbWVzc2FnZVwiKVxuICAgICAgICAgICAgdGhpcy5zZW5kKCdjbG9zZVNlc3Npb24nLCBudWxsLCBmdW5jdGlvbihlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVycm9yIHNlbmRpbmcgY2xvc2UgbWVzc2FnZTogXCIgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB3cy5jbG9zZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG5cdFx0XHR3cy5jbG9zZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVGhpcyBtZXRob2QgaXMgb25seSBmb3IgdGVzdGluZ1xuICAgIHRoaXMuZm9yY2VDbG9zZSA9IGZ1bmN0aW9uKG1pbGxpcykge1xuICAgICAgICB3cy5mb3JjZUNsb3NlKG1pbGxpcyk7XG4gICAgfVxuXG4gICAgdGhpcy5yZWNvbm5lY3QgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgd3MucmVjb25uZWN0V3MoKTtcbiAgICB9XG59XG5cblxubW9kdWxlLmV4cG9ydHMgPSBKc29uUnBjQ2xpZW50O1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uICA9IHJlcXVpcmUoJy4vd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xuXG5cbmV4cG9ydHMuV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbiAgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uOyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTMtMjAxNSBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBCcm93c2VyV2ViU29ja2V0ID0gZ2xvYmFsLldlYlNvY2tldCB8fCBnbG9iYWwuTW96V2ViU29ja2V0O1xuXG52YXIgTG9nZ2VyID0gY29uc29sZTtcblxuLyoqXG4gKiBHZXQgZWl0aGVyIHRoZSBgV2ViU29ja2V0YCBvciBgTW96V2ViU29ja2V0YCBnbG9iYWxzXG4gKiBpbiB0aGUgYnJvd3NlciBvciB0cnkgdG8gcmVzb2x2ZSBXZWJTb2NrZXQtY29tcGF0aWJsZVxuICogaW50ZXJmYWNlIGV4cG9zZWQgYnkgYHdzYCBmb3IgTm9kZS1saWtlIGVudmlyb25tZW50LlxuICovXG5cbi8qdmFyIFdlYlNvY2tldCA9IEJyb3dzZXJXZWJTb2NrZXQ7XG5pZiAoIVdlYlNvY2tldCAmJiB0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xuICAgIHRyeSB7XG4gICAgICAgIFdlYlNvY2tldCA9IHJlcXVpcmUoJ3dzJyk7XG4gICAgfSBjYXRjaCAoZSkgeyB9XG59Ki9cblxuLy92YXIgU29ja0pTID0gcmVxdWlyZSgnc29ja2pzLWNsaWVudCcpO1xuXG52YXIgTUFYX1JFVFJJRVMgPSAyMDAwOyAvLyBGb3JldmVyLi4uXG52YXIgUkVUUllfVElNRV9NUyA9IDMwMDA7IC8vIEZJWE1FOiBJbXBsZW1lbnQgZXhwb25lbnRpYWwgd2FpdCB0aW1lcy4uLlxuXG52YXIgQ09OTkVDVElORyA9IDA7XG52YXIgT1BFTiA9IDE7XG52YXIgQ0xPU0lORyA9IDI7XG52YXIgQ0xPU0VEID0gMztcblxuLypcbmNvbmZpZyA9IHtcblx0XHR1cmkgOiB3c1VyaSxcblx0XHR1c2VTb2NrSlMgOiB0cnVlICh1c2UgU29ja0pTKSAvIGZhbHNlICh1c2UgV2ViU29ja2V0KSBieSBkZWZhdWx0LFxuXHRcdG9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcblx0XHRvbmRpc2Nvbm5lY3QgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgbG9zdCxcblx0XHRvbnJlY29ubmVjdGluZyA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY2xpZW50IGlzIHJlY29ubmVjdGluZyxcblx0XHRvbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2VzZnVsbHkgcmVjb25uZWN0cyxcblx0fTtcbiovXG5mdW5jdGlvbiBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uKGNvbmZpZykge1xuXG4gICAgdmFyIGNsb3NpbmcgPSBmYWxzZTtcbiAgICB2YXIgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcjtcbiAgICB2YXIgd3NVcmkgPSBjb25maWcudXJpO1xuICAgIHZhciB1c2VTb2NrSlMgPSBjb25maWcudXNlU29ja0pTO1xuICAgIHZhciByZWNvbm5lY3RpbmcgPSBmYWxzZTtcblxuICAgIHZhciBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IGZhbHNlO1xuXG4gICAgdmFyIHdzO1xuXG4gICAgaWYgKHVzZVNvY2tKUykge1xuICAgICAgICB3cyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHdzID0gbmV3IFdlYlNvY2tldCh3c1VyaSk7XG4gICAgfVxuXG4gICAgd3Mub25vcGVuID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGxvZ0Nvbm5lY3RlZCh3cywgd3NVcmkpO1xuICAgICAgICBpZiAoY29uZmlnLm9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBjb25maWcub25jb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmVycm9yID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmVycm9yKFwiQ291bGQgbm90IGNvbm5lY3QgdG8gXCIgKyB3c1VyaSArIFwiIChpbnZva2luZyBvbmVycm9yIGlmIGRlZmluZWQpXCIsIGVycm9yKTtcbiAgICAgICAgaWYgKGNvbmZpZy5vbmVycm9yKSB7XG4gICAgICAgICAgICBjb25maWcub25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gbG9nQ29ubmVjdGVkKHdzLCB3c1VyaSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiV2ViU29ja2V0IGNvbm5lY3RlZCB0byBcIiArIHdzVXJpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHJlY29ubmVjdGlvbk9uQ2xvc2UgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHdzLnJlYWR5U3RhdGUgPT09IENMT1NFRCkge1xuICAgICAgICAgICAgaWYgKGNsb3NpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCBieSB1c2VyXCIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCB1bmV4cGVjdGVjbHkuIFJlY29ubmVjdGluZy4uLlwiKTtcbiAgICAgICAgICAgICAgICByZWNvbm5lY3RUb1NhbWVVcmkoTUFYX1JFVFJJRVMsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ2xvc2UgY2FsbGJhY2sgZnJvbSBwcmV2aW91cyB3ZWJzb2NrZXQuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHdzLm9uY2xvc2UgPSByZWNvbm5lY3Rpb25PbkNsb3NlO1xuXG4gICAgZnVuY3Rpb24gcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwicmVjb25uZWN0VG9TYW1lVXJpIChhdHRlbXB0ICNcIiArIG51bVJldHJpZXMgKyBcIiwgbWF4PVwiICsgbWF4UmV0cmllcyArIFwiKVwiKTtcblxuICAgICAgICBpZiAobnVtUmV0cmllcyA9PT0gMSkge1xuICAgICAgICAgICAgaWYgKHJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIExvZ2dlci53YXJuKFwiVHJ5aW5nIHRvIHJlY29ubmVjdFRvTmV3VXJpIHdoZW4gcmVjb25uZWN0aW5nLi4uIElnbm9yaW5nIHRoaXMgcmVjb25uZWN0aW9uLlwiKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNvbmZpZy5vbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5vbnJlY29ubmVjdGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZvcmNpbmdEaXNjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCB3c1VyaSk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChjb25maWcubmV3V3NVcmlPblJlY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5uZXdXc1VyaU9uUmVjb25uZWN0aW9uKGZ1bmN0aW9uKGVycm9yLCBuZXdXc1VyaSkge1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIFJFVFJZX1RJTUVfTVMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgbmV3V3NVcmkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgd3NVcmkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVE9ETyBUZXN0IHJldHJpZXMuIEhvdyB0byBmb3JjZSBub3QgY29ubmVjdGlvbj9cbiAgICBmdW5jdGlvbiByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCByZWNvbm5lY3RXc1VyaSkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJSZWNvbm5lY3Rpb24gYXR0ZW1wdCAjXCIgKyBudW1SZXRyaWVzKTtcblxuICAgICAgICB3cy5jbG9zZSgpO1xuXG4gICAgICAgIHdzVXJpID0gcmVjb25uZWN0V3NVcmkgfHwgd3NVcmk7XG5cbiAgICAgICAgdmFyIG5ld1dzO1xuICAgICAgICBpZiAodXNlU29ja0pTKSB7XG4gICAgICAgICAgICBuZXdXcyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3V3MgPSBuZXcgV2ViU29ja2V0KHdzVXJpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5ld1dzLm9ub3BlbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiUmVjb25uZWN0ZWQgYWZ0ZXIgXCIgKyBudW1SZXRyaWVzICsgXCIgYXR0ZW1wdHMuLi5cIik7XG4gICAgICAgICAgICBsb2dDb25uZWN0ZWQobmV3V3MsIHdzVXJpKTtcbiAgICAgICAgICAgIHJlY29ubmVjdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcigpO1xuICAgICAgICAgICAgaWYgKGNvbmZpZy5vbnJlY29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICBjb25maWcub25yZWNvbm5lY3RlZCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBuZXdXcy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgb25FcnJvck9yQ2xvc2UgPSBmdW5jdGlvbihlcnJvcikge1xuICAgICAgICAgICAgTG9nZ2VyLndhcm4oXCJSZWNvbm5lY3Rpb24gZXJyb3I6IFwiLCBlcnJvcik7XG5cbiAgICAgICAgICAgIGlmIChudW1SZXRyaWVzID09PSBtYXhSZXRyaWVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbmZpZy5vbmRpc2Nvbm5lY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uZmlnLm9uZGlzY29ubmVjdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICB9LCBSRVRSWV9USU1FX01TKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBuZXdXcy5vbmVycm9yID0gb25FcnJvck9yQ2xvc2U7XG5cbiAgICAgICAgd3MgPSBuZXdXcztcbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGNsb3NpbmcgPSB0cnVlO1xuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cblxuICAgIC8vIFRoaXMgbWV0aG9kIGlzIG9ubHkgZm9yIHRlc3RpbmdcbiAgICB0aGlzLmZvcmNlQ2xvc2UgPSBmdW5jdGlvbihtaWxsaXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogRm9yY2UgV2ViU29ja2V0IGNsb3NlXCIpO1xuXG4gICAgICAgIGlmIChtaWxsaXMpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IENoYW5nZSB3c1VyaSBmb3IgXCIgKyBtaWxsaXMgKyBcIiBtaWxsaXMgdG8gc2ltdWxhdGUgbmV0IGZhaWx1cmVcIik7XG4gICAgICAgICAgICB2YXIgZ29vZFdzVXJpID0gd3NVcmk7XG4gICAgICAgICAgICB3c1VyaSA9IFwid3NzOi8vMjEuMjM0LjEyLjM0LjQ6NDQzL1wiO1xuXG4gICAgICAgICAgICBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IHRydWU7XG5cbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogUmVjb3ZlciBnb29kIHdzVXJpIFwiICsgZ29vZFdzVXJpKTtcbiAgICAgICAgICAgICAgICB3c1VyaSA9IGdvb2RXc1VyaTtcblxuICAgICAgICAgICAgICAgIGZvcmNpbmdEaXNjb25uZWN0aW9uID0gZmFsc2U7XG5cbiAgICAgICAgICAgIH0sIG1pbGxpcyk7XG4gICAgICAgIH1cblxuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cbiAgICB0aGlzLnJlY29ubmVjdFdzID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcInJlY29ubmVjdFdzXCIpO1xuICAgICAgICByZWNvbm5lY3RUb1NhbWVVcmkoTUFYX1JFVFJJRVMsIDEsIHdzVXJpKTtcbiAgICB9O1xuXG4gICAgdGhpcy5zZW5kID0gZnVuY3Rpb24obWVzc2FnZSkge1xuICAgICAgICB3cy5zZW5kKG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbih0eXBlLCBjYWxsYmFjaykge1xuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB3cy5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKCk7XG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cblxudmFyIGRlZmluZVByb3BlcnR5X0lFOCA9IGZhbHNlXG5pZihPYmplY3QuZGVmaW5lUHJvcGVydHkpXG57XG4gIHRyeVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCBcInhcIiwge30pO1xuICB9XG4gIGNhdGNoKGUpXG4gIHtcbiAgICBkZWZpbmVQcm9wZXJ0eV9JRTggPSB0cnVlXG4gIH1cbn1cblxuLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRnVuY3Rpb24vYmluZFxuaWYgKCFGdW5jdGlvbi5wcm90b3R5cGUuYmluZCkge1xuICBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKG9UaGlzKSB7XG4gICAgaWYgKHR5cGVvZiB0aGlzICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBjbG9zZXN0IHRoaW5nIHBvc3NpYmxlIHRvIHRoZSBFQ01BU2NyaXB0IDVcbiAgICAgIC8vIGludGVybmFsIElzQ2FsbGFibGUgZnVuY3Rpb25cbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Z1bmN0aW9uLnByb3RvdHlwZS5iaW5kIC0gd2hhdCBpcyB0cnlpbmcgdG8gYmUgYm91bmQgaXMgbm90IGNhbGxhYmxlJyk7XG4gICAgfVxuXG4gICAgdmFyIGFBcmdzICAgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxuICAgICAgICBmVG9CaW5kID0gdGhpcyxcbiAgICAgICAgZk5PUCAgICA9IGZ1bmN0aW9uKCkge30sXG4gICAgICAgIGZCb3VuZCAgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gZlRvQmluZC5hcHBseSh0aGlzIGluc3RhbmNlb2YgZk5PUCAmJiBvVGhpc1xuICAgICAgICAgICAgICAgICA/IHRoaXNcbiAgICAgICAgICAgICAgICAgOiBvVGhpcyxcbiAgICAgICAgICAgICAgICAgYUFyZ3MuY29uY2F0KEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKTtcbiAgICAgICAgfTtcblxuICAgIGZOT1AucHJvdG90eXBlID0gdGhpcy5wcm90b3R5cGU7XG4gICAgZkJvdW5kLnByb3RvdHlwZSA9IG5ldyBmTk9QKCk7XG5cbiAgICByZXR1cm4gZkJvdW5kO1xuICB9O1xufVxuXG5cbnZhciBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXI7XG5cbnZhciBpbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJyk7XG5cbnZhciBwYWNrZXJzID0gcmVxdWlyZSgnLi9wYWNrZXJzJyk7XG52YXIgTWFwcGVyID0gcmVxdWlyZSgnLi9NYXBwZXInKTtcblxuXG52YXIgQkFTRV9USU1FT1VUID0gNTAwMDtcblxuXG5mdW5jdGlvbiB1bmlmeVJlc3BvbnNlTWV0aG9kcyhyZXNwb25zZU1ldGhvZHMpXG57XG4gIGlmKCFyZXNwb25zZU1ldGhvZHMpIHJldHVybiB7fTtcblxuICBmb3IodmFyIGtleSBpbiByZXNwb25zZU1ldGhvZHMpXG4gIHtcbiAgICB2YXIgdmFsdWUgPSByZXNwb25zZU1ldGhvZHNba2V5XTtcblxuICAgIGlmKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJylcbiAgICAgIHJlc3BvbnNlTWV0aG9kc1trZXldID1cbiAgICAgIHtcbiAgICAgICAgcmVzcG9uc2U6IHZhbHVlXG4gICAgICB9XG4gIH07XG5cbiAgcmV0dXJuIHJlc3BvbnNlTWV0aG9kcztcbn07XG5cbmZ1bmN0aW9uIHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydClcbntcbiAgaWYoIXRyYW5zcG9ydCkgcmV0dXJuO1xuXG4gIC8vIFRyYW5zcG9ydCBhcyBhIGZ1bmN0aW9uXG4gIGlmKHRyYW5zcG9ydCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB7c2VuZDogdHJhbnNwb3J0fTtcblxuICAvLyBXZWJTb2NrZXQgJiBEYXRhQ2hhbm5lbFxuICBpZih0cmFuc3BvcnQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB0cmFuc3BvcnQ7XG5cbiAgLy8gTWVzc2FnZSBBUEkgKEludGVyLXdpbmRvdyAmIFdlYldvcmtlcilcbiAgaWYodHJhbnNwb3J0LnBvc3RNZXNzYWdlIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICB0cmFuc3BvcnQuc2VuZCA9IHRyYW5zcG9ydC5wb3N0TWVzc2FnZTtcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuICB9XG5cbiAgLy8gU3RyZWFtIEFQSVxuICBpZih0cmFuc3BvcnQud3JpdGUgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIHRyYW5zcG9ydC5zZW5kID0gdHJhbnNwb3J0LndyaXRlO1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cblxuICAvLyBUcmFuc3BvcnRzIHRoYXQgb25seSBjYW4gcmVjZWl2ZSBtZXNzYWdlcywgYnV0IG5vdCBzZW5kXG4gIGlmKHRyYW5zcG9ydC5vbm1lc3NhZ2UgIT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICBpZih0cmFuc3BvcnQucGF1c2UgaW5zdGFuY2VvZiBGdW5jdGlvbikgcmV0dXJuO1xuXG4gIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRyYW5zcG9ydCBpcyBub3QgYSBmdW5jdGlvbiBub3IgYSB2YWxpZCBvYmplY3RcIik7XG59O1xuXG5cbi8qKlxuICogUmVwcmVzZW50YXRpb24gb2YgYSBSUEMgbm90aWZpY2F0aW9uXG4gKlxuICogQGNsYXNzXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZCAtbWV0aG9kIG9mIHRoZSBub3RpZmljYXRpb25cbiAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAqL1xuZnVuY3Rpb24gUnBjTm90aWZpY2F0aW9uKG1ldGhvZCwgcGFyYW1zKVxue1xuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gIHtcbiAgICB0aGlzLm1ldGhvZCA9IG1ldGhvZFxuICAgIHRoaXMucGFyYW1zID0gcGFyYW1zXG4gIH1cbiAgZWxzZVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdtZXRob2QnLCB7dmFsdWU6IG1ldGhvZCwgZW51bWVyYWJsZTogdHJ1ZX0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAncGFyYW1zJywge3ZhbHVlOiBwYXJhbXMsIGVudW1lcmFibGU6IHRydWV9KTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEBjbGFzc1xuICpcbiAqIEBjb25zdHJ1Y3RvclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwYWNrZXJcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gW29wdGlvbnNdXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29uUmVxdWVzdF1cbiAqL1xuZnVuY3Rpb24gUnBjQnVpbGRlcihwYWNrZXIsIG9wdGlvbnMsIHRyYW5zcG9ydCwgb25SZXF1ZXN0KVxue1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgaWYoIXBhY2tlcilcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBub3QgZGVmaW5lZCcpO1xuXG4gIGlmKCFwYWNrZXIucGFjayB8fCAhcGFja2VyLnVucGFjaylcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBpbnZhbGlkJyk7XG5cbiAgdmFyIHJlc3BvbnNlTWV0aG9kcyA9IHVuaWZ5UmVzcG9uc2VNZXRob2RzKHBhY2tlci5yZXNwb25zZU1ldGhvZHMpO1xuXG5cbiAgaWYob3B0aW9ucyBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgaWYodHJhbnNwb3J0ICE9IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgb25SZXF1ZXN0XCIpO1xuXG4gICAgb25SZXF1ZXN0ID0gb3B0aW9ucztcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgb3B0aW9ucyAgID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmKG9wdGlvbnMgJiYgb3B0aW9ucy5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICBpZih0cmFuc3BvcnQgJiYgISh0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbikpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJPbmx5IGEgZnVuY3Rpb24gY2FuIGJlIGFmdGVyIHRyYW5zcG9ydFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSBvcHRpb25zO1xuICAgIG9wdGlvbnMgICA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIGlmKG9uUmVxdWVzdCAhPSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIG9uUmVxdWVzdFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gIH07XG5cbiAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgaWYob25SZXF1ZXN0ICYmICEob25SZXF1ZXN0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblxuICBFdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcblxuICBpZihvblJlcXVlc3QpXG4gICAgdGhpcy5vbigncmVxdWVzdCcsIG9uUmVxdWVzdCk7XG5cblxuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgdGhpcy5wZWVySUQgPSBvcHRpb25zLnBlZXJJRFxuICBlbHNlXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdwZWVySUQnLCB7dmFsdWU6IG9wdGlvbnMucGVlcklEfSk7XG5cbiAgdmFyIG1heF9yZXRyaWVzID0gb3B0aW9ucy5tYXhfcmV0cmllcyB8fCAwO1xuXG5cbiAgZnVuY3Rpb24gdHJhbnNwb3J0TWVzc2FnZShldmVudClcbiAge1xuICAgIHNlbGYuZGVjb2RlKGV2ZW50LmRhdGEgfHwgZXZlbnQpO1xuICB9O1xuXG4gIHRoaXMuZ2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24oKVxuICB7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuICB0aGlzLnNldFRyYW5zcG9ydCA9IGZ1bmN0aW9uKHZhbHVlKVxuICB7XG4gICAgLy8gUmVtb3ZlIGxpc3RlbmVyIGZyb20gb2xkIHRyYW5zcG9ydFxuICAgIGlmKHRyYW5zcG9ydClcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodHJhbnNwb3J0LnJlbW92ZUV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgdHJhbnNwb3J0TWVzc2FnZSk7XG5cbiAgICAgIC8vIE5vZGUuanMgU3RyZWFtcyBBUElcbiAgICAgIGVsc2UgaWYodHJhbnNwb3J0LnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICB0cmFuc3BvcnQucmVtb3ZlTGlzdGVuZXIoJ2RhdGEnLCB0cmFuc3BvcnRNZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgLy8gU2V0IGxpc3RlbmVyIG9uIG5ldyB0cmFuc3BvcnRcbiAgICBpZih2YWx1ZSlcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodmFsdWUuYWRkRXZlbnRMaXN0ZW5lcilcbiAgICAgICAgdmFsdWUuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuXG4gICAgICAvLyBOb2RlLmpzIFN0cmVhbXMgQVBJXG4gICAgICBlbHNlIGlmKHZhbHVlLmFkZExpc3RlbmVyKVxuICAgICAgICB2YWx1ZS5hZGRMaXN0ZW5lcignZGF0YScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gIH1cblxuICBpZighZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICB7XG4gICAgICBnZXQ6IHRoaXMuZ2V0VHJhbnNwb3J0LmJpbmQodGhpcyksXG4gICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICB9KVxuXG4gIHRoaXMuc2V0VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cblxuICB2YXIgcmVxdWVzdF90aW1lb3V0ICAgICAgPSBvcHRpb25zLnJlcXVlc3RfdGltZW91dCAgICAgIHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIHBpbmdfcmVxdWVzdF90aW1lb3V0ID0gb3B0aW9ucy5waW5nX3JlcXVlc3RfdGltZW91dCB8fCByZXF1ZXN0X3RpbWVvdXQ7XG4gIHZhciByZXNwb25zZV90aW1lb3V0ICAgICA9IG9wdGlvbnMucmVzcG9uc2VfdGltZW91dCAgICAgfHwgQkFTRV9USU1FT1VUO1xuICB2YXIgZHVwbGljYXRlc190aW1lb3V0ICAgPSBvcHRpb25zLmR1cGxpY2F0ZXNfdGltZW91dCAgIHx8IEJBU0VfVElNRU9VVDtcblxuXG4gIHZhciByZXF1ZXN0SUQgPSAwO1xuXG4gIHZhciByZXF1ZXN0cyAgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciByZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciBwcm9jZXNzZWRSZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG5cbiAgdmFyIG1lc3NhZ2UyS2V5ID0ge307XG5cblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIHByZXZlbnQgdG8gcHJvY2VzcyBkdXBsaWNhdGUgcmVxdWVzdCBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVSZXNwb25zZShtZXNzYWdlLCBpZCwgZGVzdClcbiAge1xuICAgIHZhciByZXNwb25zZSA9XG4gICAge1xuICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgIC8qKiBUaW1lb3V0IHRvIGF1dG8tY2xlYW4gb2xkIHJlc3BvbnNlcyAqL1xuICAgICAgdGltZW91dDogc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAgICB7XG4gICAgICAgIHJlc3BvbnNlcy5yZW1vdmUoaWQsIGRlc3QpO1xuICAgICAgfSxcbiAgICAgIHJlc3BvbnNlX3RpbWVvdXQpXG4gICAgfTtcblxuICAgIHJlc3BvbnNlcy5zZXQocmVzcG9uc2UsIGlkLCBkZXN0KTtcbiAgfTtcblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIGlnbm9yZSBkdXBsaWNhdGVkIG1lc3NhZ2VzIGxhdGVyXG4gICAqL1xuICBmdW5jdGlvbiBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGFjaywgZnJvbSlcbiAge1xuICAgIHZhciB0aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAge1xuICAgICAgcHJvY2Vzc2VkUmVzcG9uc2VzLnJlbW92ZShhY2ssIGZyb20pO1xuICAgIH0sXG4gICAgZHVwbGljYXRlc190aW1lb3V0KTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5zZXQodGltZW91dCwgYWNrLCBmcm9tKTtcbiAgfTtcblxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRhdGlvbiBvZiBhIFJQQyByZXF1ZXN0XG4gICAqXG4gICAqIEBjbGFzc1xuICAgKiBAZXh0ZW5kcyBScGNOb3RpZmljYXRpb25cbiAgICpcbiAgICogQGNvbnN0cnVjdG9yXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBpZCAtIGlkZW50aWZpZXIgb2YgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIFtmcm9tXSAtIHNvdXJjZSBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqL1xuICBmdW5jdGlvbiBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZCwgZnJvbSwgdHJhbnNwb3J0KVxuICB7XG4gICAgUnBjTm90aWZpY2F0aW9uLmNhbGwodGhpcywgbWV0aG9kLCBwYXJhbXMpO1xuXG4gICAgdGhpcy5nZXRUcmFuc3BvcnQgPSBmdW5jdGlvbigpXG4gICAge1xuICAgICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgICB9XG4gICAgdGhpcy5zZXRUcmFuc3BvcnQgPSBmdW5jdGlvbih2YWx1ZSlcbiAgICB7XG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgaWYoIWRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICAgIHtcbiAgICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICAgIH0pXG5cbiAgICB2YXIgcmVzcG9uc2UgPSByZXNwb25zZXMuZ2V0KGlkLCBmcm9tKTtcblxuICAgIC8qKlxuICAgICAqIEBjb25zdGFudCB7Qm9vbGVhbn0gZHVwbGljYXRlZFxuICAgICAqL1xuICAgIGlmKCEodHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCkpKVxuICAgIHtcbiAgICAgIGlmKGRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgICAgdGhpcy5kdXBsaWNhdGVkID0gQm9vbGVhbihyZXNwb25zZSlcbiAgICAgIGVsc2VcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdkdXBsaWNhdGVkJyxcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiBCb29sZWFuKHJlc3BvbnNlKVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgcmVzcG9uc2VNZXRob2QgPSByZXNwb25zZU1ldGhvZHNbbWV0aG9kXTtcblxuICAgIHRoaXMucGFjayA9IHBhY2tlci5wYWNrLmJpbmQocGFja2VyLCB0aGlzLCBpZClcblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgcmVzcG9uc2UgdG8gdGhpcyByZXF1ZXN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Vycm9yfSBbZXJyb3JdXG4gICAgICogQHBhcmFtIHsqfSBbcmVzdWx0XVxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICB0aGlzLnJlcGx5ID0gZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCwgdHJhbnNwb3J0KVxuICAgIHtcbiAgICAgIC8vIEZpeCBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgICBpZihlcnJvciBpbnN0YW5jZW9mIEZ1bmN0aW9uIHx8IGVycm9yICYmIGVycm9yLnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICAgIHtcbiAgICAgICAgaWYocmVzdWx0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IGVycm9yO1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgICBlcnJvciA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgZWxzZSBpZihyZXN1bHQgaW5zdGFuY2VvZiBGdW5jdGlvblxuICAgICAgfHwgcmVzdWx0ICYmIHJlc3VsdC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgICB7XG4gICAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSByZXN1bHQ7XG4gICAgICAgIHJlc3VsdCA9IG51bGw7XG4gICAgICB9O1xuXG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICAvLyBEdXBsaWNhdGVkIHJlcXVlc3QsIHJlbW92ZSBvbGQgcmVzcG9uc2UgdGltZW91dFxuICAgICAgaWYocmVzcG9uc2UpXG4gICAgICAgIGNsZWFyVGltZW91dChyZXNwb25zZS50aW1lb3V0KTtcblxuICAgICAgaWYoZnJvbSAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgIGVycm9yLmRlc3QgPSBmcm9tO1xuXG4gICAgICAgIGlmKHJlc3VsdClcbiAgICAgICAgICByZXN1bHQuZGVzdCA9IGZyb207XG4gICAgICB9O1xuXG4gICAgICB2YXIgbWVzc2FnZTtcblxuICAgICAgLy8gTmV3IHJlcXVlc3Qgb3Igb3ZlcnJpZGVuIG9uZSwgY3JlYXRlIG5ldyByZXNwb25zZSB3aXRoIHByb3ZpZGVkIGRhdGFcbiAgICAgIGlmKGVycm9yIHx8IHJlc3VsdCAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZClcbiAgICAgICAge1xuICAgICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgICAgZXJyb3IuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIHJlc3VsdC5mcm9tID0gc2VsZi5wZWVySUQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcm90b2NvbCBpbmRpY2F0ZXMgdGhhdCByZXNwb25zZXMgaGFzIG93biByZXF1ZXN0IG1ldGhvZHNcbiAgICAgICAgaWYocmVzcG9uc2VNZXRob2QpXG4gICAgICAgIHtcbiAgICAgICAgICBpZihyZXNwb25zZU1ldGhvZC5lcnJvciA9PSB1bmRlZmluZWQgJiYgZXJyb3IpXG4gICAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXJyb3I6IGVycm9yXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHZhciBtZXRob2QgPSBlcnJvclxuICAgICAgICAgICAgICAgICAgICAgICA/IHJlc3BvbnNlTWV0aG9kLmVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgIDogcmVzcG9uc2VNZXRob2QucmVzcG9uc2U7XG5cbiAgICAgICAgICAgIG1lc3NhZ2UgPVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgICAgICAgcGFyYW1zOiBlcnJvciB8fCByZXN1bHRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICB7XG4gICAgICAgICAgICBlcnJvcjogIGVycm9yLFxuICAgICAgICAgICAgcmVzdWx0OiByZXN1bHRcbiAgICAgICAgICB9O1xuXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIER1cGxpY2F0ZSAmIG5vdC1vdmVycmlkZW4gcmVxdWVzdCwgcmUtc2VuZCBvbGQgcmVzcG9uc2VcbiAgICAgIGVsc2UgaWYocmVzcG9uc2UpXG4gICAgICAgIG1lc3NhZ2UgPSByZXNwb25zZS5tZXNzYWdlO1xuXG4gICAgICAvLyBOZXcgZW1wdHkgcmVwbHksIHJlc3BvbnNlIG51bGwgdmFsdWVcbiAgICAgIGVsc2VcbiAgICAgICAgbWVzc2FnZSA9IHBhY2tlci5wYWNrKHtyZXN1bHQ6IG51bGx9LCBpZCk7XG5cbiAgICAgIC8vIFN0b3JlIHRoZSByZXNwb25zZSB0byBwcmV2ZW50IHRvIHByb2Nlc3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QgbGF0ZXJcbiAgICAgIHN0b3JlUmVzcG9uc2UobWVzc2FnZSwgaWQsIGZyb20pO1xuXG4gICAgICAvLyBSZXR1cm4gdGhlIHN0b3JlZCByZXNwb25zZSBzbyBpdCBjYW4gYmUgZGlyZWN0bHkgc2VuZCBiYWNrXG4gICAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKSB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuXG4gICAgICBpZih0cmFuc3BvcnQpXG4gICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChtZXNzYWdlKTtcblxuICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgfVxuICB9O1xuICBpbmhlcml0cyhScGNSZXF1ZXN0LCBScGNOb3RpZmljYXRpb24pO1xuXG5cbiAgZnVuY3Rpb24gY2FuY2VsKG1lc3NhZ2UpXG4gIHtcbiAgICB2YXIga2V5ID0gbWVzc2FnZTJLZXlbbWVzc2FnZV07XG4gICAgaWYoIWtleSkgcmV0dXJuO1xuXG4gICAgZGVsZXRlIG1lc3NhZ2UyS2V5W21lc3NhZ2VdO1xuXG4gICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5wb3Aoa2V5LmlkLCBrZXkuZGVzdCk7XG4gICAgaWYoIXJlcXVlc3QpIHJldHVybjtcblxuICAgIGNsZWFyVGltZW91dChyZXF1ZXN0LnRpbWVvdXQpO1xuXG4gICAgLy8gU3RhcnQgZHVwbGljYXRlZCByZXNwb25zZXMgdGltZW91dFxuICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2Uoa2V5LmlkLCBrZXkuZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEFsbG93IHRvIGNhbmNlbCBhIHJlcXVlc3QgYW5kIGRvbid0IHdhaXQgZm9yIGEgcmVzcG9uc2VcbiAgICpcbiAgICogSWYgYG1lc3NhZ2VgIGlzIG5vdCBnaXZlbiwgY2FuY2VsIGFsbCB0aGUgcmVxdWVzdFxuICAgKi9cbiAgdGhpcy5jYW5jZWwgPSBmdW5jdGlvbihtZXNzYWdlKVxuICB7XG4gICAgaWYobWVzc2FnZSkgcmV0dXJuIGNhbmNlbChtZXNzYWdlKTtcblxuICAgIGZvcih2YXIgbWVzc2FnZSBpbiBtZXNzYWdlMktleSlcbiAgICAgIGNhbmNlbChtZXNzYWdlKTtcbiAgfTtcblxuXG4gIHRoaXMuY2xvc2UgPSBmdW5jdGlvbigpXG4gIHtcbiAgICAvLyBQcmV2ZW50IHRvIHJlY2VpdmUgbmV3IG1lc3NhZ2VzXG4gICAgdmFyIHRyYW5zcG9ydCA9IHRoaXMuZ2V0VHJhbnNwb3J0KCk7XG4gICAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5jbG9zZSlcbiAgICAgICB0cmFuc3BvcnQuY2xvc2UoKTtcblxuICAgIC8vIFJlcXVlc3QgJiBwcm9jZXNzZWQgcmVzcG9uc2VzXG4gICAgdGhpcy5jYW5jZWwoKTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5mb3JFYWNoKGNsZWFyVGltZW91dCk7XG5cbiAgICAvLyBSZXNwb25zZXNcbiAgICByZXNwb25zZXMuZm9yRWFjaChmdW5jdGlvbihyZXNwb25zZSlcbiAgICB7XG4gICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG4gICAgfSk7XG4gIH07XG5cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGFuZCBlbmNvZGUgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIFtkZXN0XSAtIGRlc3RpbmF0aW9uIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdIC0gdHJhbnNwb3J0IHdoZXJlIHRvIHNlbmQgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIFtjYWxsYmFja10gLSBmdW5jdGlvbiBjYWxsZWQgd2hlbiBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdCBpc1xuICAgKiAgIHJlY2VpdmVkLiBJZiBub3QgZGVmaW5lZCwgYSBub3RpZmljYXRpb24gd2lsbCBiZSBzZW5kIGluc3RlYWRcbiAgICpcbiAgICogQHJldHVybnMge3N0cmluZ30gQSByYXcgSnNvblJQQyAyLjAgcmVxdWVzdCBvciBub3RpZmljYXRpb24gc3RyaW5nXG4gICAqL1xuICB0aGlzLmVuY29kZSA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBkZXN0LCB0cmFuc3BvcnQsIGNhbGxiYWNrKVxuICB7XG4gICAgLy8gRml4IG9wdGlvbmFsIHBhcmFtZXRlcnNcbiAgICBpZihwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihkZXN0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgY2FsbGJhY2sgID0gcGFyYW1zO1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCAgICAgID0gdW5kZWZpbmVkO1xuICAgICAgcGFyYW1zICAgID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGVsc2UgaWYoZGVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHtcbiAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IGRlc3Q7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgICBkZXN0ICAgICAgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgZWxzZSBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihjYWxsYmFjayAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IHRyYW5zcG9ydDtcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgaWYoc2VsZi5wZWVySUQgIT0gdW5kZWZpbmVkKVxuICAgIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICB9O1xuXG4gICAgaWYoZGVzdCAhPSB1bmRlZmluZWQpXG4gICAge1xuICAgICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuXG4gICAgICBwYXJhbXMuZGVzdCA9IGRlc3Q7XG4gICAgfTtcblxuICAgIC8vIEVuY29kZSBtZXNzYWdlXG4gICAgdmFyIG1lc3NhZ2UgPVxuICAgIHtcbiAgICAgIG1ldGhvZDogbWV0aG9kLFxuICAgICAgcGFyYW1zOiBwYXJhbXNcbiAgICB9O1xuXG4gICAgaWYoY2FsbGJhY2spXG4gICAge1xuICAgICAgdmFyIGlkID0gcmVxdWVzdElEKys7XG4gICAgICB2YXIgcmV0cmllZCA9IDA7XG5cbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG5cbiAgICAgIGZ1bmN0aW9uIGRpc3BhdGNoQ2FsbGJhY2soZXJyb3IsIHJlc3VsdClcbiAgICAgIHtcbiAgICAgICAgc2VsZi5jYW5jZWwobWVzc2FnZSk7XG5cbiAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgcmVxdWVzdCA9XG4gICAgICB7XG4gICAgICAgIG1lc3NhZ2U6ICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgY2FsbGJhY2s6ICAgICAgICBkaXNwYXRjaENhbGxiYWNrLFxuICAgICAgICByZXNwb25zZU1ldGhvZHM6IHJlc3BvbnNlTWV0aG9kc1ttZXRob2RdIHx8IHt9XG4gICAgICB9O1xuXG4gICAgICB2YXIgZW5jb2RlX3RyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgIGZ1bmN0aW9uIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJ0ID0gKG1ldGhvZCA9PT0gJ3BpbmcnID8gcGluZ19yZXF1ZXN0X3RpbWVvdXQgOiByZXF1ZXN0X3RpbWVvdXQpO1xuICAgICAgICByZXF1ZXN0LnRpbWVvdXQgPSBzZXRUaW1lb3V0KHRpbWVvdXQsIHJ0Kk1hdGgucG93KDIsIHJldHJpZWQrKykpO1xuICAgICAgICBtZXNzYWdlMktleVttZXNzYWdlXSA9IHtpZDogaWQsIGRlc3Q6IGRlc3R9O1xuICAgICAgICByZXF1ZXN0cy5zZXQocmVxdWVzdCwgaWQsIGRlc3QpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IHRyYW5zcG9ydCB8fCBlbmNvZGVfdHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICB9O1xuXG4gICAgICBmdW5jdGlvbiByZXRyeSh0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgY29uc29sZS53YXJuKHJldHJpZWQrJyByZXRyeSBmb3IgcmVxdWVzdCBtZXNzYWdlOicsbWVzc2FnZSk7XG5cbiAgICAgICAgdmFyIHRpbWVvdXQgPSBwcm9jZXNzZWRSZXNwb25zZXMucG9wKGlkLCBkZXN0KTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXG4gICAgICAgIHJldHVybiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gdGltZW91dCgpXG4gICAgICB7XG4gICAgICAgIGlmKHJldHJpZWQgPCBtYXhfcmV0cmllcylcbiAgICAgICAgICByZXR1cm4gcmV0cnkodHJhbnNwb3J0KTtcblxuICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ1JlcXVlc3QgaGFzIHRpbWVkIG91dCcpO1xuICAgICAgICAgICAgZXJyb3IucmVxdWVzdCA9IG1lc3NhZ2U7XG5cbiAgICAgICAgZXJyb3IucmV0cnkgPSByZXRyeTtcblxuICAgICAgICBkaXNwYXRjaENhbGxiYWNrKGVycm9yKVxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydCk7XG4gICAgfTtcblxuICAgIC8vIFJldHVybiB0aGUgcGFja2VkIG1lc3NhZ2VcbiAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSk7XG5cbiAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKTtcbiAgICBpZih0cmFuc3BvcnQpXG4gICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfTtcblxuICAvKipcbiAgICogRGVjb2RlIGFuZCBwcm9jZXNzIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBtZXNzYWdlXG4gICAqXG4gICAqIEByZXR1cm5zIHtScGNOb3RpZmljYXRpb258UnBjUmVxdWVzdHx1bmRlZmluZWR9IC0gdGhlIHJlcHJlc2VudGF0aW9uIG9mIHRoZVxuICAgKiAgIG5vdGlmaWNhdGlvbiBvciB0aGUgcmVxdWVzdC4gSWYgYSByZXNwb25zZSB3YXMgcHJvY2Vzc2VkLCBpdCB3aWxsIHJldHVyblxuICAgKiAgIGB1bmRlZmluZWRgIHRvIG5vdGlmeSB0aGF0IGl0IHdhcyBwcm9jZXNzZWRcbiAgICpcbiAgICogQHRocm93cyB7VHlwZUVycm9yfSAtIE1lc3NhZ2UgaXMgbm90IGRlZmluZWRcbiAgICovXG4gIHRoaXMuZGVjb2RlID0gZnVuY3Rpb24obWVzc2FnZSwgdHJhbnNwb3J0KVxuICB7XG4gICAgaWYoIW1lc3NhZ2UpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWVzc2FnZSBpcyBub3QgZGVmaW5lZFwiKTtcblxuICAgIHRyeVxuICAgIHtcbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIudW5wYWNrKG1lc3NhZ2UpO1xuICAgIH1cbiAgICBjYXRjaChlKVxuICAgIHtcbiAgICAgIC8vIElnbm9yZSBpbnZhbGlkIG1lc3NhZ2VzXG4gICAgICByZXR1cm4gY29uc29sZS5kZWJ1ZyhlLCBtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdmFyIGlkICAgICA9IG1lc3NhZ2UuaWQ7XG4gICAgdmFyIGFjayAgICA9IG1lc3NhZ2UuYWNrO1xuICAgIHZhciBtZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcbiAgICB2YXIgcGFyYW1zID0gbWVzc2FnZS5wYXJhbXMgfHwge307XG5cbiAgICB2YXIgZnJvbSA9IHBhcmFtcy5mcm9tO1xuICAgIHZhciBkZXN0ID0gcGFyYW1zLmRlc3Q7XG5cbiAgICAvLyBJZ25vcmUgbWVzc2FnZXMgc2VuZCBieSB1c1xuICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZCAmJiBmcm9tID09IHNlbGYucGVlcklEKSByZXR1cm47XG5cbiAgICAvLyBOb3RpZmljYXRpb25cbiAgICBpZihpZCA9PSB1bmRlZmluZWQgJiYgYWNrID09IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICB2YXIgbm90aWZpY2F0aW9uID0gbmV3IFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcyk7XG5cbiAgICAgIGlmKHNlbGYuZW1pdCgncmVxdWVzdCcsIG5vdGlmaWNhdGlvbikpIHJldHVybjtcbiAgICAgIHJldHVybiBub3RpZmljYXRpb247XG4gICAgfTtcblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlcXVlc3QoKVxuICAgIHtcbiAgICAgIC8vIElmIHdlIGhhdmUgYSB0cmFuc3BvcnQgYW5kIGl0J3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QsIHJlcGx5IGlubWVkaWF0bHlcbiAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCkgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKTtcbiAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG4gICAgICAgIGlmKHJlc3BvbnNlKVxuICAgICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChyZXNwb25zZS5tZXNzYWdlKTtcbiAgICAgIH07XG5cbiAgICAgIHZhciBpZEFjayA9IChpZCAhPSB1bmRlZmluZWQpID8gaWQgOiBhY2s7XG4gICAgICB2YXIgcmVxdWVzdCA9IG5ldyBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZEFjaywgZnJvbSwgdHJhbnNwb3J0KTtcblxuICAgICAgaWYoc2VsZi5lbWl0KCdyZXF1ZXN0JywgcmVxdWVzdCkpIHJldHVybjtcbiAgICAgIHJldHVybiByZXF1ZXN0O1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdClcbiAgICB7XG4gICAgICByZXF1ZXN0LmNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBkdXBsaWNhdGVkUmVzcG9uc2UodGltZW91dClcbiAgICB7XG4gICAgICBjb25zb2xlLndhcm4oXCJSZXNwb25zZSBhbHJlYWR5IHByb2Nlc3NlZFwiLCBtZXNzYWdlKTtcblxuICAgICAgLy8gVXBkYXRlIGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2UoYWNrLCBmcm9tKTtcbiAgICB9O1xuXG5cbiAgICAvLyBSZXF1ZXN0LCBvciByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICBpZihtZXRob2QpXG4gICAge1xuICAgICAgLy8gQ2hlY2sgaWYgaXQncyBhIHJlc3BvbnNlIHdpdGggb3duIG1ldGhvZFxuICAgICAgaWYoZGVzdCA9PSB1bmRlZmluZWQgfHwgZGVzdCA9PSBzZWxmLnBlZXJJRClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgICAgaWYocmVxdWVzdClcbiAgICAgICAge1xuICAgICAgICAgIHZhciByZXNwb25zZU1ldGhvZHMgPSByZXF1ZXN0LnJlc3BvbnNlTWV0aG9kcztcblxuICAgICAgICAgIGlmKG1ldGhvZCA9PSByZXNwb25zZU1ldGhvZHMuZXJyb3IpXG4gICAgICAgICAgICByZXR1cm4gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIHBhcmFtcyk7XG5cbiAgICAgICAgICBpZihtZXRob2QgPT0gcmVzcG9uc2VNZXRob2RzLnJlc3BvbnNlKVxuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXNwb25zZShyZXF1ZXN0LCBudWxsLCBwYXJhbXMpO1xuXG4gICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXF1ZXN0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkUmVzcG9uc2VzLmdldChhY2ssIGZyb20pO1xuICAgICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgICAgcmV0dXJuIGR1cGxpY2F0ZWRSZXNwb25zZShwcm9jZXNzZWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZXF1ZXN0XG4gICAgICByZXR1cm4gcHJvY2Vzc1JlcXVlc3QoKTtcbiAgICB9O1xuXG4gICAgdmFyIGVycm9yICA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgdmFyIHJlc3VsdCA9IG1lc3NhZ2UucmVzdWx0O1xuXG4gICAgLy8gSWdub3JlIHJlc3BvbnNlcyBub3Qgc2VuZCB0byB1c1xuICAgIGlmKGVycm9yICAmJiBlcnJvci5kZXN0ICAmJiBlcnJvci5kZXN0ICAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuICAgIGlmKHJlc3VsdCAmJiByZXN1bHQuZGVzdCAmJiByZXN1bHQuZGVzdCAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gUmVzcG9uc2VcbiAgICB2YXIgcmVxdWVzdCA9IHJlcXVlc3RzLmdldChhY2ssIGZyb20pO1xuICAgIGlmKCFyZXF1ZXN0KVxuICAgIHtcbiAgICAgIHZhciBwcm9jZXNzZWQgPSBwcm9jZXNzZWRSZXNwb25zZXMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgIHJldHVybiBkdXBsaWNhdGVkUmVzcG9uc2UocHJvY2Vzc2VkKTtcblxuICAgICAgcmV0dXJuIGNvbnNvbGUud2FybihcIk5vIGNhbGxiYWNrIHdhcyBkZWZpbmVkIGZvciB0aGlzIG1lc3NhZ2VcIiwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFByb2Nlc3MgcmVzcG9uc2VcbiAgICBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdCk7XG4gIH07XG59O1xuaW5oZXJpdHMoUnBjQnVpbGRlciwgRXZlbnRFbWl0dGVyKTtcblxuXG5ScGNCdWlsZGVyLlJwY05vdGlmaWNhdGlvbiA9IFJwY05vdGlmaWNhdGlvbjtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFJwY0J1aWxkZXI7XG5cbnZhciBjbGllbnRzID0gcmVxdWlyZSgnLi9jbGllbnRzJyk7XG52YXIgdHJhbnNwb3J0cyA9IHJlcXVpcmUoJy4vY2xpZW50cy90cmFuc3BvcnRzJyk7XG5cblJwY0J1aWxkZXIuY2xpZW50cyA9IGNsaWVudHM7XG5ScGNCdWlsZGVyLmNsaWVudHMudHJhbnNwb3J0cyA9IHRyYW5zcG9ydHM7XG5ScGNCdWlsZGVyLnBhY2tlcnMgPSBwYWNrZXJzO1xuIiwiLyoqXG4gKiBKc29uUlBDIDIuMCBwYWNrZXJcbiAqL1xuXG4vKipcbiAqIFBhY2sgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG1lc3NhZ2UgLSBvYmplY3QgdG8gYmUgcGFja2FnZWQuIEl0IHJlcXVpcmVzIHRvIGhhdmUgYWxsIHRoZVxuICogICBmaWVsZHMgbmVlZGVkIGJ5IHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIHRoYXQgaXQncyBnb2luZyB0byBiZSBnZW5lcmF0ZWRcbiAqXG4gKiBAcmV0dXJuIHtTdHJpbmd9IC0gdGhlIHN0cmluZ2lmaWVkIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqL1xuZnVuY3Rpb24gcGFjayhtZXNzYWdlLCBpZClcbntcbiAgdmFyIHJlc3VsdCA9XG4gIHtcbiAgICBqc29ucnBjOiBcIjIuMFwiXG4gIH07XG5cbiAgLy8gUmVxdWVzdFxuICBpZihtZXNzYWdlLm1ldGhvZClcbiAge1xuICAgIHJlc3VsdC5tZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcblxuICAgIGlmKG1lc3NhZ2UucGFyYW1zKVxuICAgICAgcmVzdWx0LnBhcmFtcyA9IG1lc3NhZ2UucGFyYW1zO1xuXG4gICAgLy8gUmVxdWVzdCBpcyBhIG5vdGlmaWNhdGlvblxuICAgIGlmKGlkICE9IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5pZCA9IGlkO1xuICB9XG5cbiAgLy8gUmVzcG9uc2VcbiAgZWxzZSBpZihpZCAhPSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihtZXNzYWdlLmVycm9yKVxuICAgIHtcbiAgICAgIGlmKG1lc3NhZ2UucmVzdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJCb3RoIHJlc3VsdCBhbmQgZXJyb3IgYXJlIGRlZmluZWRcIik7XG5cbiAgICAgIHJlc3VsdC5lcnJvciA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgfVxuICAgIGVsc2UgaWYobWVzc2FnZS5yZXN1bHQgIT09IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5yZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWRcIik7XG5cbiAgICByZXN1bHQuaWQgPSBpZDtcbiAgfTtcblxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocmVzdWx0KTtcbn07XG5cbi8qKlxuICogVW5wYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIC0gc3RyaW5nIHdpdGggdGhlIGNvbnRlbnQgb2YgdGhlIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAdGhyb3dzIHtUeXBlRXJyb3J9IC0gSW52YWxpZCBKc29uUlBDIHZlcnNpb25cbiAqXG4gKiBAcmV0dXJuIHtPYmplY3R9IC0gb2JqZWN0IGZpbGxlZCB3aXRoIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIGNvbnRlbnRcbiAqL1xuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpXG57XG4gIHZhciByZXN1bHQgPSBtZXNzYWdlO1xuXG4gIGlmKHR5cGVvZiBtZXNzYWdlID09PSAnc3RyaW5nJyB8fCBtZXNzYWdlIGluc3RhbmNlb2YgU3RyaW5nKSB7XG4gICAgcmVzdWx0ID0gSlNPTi5wYXJzZShtZXNzYWdlKTtcbiAgfVxuXG4gIC8vIENoZWNrIGlmIGl0J3MgYSB2YWxpZCBtZXNzYWdlXG5cbiAgdmFyIHZlcnNpb24gPSByZXN1bHQuanNvbnJwYztcbiAgaWYodmVyc2lvbiAhPT0gJzIuMCcpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgSnNvblJQQyB2ZXJzaW9uICdcIiArIHZlcnNpb24gKyBcIic6IFwiICsgbWVzc2FnZSk7XG5cbiAgLy8gUmVzcG9uc2VcbiAgaWYocmVzdWx0Lm1ldGhvZCA9PSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihyZXN1bHQuaWQgPT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgbWVzc2FnZTogXCIrbWVzc2FnZSk7XG5cbiAgICB2YXIgcmVzdWx0X2RlZmluZWQgPSByZXN1bHQucmVzdWx0ICE9PSB1bmRlZmluZWQ7XG4gICAgdmFyIGVycm9yX2RlZmluZWQgID0gcmVzdWx0LmVycm9yICAhPT0gdW5kZWZpbmVkO1xuXG4gICAgLy8gQ2hlY2sgb25seSByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZCwgbm90IGJvdGggb3Igbm9uZVxuICAgIGlmKHJlc3VsdF9kZWZpbmVkICYmIGVycm9yX2RlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQm90aCByZXN1bHQgYW5kIGVycm9yIGFyZSBkZWZpbmVkOiBcIittZXNzYWdlKTtcblxuICAgIGlmKCFyZXN1bHRfZGVmaW5lZCAmJiAhZXJyb3JfZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZDogXCIrbWVzc2FnZSk7XG5cbiAgICByZXN1bHQuYWNrID0gcmVzdWx0LmlkO1xuICAgIGRlbGV0ZSByZXN1bHQuaWQ7XG4gIH1cblxuICAvLyBSZXR1cm4gdW5wYWNrZWQgbWVzc2FnZVxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuXG5leHBvcnRzLnBhY2sgICA9IHBhY2s7XG5leHBvcnRzLnVucGFjayA9IHVucGFjaztcbiIsImZ1bmN0aW9uIHBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5mdW5jdGlvbiB1bnBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5cbmV4cG9ydHMucGFjayAgID0gcGFjaztcbmV4cG9ydHMudW5wYWNrID0gdW5wYWNrO1xuIiwidmFyIEpzb25SUEMgPSByZXF1aXJlKCcuL0pzb25SUEMnKTtcbnZhciBYbWxSUEMgID0gcmVxdWlyZSgnLi9YbWxSUEMnKTtcblxuXG5leHBvcnRzLkpzb25SUEMgPSBKc29uUlBDO1xuZXhwb3J0cy5YbWxSUEMgID0gWG1sUlBDO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNC0yMDE1IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG52YXIgZnJlZWljZSA9IHJlcXVpcmUoJ2ZyZWVpY2UnKVxudmFyIGluaGVyaXRzID0gcmVxdWlyZSgnaW5oZXJpdHMnKVxudmFyIFVBUGFyc2VyID0gcmVxdWlyZSgndWEtcGFyc2VyLWpzJylcbnZhciB1dWlkID0gcmVxdWlyZSgndXVpZCcpXG52YXIgaGFyayA9IHJlcXVpcmUoJ2hhcmsnKVxuXG52YXIgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnZXZlbnRzJykuRXZlbnRFbWl0dGVyXG52YXIgcmVjdXJzaXZlID0gcmVxdWlyZSgnbWVyZ2UnKS5yZWN1cnNpdmUuYmluZCh1bmRlZmluZWQsIHRydWUpXG52YXIgc2RwVHJhbnNsYXRvciA9IHJlcXVpcmUoJ3NkcC10cmFuc2xhdG9yJylcbnZhciBsb2dnZXIgPSB3aW5kb3cuTG9nZ2VyIHx8IGNvbnNvbGVcblxuLy8gdmFyIGdVTSA9IG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhIHx8IGZ1bmN0aW9uIChjb25zdHJhaW50cykge1xuLy8gICByZXR1cm4gbmV3IFByb21pc2UobmF2aWdhdG9yLmdldFVzZXJNZWRpYShjb25zdHJhaW50cywgZnVuY3Rpb24gKHN0cmVhbSkge1xuLy8gICAgIHZpZGVvU3RyZWFtID0gc3RyZWFtXG4vLyAgICAgc3RhcnQoKVxuLy8gICB9KS5lcm9yKGNhbGxiYWNrKSk7XG4vLyB9XG5cbi8qdHJ5IHtcbiAgcmVxdWlyZSgna3VyZW50by1icm93c2VyLWV4dGVuc2lvbnMnKVxufSBjYXRjaCAoZXJyb3IpIHtcbiAgaWYgKHR5cGVvZiBnZXRTY3JlZW5Db25zdHJhaW50cyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBsb2dnZXIud2Fybignc2NyZWVuIHNoYXJpbmcgaXMgbm90IGF2YWlsYWJsZScpXG5cbiAgICBnZXRTY3JlZW5Db25zdHJhaW50cyA9IGZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKHNlbmRTb3VyY2UsIGNhbGxiYWNrKSB7XG4gICAgICBjYWxsYmFjayhuZXcgRXJyb3IoXCJUaGlzIGxpYnJhcnkgaXMgbm90IGVuYWJsZWQgZm9yIHNjcmVlbiBzaGFyaW5nXCIpKVxuICAgIH1cbiAgfVxufSovXG5cbnZhciBNRURJQV9DT05TVFJBSU5UUyA9IHtcbiAgYXVkaW86IHRydWUsXG4gIHZpZGVvOiB7XG4gICAgd2lkdGg6IDY0MCxcbiAgICBmcmFtZXJhdGU6IDE1XG4gIH1cbn1cblxuLy8gU29tZWhvdywgdGhlIFVBUGFyc2VyIGNvbnN0cnVjdG9yIGdldHMgYW4gZW1wdHkgd2luZG93IG9iamVjdC5cbi8vIFdlIG5lZWQgdG8gcGFzcyB0aGUgdXNlciBhZ2VudCBzdHJpbmcgaW4gb3JkZXIgdG8gZ2V0IGluZm9ybWF0aW9uXG52YXIgdWEgPSAod2luZG93ICYmIHdpbmRvdy5uYXZpZ2F0b3IpID8gd2luZG93Lm5hdmlnYXRvci51c2VyQWdlbnQgOiAnJ1xudmFyIHBhcnNlciA9IG5ldyBVQVBhcnNlcih1YSlcbnZhciBicm93c2VyID0gcGFyc2VyLmdldEJyb3dzZXIoKVxuXG52YXIgdXNlUGxhbkIgPSBmYWxzZVxuaWYgKGJyb3dzZXIubmFtZSA9PT0gJ0Nocm9tZScgfHwgYnJvd3Nlci5uYW1lID09PSAnQ2hyb21pdW0nKSB7XG4gIGxvZ2dlci5kZWJ1Zyhicm93c2VyLm5hbWUgKyBcIjogdXNpbmcgU0RQIFBsYW5CXCIpXG4gIHVzZVBsYW5CID0gdHJ1ZVxufVxuXG5mdW5jdGlvbiBub29wKGVycm9yKSB7XG4gIGlmIChlcnJvcikgbG9nZ2VyLmVycm9yKGVycm9yKVxufVxuXG5mdW5jdGlvbiB0cmFja1N0b3AodHJhY2spIHtcbiAgdHJhY2suc3RvcCAmJiB0cmFjay5zdG9wKClcbn1cblxuZnVuY3Rpb24gc3RyZWFtU3RvcChzdHJlYW0pIHtcbiAgc3RyZWFtLmdldFRyYWNrcygpLmZvckVhY2godHJhY2tTdG9wKVxufVxuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBTZXNzaW9uRGVzY3JpcHRpb24gb2JqZWN0LlxuICovXG52YXIgZHVtcFNEUCA9IGZ1bmN0aW9uIChkZXNjcmlwdGlvbikge1xuICBpZiAodHlwZW9mIGRlc2NyaXB0aW9uID09PSAndW5kZWZpbmVkJyB8fCBkZXNjcmlwdGlvbiA9PT0gbnVsbCkge1xuICAgIHJldHVybiAnJ1xuICB9XG5cbiAgcmV0dXJuICd0eXBlOiAnICsgZGVzY3JpcHRpb24udHlwZSArICdcXHJcXG4nICsgZGVzY3JpcHRpb24uc2RwXG59XG5cbmZ1bmN0aW9uIGJ1ZmZlcml6ZUNhbmRpZGF0ZXMocGMsIG9uZXJyb3IpIHtcbiAgdmFyIGNhbmRpZGF0ZXNRdWV1ZSA9IFtdXG5cbiAgcGMuYWRkRXZlbnRMaXN0ZW5lcignc2lnbmFsaW5nc3RhdGVjaGFuZ2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMuc2lnbmFsaW5nU3RhdGUgPT09ICdzdGFibGUnKSB7XG4gICAgICB3aGlsZSAoY2FuZGlkYXRlc1F1ZXVlLmxlbmd0aCkge1xuICAgICAgICB2YXIgZW50cnkgPSBjYW5kaWRhdGVzUXVldWUuc2hpZnQoKVxuXG4gICAgICAgIHRoaXMuYWRkSWNlQ2FuZGlkYXRlKGVudHJ5LmNhbmRpZGF0ZSwgZW50cnkuY2FsbGJhY2ssIGVudHJ5LmNhbGxiYWNrKVxuICAgICAgfVxuICAgIH1cbiAgfSlcblxuICByZXR1cm4gZnVuY3Rpb24gKGNhbmRpZGF0ZSwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IGNhbGxiYWNrIHx8IG9uZXJyb3JcblxuICAgIHN3aXRjaCAocGMuc2lnbmFsaW5nU3RhdGUpIHtcbiAgICBjYXNlICdjbG9zZWQnOlxuICAgICAgY2FsbGJhY2sobmV3IEVycm9yKCdQZWVyQ29ubmVjdGlvbiBvYmplY3QgaXMgY2xvc2VkJykpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnc3RhYmxlJzpcbiAgICAgIGlmIChwYy5yZW1vdGVEZXNjcmlwdGlvbikge1xuICAgICAgICBwYy5hZGRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlLCBjYWxsYmFjaywgY2FsbGJhY2spO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgZGVmYXVsdDpcbiAgICAgIGNhbmRpZGF0ZXNRdWV1ZS5wdXNoKHtcbiAgICAgICAgY2FuZGlkYXRlOiBjYW5kaWRhdGUsXG4gICAgICAgIGNhbGxiYWNrOiBjYWxsYmFja1xuICAgICAgfSlcbiAgICB9XG4gIH1cbn1cblxuLyogU2ltdWxjYXN0IHV0aWxpdGllcyAqL1xuXG5mdW5jdGlvbiByZW1vdmVGSURGcm9tT2ZmZXIoc2RwKSB7XG4gIHZhciBuID0gc2RwLmluZGV4T2YoXCJhPXNzcmMtZ3JvdXA6RklEXCIpO1xuXG4gIGlmIChuID4gMCkge1xuICAgIHJldHVybiBzZHAuc2xpY2UoMCwgbik7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHNkcDtcbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRTaW11bGNhc3RJbmZvKHZpZGVvU3RyZWFtKSB7XG4gIHZhciB2aWRlb1RyYWNrcyA9IHZpZGVvU3RyZWFtLmdldFZpZGVvVHJhY2tzKCk7XG4gIGlmICghdmlkZW9UcmFja3MubGVuZ3RoKSB7XG4gICAgbG9nZ2VyLndhcm4oJ05vIHZpZGVvIHRyYWNrcyBhdmFpbGFibGUgaW4gdGhlIHZpZGVvIHN0cmVhbScpXG4gICAgcmV0dXJuICcnXG4gIH1cbiAgdmFyIGxpbmVzID0gW1xuICAgICdhPXgtZ29vZ2xlLWZsYWc6Y29uZmVyZW5jZScsXG4gICAgJ2E9c3NyYy1ncm91cDpTSU0gMSAyIDMnLFxuICAgICdhPXNzcmM6MSBjbmFtZTpsb2NhbFZpZGVvJyxcbiAgICAnYT1zc3JjOjEgbXNpZDonICsgdmlkZW9TdHJlYW0uaWQgKyAnICcgKyB2aWRlb1RyYWNrc1swXS5pZCxcbiAgICAnYT1zc3JjOjEgbXNsYWJlbDonICsgdmlkZW9TdHJlYW0uaWQsXG4gICAgJ2E9c3NyYzoxIGxhYmVsOicgKyB2aWRlb1RyYWNrc1swXS5pZCxcbiAgICAnYT1zc3JjOjIgY25hbWU6bG9jYWxWaWRlbycsXG4gICAgJ2E9c3NyYzoyIG1zaWQ6JyArIHZpZGVvU3RyZWFtLmlkICsgJyAnICsgdmlkZW9UcmFja3NbMF0uaWQsXG4gICAgJ2E9c3NyYzoyIG1zbGFiZWw6JyArIHZpZGVvU3RyZWFtLmlkLFxuICAgICdhPXNzcmM6MiBsYWJlbDonICsgdmlkZW9UcmFja3NbMF0uaWQsXG4gICAgJ2E9c3NyYzozIGNuYW1lOmxvY2FsVmlkZW8nLFxuICAgICdhPXNzcmM6MyBtc2lkOicgKyB2aWRlb1N0cmVhbS5pZCArICcgJyArIHZpZGVvVHJhY2tzWzBdLmlkLFxuICAgICdhPXNzcmM6MyBtc2xhYmVsOicgKyB2aWRlb1N0cmVhbS5pZCxcbiAgICAnYT1zc3JjOjMgbGFiZWw6JyArIHZpZGVvVHJhY2tzWzBdLmlkXG4gIF07XG5cbiAgbGluZXMucHVzaCgnJyk7XG5cbiAgcmV0dXJuIGxpbmVzLmpvaW4oJ1xcbicpO1xufVxuXG4vKipcbiAqIFdyYXBwZXIgb2JqZWN0IG9mIGFuIFJUQ1BlZXJDb25uZWN0aW9uLiBUaGlzIG9iamVjdCBpcyBhaW1lZCB0byBzaW1wbGlmeSB0aGVcbiAqIGRldmVsb3BtZW50IG9mIFdlYlJUQy1iYXNlZCBhcHBsaWNhdGlvbnMuXG4gKlxuICogQGNvbnN0cnVjdG9yIG1vZHVsZTprdXJlbnRvVXRpbHMuV2ViUnRjUGVlclxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtb2RlIE1vZGUgaW4gd2hpY2ggdGhlIFBlZXJDb25uZWN0aW9uIHdpbGwgYmUgY29uZmlndXJlZC5cbiAqICBWYWxpZCB2YWx1ZXMgYXJlOiAncmVjdicsICdzZW5kJywgYW5kICdzZW5kUmVjdidcbiAqIEBwYXJhbSBsb2NhbFZpZGVvIFZpZGVvIHRhZyBmb3IgdGhlIGxvY2FsIHN0cmVhbVxuICogQHBhcmFtIHJlbW90ZVZpZGVvIFZpZGVvIHRhZyBmb3IgdGhlIHJlbW90ZSBzdHJlYW1cbiAqIEBwYXJhbSB7TWVkaWFTdHJlYW19IHZpZGVvU3RyZWFtIFN0cmVhbSB0byBiZSB1c2VkIGFzIHByaW1hcnkgc291cmNlXG4gKiAgKHR5cGljYWxseSB2aWRlbyBhbmQgYXVkaW8sIG9yIG9ubHkgdmlkZW8gaWYgY29tYmluZWQgd2l0aCBhdWRpb1N0cmVhbSkgZm9yXG4gKiAgbG9jYWxWaWRlbyBhbmQgdG8gYmUgYWRkZWQgYXMgc3RyZWFtIHRvIHRoZSBSVENQZWVyQ29ubmVjdGlvblxuICogQHBhcmFtIHtNZWRpYVN0cmVhbX0gYXVkaW9TdHJlYW0gU3RyZWFtIHRvIGJlIHVzZWQgYXMgc2Vjb25kIHNvdXJjZVxuICogICh0eXBpY2FsbHkgZm9yIGF1ZGlvKSBmb3IgbG9jYWxWaWRlbyBhbmQgdG8gYmUgYWRkZWQgYXMgc3RyZWFtIHRvIHRoZVxuICogIFJUQ1BlZXJDb25uZWN0aW9uXG4gKi9cbmZ1bmN0aW9uIFdlYlJ0Y1BlZXIobW9kZSwgb3B0aW9ucywgY2FsbGJhY2spIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFdlYlJ0Y1BlZXIpKSB7XG4gICAgcmV0dXJuIG5ldyBXZWJSdGNQZWVyKG1vZGUsIG9wdGlvbnMsIGNhbGxiYWNrKVxuICB9XG5cbiAgV2ViUnRjUGVlci5zdXBlcl8uY2FsbCh0aGlzKVxuXG4gIGlmIChvcHRpb25zIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICBjYWxsYmFjayA9IG9wdGlvbnNcbiAgICBvcHRpb25zID0gdW5kZWZpbmVkXG4gIH1cblxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuICBjYWxsYmFjayA9IChjYWxsYmFjayB8fCBub29wKS5iaW5kKHRoaXMpXG5cbiAgdmFyIHNlbGYgPSB0aGlzXG4gIHZhciBsb2NhbFZpZGVvID0gb3B0aW9ucy5sb2NhbFZpZGVvXG4gIHZhciByZW1vdGVWaWRlbyA9IG9wdGlvbnMucmVtb3RlVmlkZW9cbiAgdmFyIHZpZGVvU3RyZWFtID0gb3B0aW9ucy52aWRlb1N0cmVhbVxuICB2YXIgYXVkaW9TdHJlYW0gPSBvcHRpb25zLmF1ZGlvU3RyZWFtXG4gIHZhciBtZWRpYUNvbnN0cmFpbnRzID0gb3B0aW9ucy5tZWRpYUNvbnN0cmFpbnRzXG5cbiAgdmFyIGNvbm5lY3Rpb25Db25zdHJhaW50cyA9IG9wdGlvbnMuY29ubmVjdGlvbkNvbnN0cmFpbnRzXG4gIHZhciBwYyA9IG9wdGlvbnMucGVlckNvbm5lY3Rpb25cbiAgdmFyIHNlbmRTb3VyY2UgPSBvcHRpb25zLnNlbmRTb3VyY2UgfHwgJ3dlYmNhbSdcblxuICB2YXIgZGF0YUNoYW5uZWxDb25maWcgPSBvcHRpb25zLmRhdGFDaGFubmVsQ29uZmlnXG4gIHZhciB1c2VEYXRhQ2hhbm5lbHMgPSBvcHRpb25zLmRhdGFDaGFubmVscyB8fCBmYWxzZVxuICB2YXIgZGF0YUNoYW5uZWxcblxuICB2YXIgZ3VpZCA9IHV1aWQudjQoKVxuICB2YXIgY29uZmlndXJhdGlvbiA9IHJlY3Vyc2l2ZSh7XG4gICAgICBpY2VTZXJ2ZXJzOiBmcmVlaWNlKClcbiAgICB9LFxuICAgIG9wdGlvbnMuY29uZmlndXJhdGlvbilcblxuICB2YXIgb25pY2VjYW5kaWRhdGUgPSBvcHRpb25zLm9uaWNlY2FuZGlkYXRlXG4gIGlmIChvbmljZWNhbmRpZGF0ZSkgdGhpcy5vbignaWNlY2FuZGlkYXRlJywgb25pY2VjYW5kaWRhdGUpXG5cbiAgdmFyIG9uY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IG9wdGlvbnMub25jYW5kaWRhdGVnYXRoZXJpbmdkb25lXG4gIGlmIChvbmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUpIHtcbiAgICB0aGlzLm9uKCdjYW5kaWRhdGVnYXRoZXJpbmdkb25lJywgb25jYW5kaWRhdGVnYXRoZXJpbmdkb25lKVxuICB9XG5cbiAgdmFyIHNpbXVsY2FzdCA9IG9wdGlvbnMuc2ltdWxjYXN0XG4gIHZhciBtdWx0aXN0cmVhbSA9IG9wdGlvbnMubXVsdGlzdHJlYW1cbiAgdmFyIGludGVyb3AgPSBuZXcgc2RwVHJhbnNsYXRvci5JbnRlcm9wKClcbiAgdmFyIGNhbmRpZGF0ZXNRdWV1ZU91dCA9IFtdXG4gIHZhciBjYW5kaWRhdGVnYXRoZXJpbmdkb25lID0gZmFsc2VcblxuICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyh0aGlzLCB7XG4gICAgJ3BlZXJDb25uZWN0aW9uJzoge1xuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBwY1xuICAgICAgfVxuICAgIH0sXG5cbiAgICAnaWQnOiB7XG4gICAgICB2YWx1ZTogb3B0aW9ucy5pZCB8fCBndWlkLFxuICAgICAgd3JpdGFibGU6IGZhbHNlXG4gICAgfSxcblxuICAgICdyZW1vdGVWaWRlbyc6IHtcbiAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gcmVtb3RlVmlkZW9cbiAgICAgIH1cbiAgICB9LFxuXG4gICAgJ2xvY2FsVmlkZW8nOiB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGxvY2FsVmlkZW9cbiAgICAgIH1cbiAgICB9LFxuXG4gICAgJ2RhdGFDaGFubmVsJzoge1xuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBkYXRhQ2hhbm5lbFxuICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBAbWVtYmVyIHsoZXh0ZXJuYWw6SW1hZ2VEYXRhfHVuZGVmaW5lZCl9IGN1cnJlbnRGcmFtZVxuICAgICAqL1xuICAgICdjdXJyZW50RnJhbWUnOiB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gW1RvRG9dIEZpbmQgc29sdXRpb24gd2hlbiB3ZSBoYXZlIGEgcmVtb3RlIHN0cmVhbSBidXQgd2UgZGlkbid0IHNldFxuICAgICAgICAvLyBhIHJlbW90ZVZpZGVvIHRhZ1xuICAgICAgICBpZiAoIXJlbW90ZVZpZGVvKSByZXR1cm47XG5cbiAgICAgICAgaWYgKHJlbW90ZVZpZGVvLnJlYWR5U3RhdGUgPCByZW1vdGVWaWRlby5IQVZFX0NVUlJFTlRfREFUQSlcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIHZpZGVvIHN0cmVhbSBkYXRhIGF2YWlsYWJsZScpXG5cbiAgICAgICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpXG4gICAgICAgIGNhbnZhcy53aWR0aCA9IHJlbW90ZVZpZGVvLnZpZGVvV2lkdGhcbiAgICAgICAgY2FudmFzLmhlaWdodCA9IHJlbW90ZVZpZGVvLnZpZGVvSGVpZ2h0XG5cbiAgICAgICAgY2FudmFzLmdldENvbnRleHQoJzJkJykuZHJhd0ltYWdlKHJlbW90ZVZpZGVvLCAwLCAwKVxuXG4gICAgICAgIHJldHVybiBjYW52YXNcbiAgICAgIH1cbiAgICB9XG4gIH0pXG5cbiAgLy8gSW5pdCBQZWVyQ29ubmVjdGlvblxuICBpZiAoIXBjKSB7XG4gICAgcGMgPSBuZXcgUlRDUGVlckNvbm5lY3Rpb24oY29uZmlndXJhdGlvbik7XG4gICAgaWYgKHVzZURhdGFDaGFubmVscyAmJiAhZGF0YUNoYW5uZWwpIHtcbiAgICAgIHZhciBkY0lkID0gJ1dlYlJ0Y1BlZXItJyArIHNlbGYuaWRcbiAgICAgIHZhciBkY09wdGlvbnMgPSB1bmRlZmluZWRcbiAgICAgIGlmIChkYXRhQ2hhbm5lbENvbmZpZykge1xuICAgICAgICBkY0lkID0gZGF0YUNoYW5uZWxDb25maWcuaWQgfHwgZGNJZFxuICAgICAgICBkY09wdGlvbnMgPSBkYXRhQ2hhbm5lbENvbmZpZy5vcHRpb25zXG4gICAgICB9XG4gICAgICBkYXRhQ2hhbm5lbCA9IHBjLmNyZWF0ZURhdGFDaGFubmVsKGRjSWQsIGRjT3B0aW9ucyk7XG4gICAgICBpZiAoZGF0YUNoYW5uZWxDb25maWcpIHtcbiAgICAgICAgZGF0YUNoYW5uZWwub25vcGVuID0gZGF0YUNoYW5uZWxDb25maWcub25vcGVuO1xuICAgICAgICBkYXRhQ2hhbm5lbC5vbmNsb3NlID0gZGF0YUNoYW5uZWxDb25maWcub25jbG9zZTtcbiAgICAgICAgZGF0YUNoYW5uZWwub25tZXNzYWdlID0gZGF0YUNoYW5uZWxDb25maWcub25tZXNzYWdlO1xuICAgICAgICBkYXRhQ2hhbm5lbC5vbmJ1ZmZlcmVkYW1vdW50bG93ID0gZGF0YUNoYW5uZWxDb25maWcub25idWZmZXJlZGFtb3VudGxvdztcbiAgICAgICAgZGF0YUNoYW5uZWwub25lcnJvciA9IGRhdGFDaGFubmVsQ29uZmlnLm9uZXJyb3IgfHwgbm9vcDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwYy5hZGRFdmVudExpc3RlbmVyKCdpY2VjYW5kaWRhdGUnLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB2YXIgY2FuZGlkYXRlID0gZXZlbnQuY2FuZGlkYXRlXG5cbiAgICBpZiAoRXZlbnRFbWl0dGVyLmxpc3RlbmVyQ291bnQoc2VsZiwgJ2ljZWNhbmRpZGF0ZScpIHx8XG4gICAgICBFdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudChcbiAgICAgICAgc2VsZiwgJ2NhbmRpZGF0ZWdhdGhlcmluZ2RvbmUnKSkge1xuICAgICAgaWYgKGNhbmRpZGF0ZSkge1xuICAgICAgICB2YXIgY2FuZFxuXG4gICAgICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgICAgIGNhbmQgPSBpbnRlcm9wLmNhbmRpZGF0ZVRvVW5pZmllZFBsYW4oY2FuZGlkYXRlKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNhbmQgPSBjYW5kaWRhdGVcbiAgICAgICAgfVxuXG4gICAgICAgIHNlbGYuZW1pdCgnaWNlY2FuZGlkYXRlJywgY2FuZClcbiAgICAgICAgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IGZhbHNlXG4gICAgICB9IGVsc2UgaWYgKCFjYW5kaWRhdGVnYXRoZXJpbmdkb25lKSB7XG4gICAgICAgIHNlbGYuZW1pdCgnY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScpXG4gICAgICAgIGNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSB0cnVlXG4gICAgICB9XG4gICAgfSBlbHNlIGlmICghY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSkge1xuICAgICAgLy8gTm90IGxpc3RlbmluZyB0byAnaWNlY2FuZGlkYXRlJyBvciAnY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScgZXZlbnRzLCBxdWV1ZVxuICAgICAgLy8gdGhlIGNhbmRpZGF0ZSB1bnRpbCBvbmUgb2YgdGhlbSBpcyBsaXN0ZW5lZFxuICAgICAgY2FuZGlkYXRlc1F1ZXVlT3V0LnB1c2goY2FuZGlkYXRlKVxuXG4gICAgICBpZiAoIWNhbmRpZGF0ZSkgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IHRydWVcbiAgICB9XG4gIH0pXG5cbiAgcGMub250cmFjayA9IG9wdGlvbnMub25hZGRzdHJlYW1cbiAgcGMub25uZWdvdGlhdGlvbm5lZWRlZCA9IG9wdGlvbnMub25uZWdvdGlhdGlvbm5lZWRlZFxuICB0aGlzLm9uKCduZXdMaXN0ZW5lcicsIGZ1bmN0aW9uIChldmVudCwgbGlzdGVuZXIpIHtcbiAgICBpZiAoZXZlbnQgPT09ICdpY2VjYW5kaWRhdGUnIHx8IGV2ZW50ID09PSAnY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScpIHtcbiAgICAgIHdoaWxlIChjYW5kaWRhdGVzUXVldWVPdXQubGVuZ3RoKSB7XG4gICAgICAgIHZhciBjYW5kaWRhdGUgPSBjYW5kaWRhdGVzUXVldWVPdXQuc2hpZnQoKVxuXG4gICAgICAgIGlmICghY2FuZGlkYXRlID09PSAoZXZlbnQgPT09ICdjYW5kaWRhdGVnYXRoZXJpbmdkb25lJykpIHtcbiAgICAgICAgICBsaXN0ZW5lcihjYW5kaWRhdGUpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH0pXG5cbiAgdmFyIGFkZEljZUNhbmRpZGF0ZSA9IGJ1ZmZlcml6ZUNhbmRpZGF0ZXMocGMpXG5cbiAgLyoqXG4gICAqIENhbGxiYWNrIGZ1bmN0aW9uIGludm9rZWQgd2hlbiBhbiBJQ0UgY2FuZGlkYXRlIGlzIHJlY2VpdmVkLiBEZXZlbG9wZXJzIGFyZVxuICAgKiBleHBlY3RlZCB0byBpbnZva2UgdGhpcyBmdW5jdGlvbiBpbiBvcmRlciB0byBjb21wbGV0ZSB0aGUgU0RQIG5lZ290aWF0aW9uLlxuICAgKlxuICAgKiBAZnVuY3Rpb24gbW9kdWxlOmt1cmVudG9VdGlscy5XZWJSdGNQZWVyLnByb3RvdHlwZS5hZGRJY2VDYW5kaWRhdGVcbiAgICpcbiAgICogQHBhcmFtIGljZUNhbmRpZGF0ZSAtIExpdGVyYWwgb2JqZWN0IHdpdGggdGhlIElDRSBjYW5kaWRhdGUgZGVzY3JpcHRpb25cbiAgICogQHBhcmFtIGNhbGxiYWNrIC0gQ2FsbGVkIHdoZW4gdGhlIElDRSBjYW5kaWRhdGUgaGFzIGJlZW4gYWRkZWQuXG4gICAqL1xuICB0aGlzLmFkZEljZUNhbmRpZGF0ZSA9IGZ1bmN0aW9uIChpY2VDYW5kaWRhdGUsIGNhbGxiYWNrKSB7XG4gICAgdmFyIGNhbmRpZGF0ZVxuXG4gICAgaWYgKG11bHRpc3RyZWFtICYmIHVzZVBsYW5CKSB7XG4gICAgICBjYW5kaWRhdGUgPSBpbnRlcm9wLmNhbmRpZGF0ZVRvUGxhbkIoaWNlQ2FuZGlkYXRlKVxuICAgIH0gZWxzZSB7XG4gICAgICBjYW5kaWRhdGUgPSBuZXcgUlRDSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZSlcbiAgICB9XG5cbiAgICBsb2dnZXIuZGVidWcoJ1JlbW90ZSBJQ0UgY2FuZGlkYXRlIHJlY2VpdmVkJywgaWNlQ2FuZGlkYXRlKVxuICAgIGNhbGxiYWNrID0gKGNhbGxiYWNrIHx8IG5vb3ApLmJpbmQodGhpcylcbiAgICBhZGRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlLCBjYWxsYmFjaylcbiAgfVxuXG4gIHRoaXMuZ2VuZXJhdGVPZmZlciA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2suYmluZCh0aGlzKVxuXG4gICAgdmFyIG9mZmVyQXVkaW8gPSB0cnVlXG4gICAgdmFyIG9mZmVyVmlkZW8gPSB0cnVlXG4gICAgLy8gQ29uc3RyYWludHMgbXVzdCBoYXZlIGJvdGggYmxvY2tzXG4gICAgaWYgKG1lZGlhQ29uc3RyYWludHMpIHtcbiAgICAgIG9mZmVyQXVkaW8gPSAodHlwZW9mIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPT09ICdib29sZWFuJykgP1xuICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIDogdHJ1ZVxuICAgICAgb2ZmZXJWaWRlbyA9ICh0eXBlb2YgbWVkaWFDb25zdHJhaW50cy52aWRlbyA9PT0gJ2Jvb2xlYW4nKSA/XG4gICAgICAgIG1lZGlhQ29uc3RyYWludHMudmlkZW8gOiB0cnVlXG4gICAgfVxuXG4gICAgdmFyIGJyb3dzZXJEZXBlbmRhbnRDb25zdHJhaW50cyA9IHtcbiAgICAgIG9mZmVyVG9SZWNlaXZlQXVkaW86IChtb2RlICE9PSAnc2VuZG9ubHknICYmIG9mZmVyQXVkaW8pLFxuICAgICAgb2ZmZXJUb1JlY2VpdmVWaWRlbzogKG1vZGUgIT09ICdzZW5kb25seScgJiYgb2ZmZXJWaWRlbylcbiAgICB9XG5cbiAgICAvL0ZJWE1FOiBjbGFyaWZ5IHBvc3NpYmxlIGNvbnN0cmFpbnRzIHBhc3NlZCB0byBjcmVhdGVPZmZlcigpXG4gICAgLyp2YXIgY29uc3RyYWludHMgPSByZWN1cnNpdmUoYnJvd3NlckRlcGVuZGFudENvbnN0cmFpbnRzLFxuICAgICAgY29ubmVjdGlvbkNvbnN0cmFpbnRzKSovXG5cbiAgICB2YXIgY29uc3RyYWludHMgPSBicm93c2VyRGVwZW5kYW50Q29uc3RyYWludHM7XG5cbiAgICBsb2dnZXIuZGVidWcoJ2NvbnN0cmFpbnRzOiAnICsgSlNPTi5zdHJpbmdpZnkoY29uc3RyYWludHMpKVxuXG4gICAgcGMuY3JlYXRlT2ZmZXIoY29uc3RyYWludHMpLnRoZW4oZnVuY3Rpb24gKG9mZmVyKSB7XG4gICAgICBsb2dnZXIuZGVidWcoJ0NyZWF0ZWQgU0RQIG9mZmVyJylcbiAgICAgIG9mZmVyID0gbWFuZ2xlU2RwVG9BZGRTaW11bGNhc3Qob2ZmZXIpXG4gICAgICByZXR1cm4gcGMuc2V0TG9jYWxEZXNjcmlwdGlvbihvZmZlcilcbiAgICB9KS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBsb2NhbERlc2NyaXB0aW9uID0gcGMubG9jYWxEZXNjcmlwdGlvblxuICAgICAgbG9nZ2VyLmRlYnVnKCdMb2NhbCBkZXNjcmlwdGlvbiBzZXQnLCBsb2NhbERlc2NyaXB0aW9uLnNkcClcbiAgICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgICBsb2NhbERlc2NyaXB0aW9uID0gaW50ZXJvcC50b1VuaWZpZWRQbGFuKGxvY2FsRGVzY3JpcHRpb24pXG4gICAgICAgIGxvZ2dlci5kZWJ1Zygnb2ZmZXI6Om9yaWdQbGFuQi0+VW5pZmllZFBsYW4nLCBkdW1wU0RQKFxuICAgICAgICAgIGxvY2FsRGVzY3JpcHRpb24pKVxuICAgICAgfVxuICAgICAgY2FsbGJhY2sobnVsbCwgbG9jYWxEZXNjcmlwdGlvbi5zZHAsIHNlbGYucHJvY2Vzc0Fuc3dlci5iaW5kKFxuICAgICAgICBzZWxmKSlcbiAgICB9KS5jYXRjaChjYWxsYmFjaylcbiAgfVxuXG4gIHRoaXMuZ2V0TG9jYWxTZXNzaW9uRGVzY3JpcHRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gcGMubG9jYWxEZXNjcmlwdGlvblxuICB9XG5cbiAgdGhpcy5nZXRSZW1vdGVTZXNzaW9uRGVzY3JpcHRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gcGMucmVtb3RlRGVzY3JpcHRpb25cbiAgfVxuXG4gIGZ1bmN0aW9uIHNldFJlbW90ZVZpZGVvKCkge1xuICAgIGlmIChyZW1vdGVWaWRlbykge1xuICAgICAgdmFyIHN0cmVhbSA9IHBjLmdldFJlbW90ZVN0cmVhbXMoKVswXVxuICAgICAgdmFyIHVybCA9IHN0cmVhbSA/IFVSTC5jcmVhdGVPYmplY3RVUkwoc3RyZWFtKSA6ICcnXG5cbiAgICAgIHJlbW90ZVZpZGVvLnBhdXNlKClcbiAgICAgIHJlbW90ZVZpZGVvLnNyYyA9IHVybFxuICAgICAgcmVtb3RlVmlkZW8ubG9hZCgpXG5cbiAgICAgIGxvZ2dlci5kZWJ1ZygnUmVtb3RlIFVSTDonLCB1cmwpXG4gICAgfVxuICB9XG5cbiAgdGhpcy5zaG93TG9jYWxWaWRlbyA9IGZ1bmN0aW9uICgpIHtcbiAgICBsb2NhbFZpZGVvLnNyYyA9IFVSTC5jcmVhdGVPYmplY3RVUkwodmlkZW9TdHJlYW0pXG4gICAgbG9jYWxWaWRlby5tdXRlZCA9IHRydWVcbiAgfVxuXG4gIHRoaXMuc2VuZCA9IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgaWYgKGRhdGFDaGFubmVsICYmIGRhdGFDaGFubmVsLnJlYWR5U3RhdGUgPT09ICdvcGVuJykge1xuICAgICAgZGF0YUNoYW5uZWwuc2VuZChkYXRhKVxuICAgIH0gZWxzZSB7XG4gICAgICBsb2dnZXIud2FybihcbiAgICAgICAgJ1RyeWluZyB0byBzZW5kIGRhdGEgb3ZlciBhIG5vbi1leGlzdGluZyBvciBjbG9zZWQgZGF0YSBjaGFubmVsJylcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2FsbGJhY2sgZnVuY3Rpb24gaW52b2tlZCB3aGVuIGEgU0RQIGFuc3dlciBpcyByZWNlaXZlZC4gRGV2ZWxvcGVycyBhcmVcbiAgICogZXhwZWN0ZWQgdG8gaW52b2tlIHRoaXMgZnVuY3Rpb24gaW4gb3JkZXIgdG8gY29tcGxldGUgdGhlIFNEUCBuZWdvdGlhdGlvbi5cbiAgICpcbiAgICogQGZ1bmN0aW9uIG1vZHVsZTprdXJlbnRvVXRpbHMuV2ViUnRjUGVlci5wcm90b3R5cGUucHJvY2Vzc0Fuc3dlclxuICAgKlxuICAgKiBAcGFyYW0gc2RwQW5zd2VyIC0gRGVzY3JpcHRpb24gb2Ygc2RwQW5zd2VyXG4gICAqIEBwYXJhbSBjYWxsYmFjayAtXG4gICAqICAgICAgICAgICAgSW52b2tlZCBhZnRlciB0aGUgU0RQIGFuc3dlciBpcyBwcm9jZXNzZWQsIG9yIHRoZXJlIGlzIGFuIGVycm9yLlxuICAgKi9cbiAgdGhpcy5wcm9jZXNzQW5zd2VyID0gZnVuY3Rpb24gKHNkcEFuc3dlciwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IChjYWxsYmFjayB8fCBub29wKS5iaW5kKHRoaXMpXG5cbiAgICB2YXIgYW5zd2VyID0gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICB0eXBlOiAnYW5zd2VyJyxcbiAgICAgIHNkcDogc2RwQW5zd2VyXG4gICAgfSlcblxuICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgdmFyIHBsYW5CQW5zd2VyID0gaW50ZXJvcC50b1BsYW5CKGFuc3dlcilcbiAgICAgIGxvZ2dlci5kZWJ1ZygnYXNud2VyOjpwbGFuQicsIGR1bXBTRFAocGxhbkJBbnN3ZXIpKVxuICAgICAgYW5zd2VyID0gcGxhbkJBbnN3ZXJcbiAgICB9XG5cbiAgICBsb2dnZXIuZGVidWcoJ1NEUCBhbnN3ZXIgcmVjZWl2ZWQsIHNldHRpbmcgcmVtb3RlIGRlc2NyaXB0aW9uJylcblxuICAgIGlmIChwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgIHJldHVybiBjYWxsYmFjaygnUGVlckNvbm5lY3Rpb24gaXMgY2xvc2VkJylcbiAgICB9XG5cbiAgICBwYy5zZXRSZW1vdGVEZXNjcmlwdGlvbihhbnN3ZXIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgc2V0UmVtb3RlVmlkZW8oKVxuXG4gICAgICAgIGNhbGxiYWNrKClcbiAgICAgIH0sXG4gICAgICBjYWxsYmFjaylcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayBmdW5jdGlvbiBpbnZva2VkIHdoZW4gYSBTRFAgb2ZmZXIgaXMgcmVjZWl2ZWQuIERldmVsb3BlcnMgYXJlXG4gICAqIGV4cGVjdGVkIHRvIGludm9rZSB0aGlzIGZ1bmN0aW9uIGluIG9yZGVyIHRvIGNvbXBsZXRlIHRoZSBTRFAgbmVnb3RpYXRpb24uXG4gICAqXG4gICAqIEBmdW5jdGlvbiBtb2R1bGU6a3VyZW50b1V0aWxzLldlYlJ0Y1BlZXIucHJvdG90eXBlLnByb2Nlc3NPZmZlclxuICAgKlxuICAgKiBAcGFyYW0gc2RwT2ZmZXIgLSBEZXNjcmlwdGlvbiBvZiBzZHBPZmZlclxuICAgKiBAcGFyYW0gY2FsbGJhY2sgLSBDYWxsZWQgd2hlbiB0aGUgcmVtb3RlIGRlc2NyaXB0aW9uIGhhcyBiZWVuIHNldFxuICAgKiAgc3VjY2Vzc2Z1bGx5LlxuICAgKi9cbiAgdGhpcy5wcm9jZXNzT2ZmZXIgPSBmdW5jdGlvbiAoc2RwT2ZmZXIsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSBjYWxsYmFjay5iaW5kKHRoaXMpXG5cbiAgICB2YXIgb2ZmZXIgPSBuZXcgUlRDU2Vzc2lvbkRlc2NyaXB0aW9uKHtcbiAgICAgIHR5cGU6ICdvZmZlcicsXG4gICAgICBzZHA6IHNkcE9mZmVyXG4gICAgfSlcblxuICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgdmFyIHBsYW5CT2ZmZXIgPSBpbnRlcm9wLnRvUGxhbkIob2ZmZXIpXG4gICAgICBsb2dnZXIuZGVidWcoJ29mZmVyOjpwbGFuQicsIGR1bXBTRFAocGxhbkJPZmZlcikpXG4gICAgICBvZmZlciA9IHBsYW5CT2ZmZXJcbiAgICB9XG5cbiAgICBsb2dnZXIuZGVidWcoJ1NEUCBvZmZlciByZWNlaXZlZCwgc2V0dGluZyByZW1vdGUgZGVzY3JpcHRpb24nKVxuXG4gICAgaWYgKHBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKCdQZWVyQ29ubmVjdGlvbiBpcyBjbG9zZWQnKVxuICAgIH1cblxuICAgIHBjLnNldFJlbW90ZURlc2NyaXB0aW9uKG9mZmVyKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBzZXRSZW1vdGVWaWRlbygpXG4gICAgfSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gcGMuY3JlYXRlQW5zd2VyKClcbiAgICB9KS50aGVuKGZ1bmN0aW9uIChhbnN3ZXIpIHtcbiAgICAgIGFuc3dlciA9IG1hbmdsZVNkcFRvQWRkU2ltdWxjYXN0KGFuc3dlcilcbiAgICAgIGxvZ2dlci5kZWJ1ZygnQ3JlYXRlZCBTRFAgYW5zd2VyJylcbiAgICAgIHJldHVybiBwYy5zZXRMb2NhbERlc2NyaXB0aW9uKGFuc3dlcilcbiAgICB9KS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBsb2NhbERlc2NyaXB0aW9uID0gcGMubG9jYWxEZXNjcmlwdGlvblxuICAgICAgaWYgKG11bHRpc3RyZWFtICYmIHVzZVBsYW5CKSB7XG4gICAgICAgIGxvY2FsRGVzY3JpcHRpb24gPSBpbnRlcm9wLnRvVW5pZmllZFBsYW4obG9jYWxEZXNjcmlwdGlvbilcbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdhbnN3ZXI6Om9yaWdQbGFuQi0+VW5pZmllZFBsYW4nLCBkdW1wU0RQKFxuICAgICAgICAgIGxvY2FsRGVzY3JpcHRpb24pKVxuICAgICAgfVxuICAgICAgbG9nZ2VyLmRlYnVnKCdMb2NhbCBkZXNjcmlwdGlvbiBzZXQnLCBsb2NhbERlc2NyaXB0aW9uLnNkcClcbiAgICAgIGNhbGxiYWNrKG51bGwsIGxvY2FsRGVzY3JpcHRpb24uc2RwKVxuICAgIH0pLmNhdGNoKGNhbGxiYWNrKVxuICB9XG5cbiAgZnVuY3Rpb24gbWFuZ2xlU2RwVG9BZGRTaW11bGNhc3QoYW5zd2VyKSB7XG4gICAgaWYgKHNpbXVsY2FzdCkge1xuICAgICAgaWYgKGJyb3dzZXIubmFtZSA9PT0gJ0Nocm9tZScgfHwgYnJvd3Nlci5uYW1lID09PSAnQ2hyb21pdW0nKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnQWRkaW5nIG11bHRpY2FzdCBpbmZvJylcbiAgICAgICAgYW5zd2VyID0gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICAgICAgJ3R5cGUnOiBhbnN3ZXIudHlwZSxcbiAgICAgICAgICAnc2RwJzogcmVtb3ZlRklERnJvbU9mZmVyKGFuc3dlci5zZHApICsgZ2V0U2ltdWxjYXN0SW5mbyhcbiAgICAgICAgICAgIHZpZGVvU3RyZWFtKVxuICAgICAgICB9KVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ1NpbXVsY2FzdCBpcyBvbmx5IGF2YWlsYWJsZSBpbiBDaHJvbWUgYnJvd3Nlci4nKVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBhbnN3ZXJcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIGZ1bmN0aW9uIGNyZWF0ZXMgdGhlIFJUQ1BlZXJDb25uZWN0aW9uIG9iamVjdCB0YWtpbmcgaW50byBhY2NvdW50IHRoZVxuICAgKiBwcm9wZXJ0aWVzIHJlY2VpdmVkIGluIHRoZSBjb25zdHJ1Y3Rvci4gSXQgc3RhcnRzIHRoZSBTRFAgbmVnb3RpYXRpb25cbiAgICogcHJvY2VzczogZ2VuZXJhdGVzIHRoZSBTRFAgb2ZmZXIgYW5kIGludm9rZXMgdGhlIG9uc2Rwb2ZmZXIgY2FsbGJhY2suIFRoaXNcbiAgICogY2FsbGJhY2sgaXMgZXhwZWN0ZWQgdG8gc2VuZCB0aGUgU0RQIG9mZmVyLCBpbiBvcmRlciB0byBvYnRhaW4gYW4gU0RQXG4gICAqIGFuc3dlciBmcm9tIGFub3RoZXIgcGVlci5cbiAgICovXG4gIGZ1bmN0aW9uIHN0YXJ0KCkge1xuICAgIGlmIChwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgIGNhbGxiYWNrKFxuICAgICAgICAnVGhlIHBlZXIgY29ubmVjdGlvbiBvYmplY3QgaXMgaW4gXCJjbG9zZWRcIiBzdGF0ZS4gVGhpcyBpcyBtb3N0IGxpa2VseSBkdWUgdG8gYW4gaW52b2NhdGlvbiBvZiB0aGUgZGlzcG9zZSBtZXRob2QgYmVmb3JlIGFjY2VwdGluZyBpbiB0aGUgZGlhbG9ndWUnXG4gICAgICApXG4gICAgfVxuXG4gICAgaWYgKHZpZGVvU3RyZWFtICYmIGxvY2FsVmlkZW8pIHtcbiAgICAgIHNlbGYuc2hvd0xvY2FsVmlkZW8oKVxuICAgIH1cblxuICAgIGlmICh2aWRlb1N0cmVhbSkge1xuICAgICAgcGMuYWRkU3RyZWFtKHZpZGVvU3RyZWFtKVxuICAgIH1cblxuICAgIGlmIChhdWRpb1N0cmVhbSkge1xuICAgICAgcGMuYWRkU3RyZWFtKGF1ZGlvU3RyZWFtKVxuICAgIH1cblxuICAgIC8vIFtIYWNrXSBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NDQzNTU4XG4gICAgdmFyIGJyb3dzZXIgPSBwYXJzZXIuZ2V0QnJvd3NlcigpXG4gICAgaWYgKG1vZGUgPT09ICdzZW5kb25seScgJiZcbiAgICAgIChicm93c2VyLm5hbWUgPT09ICdDaHJvbWUnIHx8IGJyb3dzZXIubmFtZSA9PT0gJ0Nocm9taXVtJykgJiZcbiAgICAgIGJyb3dzZXIubWFqb3IgPT09IDM5KSB7XG4gICAgICBtb2RlID0gJ3NlbmRyZWN2J1xuICAgIH1cblxuICAgIGNhbGxiYWNrKClcbiAgfVxuXG4gIGlmIChtb2RlICE9PSAncmVjdm9ubHknICYmICF2aWRlb1N0cmVhbSAmJiAhYXVkaW9TdHJlYW0pIHtcbiAgICBmdW5jdGlvbiBnZXRNZWRpYShjb25zdHJhaW50cykge1xuICAgICAgaWYgKGNvbnN0cmFpbnRzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29uc3RyYWludHMgPSBNRURJQV9DT05TVFJBSU5UU1xuICAgICAgfVxuXG4gICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cykudGhlbihmdW5jdGlvbiAoc3RyZWFtKSB7XG4gICAgICAgIHZpZGVvU3RyZWFtID0gc3RyZWFtXG4gICAgICAgIHN0YXJ0KClcbiAgICAgIH0pLmNhdGNoKGNhbGxiYWNrKTtcbiAgICB9XG4gICAgaWYgKHNlbmRTb3VyY2UgPT09ICd3ZWJjYW0nKSB7XG4gICAgICBnZXRNZWRpYShtZWRpYUNvbnN0cmFpbnRzKVxuICAgIH0gZWxzZSB7XG4gICAgICBnZXRTY3JlZW5Db25zdHJhaW50cyhzZW5kU291cmNlLCBmdW5jdGlvbiAoZXJyb3IsIGNvbnN0cmFpbnRzXykge1xuICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGVycm9yKVxuXG4gICAgICAgIGNvbnN0cmFpbnRzID0gW21lZGlhQ29uc3RyYWludHNdXG4gICAgICAgIGNvbnN0cmFpbnRzLnVuc2hpZnQoY29uc3RyYWludHNfKVxuICAgICAgICBnZXRNZWRpYShyZWN1cnNpdmUuYXBwbHkodW5kZWZpbmVkLCBjb25zdHJhaW50cykpXG4gICAgICB9LCBndWlkKVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBzZXRUaW1lb3V0KHN0YXJ0LCAwKVxuICB9XG5cbiAgdGhpcy5vbignX2Rpc3Bvc2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKGxvY2FsVmlkZW8pIHtcbiAgICAgIGxvY2FsVmlkZW8ucGF1c2UoKVxuICAgICAgbG9jYWxWaWRlby5zcmMgPSAnJ1xuICAgICAgbG9jYWxWaWRlby5sb2FkKClcbiAgICAgIC8vVW5tdXRlIGxvY2FsIHZpZGVvIGluIGNhc2UgdGhlIHZpZGVvIHRhZyBpcyBsYXRlciB1c2VkIGZvciByZW1vdGUgdmlkZW9cbiAgICAgIGxvY2FsVmlkZW8ubXV0ZWQgPSBmYWxzZVxuICAgIH1cbiAgICBpZiAocmVtb3RlVmlkZW8pIHtcbiAgICAgIHJlbW90ZVZpZGVvLnBhdXNlKClcbiAgICAgIHJlbW90ZVZpZGVvLnNyYyA9ICcnXG4gICAgICByZW1vdGVWaWRlby5sb2FkKClcbiAgICB9XG4gICAgc2VsZi5yZW1vdmVBbGxMaXN0ZW5lcnMoKVxuXG4gICAgaWYgKHdpbmRvdy5jYW5jZWxDaG9vc2VEZXNrdG9wTWVkaWEgIT09IHVuZGVmaW5lZCkge1xuICAgICAgd2luZG93LmNhbmNlbENob29zZURlc2t0b3BNZWRpYShndWlkKVxuICAgIH1cbiAgfSlcbn1cbmluaGVyaXRzKFdlYlJ0Y1BlZXIsIEV2ZW50RW1pdHRlcilcblxuZnVuY3Rpb24gY3JlYXRlRW5hYmxlRGVzY3JpcHRvcih0eXBlKSB7XG4gIHZhciBtZXRob2QgPSAnZ2V0JyArIHR5cGUgKyAnVHJhY2tzJ1xuXG4gIHJldHVybiB7XG4gICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFtUb0RvXSBTaG91bGQgcmV0dXJuIHVuZGVmaW5lZCBpZiBub3QgYWxsIHRyYWNrcyBoYXZlIHRoZSBzYW1lIHZhbHVlP1xuXG4gICAgICBpZiAoIXRoaXMucGVlckNvbm5lY3Rpb24pIHJldHVyblxuXG4gICAgICB2YXIgc3RyZWFtcyA9IHRoaXMucGVlckNvbm5lY3Rpb24uZ2V0TG9jYWxTdHJlYW1zKClcbiAgICAgIGlmICghc3RyZWFtcy5sZW5ndGgpIHJldHVyblxuXG4gICAgICBmb3IgKHZhciBpID0gMCwgc3RyZWFtOyBzdHJlYW0gPSBzdHJlYW1zW2ldOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYWNrcyA9IHN0cmVhbVttZXRob2RdKClcbiAgICAgICAgZm9yICh2YXIgaiA9IDAsIHRyYWNrOyB0cmFjayA9IHRyYWNrc1tqXTsgaisrKVxuICAgICAgICAgIGlmICghdHJhY2suZW5hYmxlZCkgcmV0dXJuIGZhbHNlXG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0cnVlXG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgZnVuY3Rpb24gdHJhY2tTZXRFbmFibGUodHJhY2spIHtcbiAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlXG4gICAgICB9XG5cbiAgICAgIHRoaXMucGVlckNvbm5lY3Rpb24uZ2V0TG9jYWxTdHJlYW1zKCkuZm9yRWFjaChmdW5jdGlvbiAoc3RyZWFtKSB7XG4gICAgICAgIHN0cmVhbVttZXRob2RdKCkuZm9yRWFjaCh0cmFja1NldEVuYWJsZSlcbiAgICAgIH0pXG4gICAgfVxuICB9XG59XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKFdlYlJ0Y1BlZXIucHJvdG90eXBlLCB7XG4gICdlbmFibGVkJzoge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gdGhpcy5hdWRpb0VuYWJsZWQgJiYgdGhpcy52aWRlb0VuYWJsZWRcbiAgICB9LFxuICAgIHNldDogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICB0aGlzLmF1ZGlvRW5hYmxlZCA9IHRoaXMudmlkZW9FbmFibGVkID0gdmFsdWVcbiAgICB9XG4gIH0sXG4gICdhdWRpb0VuYWJsZWQnOiBjcmVhdGVFbmFibGVEZXNjcmlwdG9yKCdBdWRpbycpLFxuICAndmlkZW9FbmFibGVkJzogY3JlYXRlRW5hYmxlRGVzY3JpcHRvcignVmlkZW8nKVxufSlcblxuV2ViUnRjUGVlci5wcm90b3R5cGUuZ2V0TG9jYWxTdHJlYW0gPSBmdW5jdGlvbiAoaW5kZXgpIHtcbiAgaWYgKHRoaXMucGVlckNvbm5lY3Rpb24pIHtcbiAgICByZXR1cm4gdGhpcy5wZWVyQ29ubmVjdGlvbi5nZXRMb2NhbFN0cmVhbXMoKVtpbmRleCB8fCAwXVxuICB9XG59XG5cbldlYlJ0Y1BlZXIucHJvdG90eXBlLmdldFJlbW90ZVN0cmVhbSA9IGZ1bmN0aW9uIChpbmRleCkge1xuICBpZiAodGhpcy5wZWVyQ29ubmVjdGlvbikge1xuICAgIHJldHVybiB0aGlzLnBlZXJDb25uZWN0aW9uLmdldFJlbW90ZVN0cmVhbXMoKVtpbmRleCB8fCAwXVxuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFRoaXMgbWV0aG9kIGZyZWVzIHRoZSByZXNvdXJjZXMgdXNlZCBieSBXZWJSdGNQZWVyLlxuICpcbiAqIEBmdW5jdGlvbiBtb2R1bGU6a3VyZW50b1V0aWxzLldlYlJ0Y1BlZXIucHJvdG90eXBlLmRpc3Bvc2VcbiAqL1xuV2ViUnRjUGVlci5wcm90b3R5cGUuZGlzcG9zZSA9IGZ1bmN0aW9uICgpIHtcbiAgbG9nZ2VyLmRlYnVnKCdEaXNwb3NpbmcgV2ViUnRjUGVlcicpXG5cbiAgdmFyIHBjID0gdGhpcy5wZWVyQ29ubmVjdGlvblxuICB2YXIgZGMgPSB0aGlzLmRhdGFDaGFubmVsXG4gIHRyeSB7XG4gICAgaWYgKGRjKSB7XG4gICAgICBpZiAoZGMuc2lnbmFsaW5nU3RhdGUgPT09ICdjbG9zZWQnKSByZXR1cm5cblxuICAgICAgZGMuY2xvc2UoKVxuICAgIH1cblxuICAgIGlmIChwYykge1xuICAgICAgaWYgKHBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykgcmV0dXJuXG5cbiAgICAgIHBjLmdldExvY2FsU3RyZWFtcygpLmZvckVhY2goc3RyZWFtU3RvcClcblxuICAgICAgLy8gRklYTUUgVGhpcyBpcyBub3QgeWV0IGltcGxlbWVudGVkIGluIGZpcmVmb3hcbiAgICAgIC8vIGlmKHZpZGVvU3RyZWFtKSBwYy5yZW1vdmVTdHJlYW0odmlkZW9TdHJlYW0pO1xuICAgICAgLy8gaWYoYXVkaW9TdHJlYW0pIHBjLnJlbW92ZVN0cmVhbShhdWRpb1N0cmVhbSk7XG5cbiAgICAgIHBjLmNsb3NlKClcbiAgICB9XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGxvZ2dlci53YXJuKCdFeGNlcHRpb24gZGlzcG9zaW5nIHdlYnJ0YyBwZWVyICcgKyBlcnIpXG4gIH1cblxuICB0aGlzLmVtaXQoJ19kaXNwb3NlJylcbn1cblxuLy9cbi8vIFNwZWNpYWxpemVkIGNoaWxkIGNsYXNzZXNcbi8vXG5cbmZ1bmN0aW9uIFdlYlJ0Y1BlZXJSZWN2b25seShvcHRpb25zLCBjYWxsYmFjaykge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgV2ViUnRjUGVlclJlY3Zvbmx5KSkge1xuICAgIHJldHVybiBuZXcgV2ViUnRjUGVlclJlY3Zvbmx5KG9wdGlvbnMsIGNhbGxiYWNrKVxuICB9XG5cbiAgV2ViUnRjUGVlclJlY3Zvbmx5LnN1cGVyXy5jYWxsKHRoaXMsICdyZWN2b25seScsIG9wdGlvbnMsIGNhbGxiYWNrKVxufVxuaW5oZXJpdHMoV2ViUnRjUGVlclJlY3Zvbmx5LCBXZWJSdGNQZWVyKVxuXG5mdW5jdGlvbiBXZWJSdGNQZWVyU2VuZG9ubHkob3B0aW9ucywgY2FsbGJhY2spIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFdlYlJ0Y1BlZXJTZW5kb25seSkpIHtcbiAgICByZXR1cm4gbmV3IFdlYlJ0Y1BlZXJTZW5kb25seShvcHRpb25zLCBjYWxsYmFjaylcbiAgfVxuXG4gIFdlYlJ0Y1BlZXJTZW5kb25seS5zdXBlcl8uY2FsbCh0aGlzLCAnc2VuZG9ubHknLCBvcHRpb25zLCBjYWxsYmFjaylcbn1cbmluaGVyaXRzKFdlYlJ0Y1BlZXJTZW5kb25seSwgV2ViUnRjUGVlcilcblxuZnVuY3Rpb24gV2ViUnRjUGVlclNlbmRyZWN2KG9wdGlvbnMsIGNhbGxiYWNrKSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBXZWJSdGNQZWVyU2VuZHJlY3YpKSB7XG4gICAgcmV0dXJuIG5ldyBXZWJSdGNQZWVyU2VuZHJlY3Yob3B0aW9ucywgY2FsbGJhY2spXG4gIH1cblxuICBXZWJSdGNQZWVyU2VuZHJlY3Yuc3VwZXJfLmNhbGwodGhpcywgJ3NlbmRyZWN2Jywgb3B0aW9ucywgY2FsbGJhY2spXG59XG5pbmhlcml0cyhXZWJSdGNQZWVyU2VuZHJlY3YsIFdlYlJ0Y1BlZXIpXG5cbmZ1bmN0aW9uIGhhcmtVdGlscyhzdHJlYW0sIG9wdGlvbnMpIHtcbiAgcmV0dXJuIGhhcmsoc3RyZWFtLCBvcHRpb25zKTtcbn1cblxuZXhwb3J0cy5idWZmZXJpemVDYW5kaWRhdGVzID0gYnVmZmVyaXplQ2FuZGlkYXRlc1xuXG5leHBvcnRzLldlYlJ0Y1BlZXJSZWN2b25seSA9IFdlYlJ0Y1BlZXJSZWN2b25seVxuZXhwb3J0cy5XZWJSdGNQZWVyU2VuZG9ubHkgPSBXZWJSdGNQZWVyU2VuZG9ubHlcbmV4cG9ydHMuV2ViUnRjUGVlclNlbmRyZWN2ID0gV2ViUnRjUGVlclNlbmRyZWN2XG5leHBvcnRzLmhhcmsgPSBoYXJrVXRpbHNcbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG4vKipcbiAqIFRoaXMgbW9kdWxlIGNvbnRhaW5zIGEgc2V0IG9mIHJldXNhYmxlIGNvbXBvbmVudHMgdGhhdCBoYXZlIGJlZW4gZm91bmQgdXNlZnVsXG4gKiBkdXJpbmcgdGhlIGRldmVsb3BtZW50IG9mIHRoZSBXZWJSVEMgYXBwbGljYXRpb25zIHdpdGggS3VyZW50by5cbiAqIFxuICogQG1vZHVsZSBrdXJlbnRvVXRpbHNcbiAqIFxuICogQGNvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKiBAbGljZW5zZSBBTHYyXG4gKi9cblxudmFyIFdlYlJ0Y1BlZXIgPSByZXF1aXJlKCcuL1dlYlJ0Y1BlZXInKTtcblxuZXhwb3J0cy5XZWJSdGNQZWVyID0gV2ViUnRjUGVlcjtcbiIsImltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdSc7XG5cbi8vVGhpcyBleHBvcnQgd2l0aCAtLXN0YW5kYWxvbmUgb3B0aW9uIGFsbG93cyB1c2luZyBPcGVuVmlkdSBmcm9tIGJvd3NlciB3aXRoIG5hbWVzcGFjZVxuLy9leHBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuXG4vL1RoaXMgXCJoYWNrXCIgYWxsb3dzIHRvIHVzZSBPcGVuVmlkdSBmcm9tIHRoZSBnbG9iYWwgc3BhY2Ugd2luZG93XG5pZih3aW5kb3cpe1xuICAgIHdpbmRvd1tcIk9wZW5WaWR1XCJdID0gT3BlblZpZHU7XG59XG5cbi8vQ29tbWFuZCB0byBnZW5lcmF0ZSBidW5kbGUuanMgd2l0aG91dCBuYW1lc3BhY2Vcbi8vd2F0Y2hpZnkgTWFpbi50cyAtcCBbIHRzaWZ5IF0gLS1leGNsdWRlIGt1cmVudG8tYnJvd3Nlci1leHRlbnNpb25zIC0tZGVidWcgLW8gLi4vc3RhdGljL2pzL09wZW5WaWR1LmpzIC12IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNyBPcGVuVmlkdSAoaHR0cDovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuaW1wb3J0IHsgT3BlblZpZHVJbnRlcm5hbCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvT3BlblZpZHVJbnRlcm5hbCc7XG5cbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi9QdWJsaXNoZXInO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TdHJlYW0nO1xuaW1wb3J0IHsgTG9jYWxSZWNvcmRlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvTG9jYWxSZWNvcmRlcic7XG5cbmltcG9ydCAqIGFzIGFkYXB0ZXIgZnJvbSAnd2VicnRjLWFkYXB0ZXInO1xuaW1wb3J0ICogYXMgc2NyZWVuU2hhcmluZyBmcm9tICcuLi9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcuanMnO1xuaW1wb3J0ICogYXMgc2NyZWVuU2hhcmluZ0F1dG8gZnJvbSAnLi4vU2NyZWVuU2hhcmluZy9TY3JlZW4tQ2FwdHVyaW5nLUF1dG8uanMnO1xuaW1wb3J0ICogYXMgRGV0ZWN0UlRDIGZyb20gJy4uL0t1cmVudG9VdGlscy9EZXRlY3RSVEMnO1xuXG5pZiAod2luZG93KSB7XG4gICAgd2luZG93W1wiYWRhcHRlclwiXSA9IGFkYXB0ZXI7XG59XG5cbmV4cG9ydCBjbGFzcyBPcGVuVmlkdSB7XG5cbiAgICBvcGVuVmlkdTogT3BlblZpZHVJbnRlcm5hbDtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLm9wZW5WaWR1ID0gbmV3IE9wZW5WaWR1SW50ZXJuYWwoKTtcbiAgICAgICAgY29uc29sZS5pbmZvKFwiJ09wZW5WaWR1JyBpbml0aWFsaXplZFwiKTtcbiAgICB9O1xuXG4gICAgaW5pdFNlc3Npb24oYXBpS2V5OiBzdHJpbmcsIHNlc3Npb25JZDogc3RyaW5nKTogU2Vzc2lvbjtcbiAgICBpbml0U2Vzc2lvbihzZXNzaW9uSWQ6IHN0cmluZyk6IFNlc3Npb247XG5cbiAgICBpbml0U2Vzc2lvbihwYXJhbTEsIHBhcmFtMj8pOiBhbnkge1xuICAgICAgICBpZiAodHlwZW9mIHBhcmFtMiA9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFNlc3Npb24odGhpcy5vcGVuVmlkdS5pbml0U2Vzc2lvbihwYXJhbTIpLCB0aGlzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgU2Vzc2lvbih0aGlzLm9wZW5WaWR1LmluaXRTZXNzaW9uKHBhcmFtMSksIHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaW5pdFB1Ymxpc2hlcihwYXJlbnRJZDogc3RyaW5nKTogUHVibGlzaGVyO1xuICAgIGluaXRQdWJsaXNoZXIocGFyZW50SWQ6IHN0cmluZywgY2FtZXJhT3B0aW9uczogYW55KTogUHVibGlzaGVyO1xuICAgIGluaXRQdWJsaXNoZXIocGFyZW50SWQ6IHN0cmluZywgY2FtZXJhT3B0aW9uczogYW55LCBjYWxsYmFjazogYW55KTogUHVibGlzaGVyO1xuXG4gICAgaW5pdFB1Ymxpc2hlcihwYXJlbnRJZDogc3RyaW5nLCBjYW1lcmFPcHRpb25zPzogYW55LCBjYWxsYmFjaz86IEZ1bmN0aW9uKTogYW55IHtcblxuICAgICAgICBsZXQgcHVibGlzaGVyOiBQdWJsaXNoZXI7XG4gICAgICAgIGlmIChjYW1lcmFPcHRpb25zICE9IG51bGwpIHtcblxuICAgICAgICAgICAgY2FtZXJhT3B0aW9ucy5hdWRpbyA9IGNhbWVyYU9wdGlvbnMuYXVkaW8gIT0gbnVsbCA/IGNhbWVyYU9wdGlvbnMuYXVkaW8gOiB0cnVlO1xuICAgICAgICAgICAgY2FtZXJhT3B0aW9ucy52aWRlbyA9IGNhbWVyYU9wdGlvbnMudmlkZW8gIT0gbnVsbCA/IGNhbWVyYU9wdGlvbnMudmlkZW8gOiB0cnVlO1xuXG4gICAgICAgICAgICBpZiAoIWNhbWVyYU9wdGlvbnMuc2NyZWVuKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBXZWJjYW0gYW5kL29yIG1pY3JvcGhvbmUgaXMgYmVpbmcgcmVxdWVzdGVkXG5cbiAgICAgICAgICAgICAgICBsZXQgY2FtZXJhT3B0aW9uc0F1eCA9IHtcbiAgICAgICAgICAgICAgICAgICAgc2VuZEF1ZGlvOiBjYW1lcmFPcHRpb25zLmF1ZGlvICE9IG51bGwgPyBjYW1lcmFPcHRpb25zLmF1ZGlvIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgc2VuZFZpZGVvOiBjYW1lcmFPcHRpb25zLnZpZGVvICE9IG51bGwgPyBjYW1lcmFPcHRpb25zLnZpZGVvIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgYWN0aXZlQXVkaW86IGNhbWVyYU9wdGlvbnMuYXVkaW9BY3RpdmUgIT0gbnVsbCA/IGNhbWVyYU9wdGlvbnMuYXVkaW9BY3RpdmUgOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBhY3RpdmVWaWRlbzogY2FtZXJhT3B0aW9ucy52aWRlb0FjdGl2ZSAhPSBudWxsID8gY2FtZXJhT3B0aW9ucy52aWRlb0FjdGl2ZSA6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIGRhdGFDaGFubmVsOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzOiB0aGlzLm9wZW5WaWR1LmdlbmVyYXRlTWVkaWFDb25zdHJhaW50cyhjYW1lcmFPcHRpb25zKVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgY2FtZXJhT3B0aW9ucyA9IGNhbWVyYU9wdGlvbnNBdXg7XG5cbiAgICAgICAgICAgICAgICBwdWJsaXNoZXIgPSBuZXcgUHVibGlzaGVyKHRoaXMub3BlblZpZHUuaW5pdFB1Ymxpc2hlclRhZ2dlZChwYXJlbnRJZCwgY2FtZXJhT3B0aW9ucywgdHJ1ZSwgY2FsbGJhY2spLCBwYXJlbnRJZCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIGluaXRpYWxpemVkXCIpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHB1Ymxpc2hlcjtcblxuICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgIC8vIFNjcmVlbiBzaGFyZSBpcyBiZWluZyByZXF1ZXN0ZWRcblxuICAgICAgICAgICAgICAgIHB1Ymxpc2hlciA9IG5ldyBQdWJsaXNoZXIodGhpcy5vcGVuVmlkdS5pbml0UHVibGlzaGVyU2NyZWVuKHBhcmVudElkLCB0cnVlLCBjYWxsYmFjayksIHBhcmVudElkLCB0cnVlKTtcbiAgICAgICAgICAgICAgICBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIubmFtZSA9PT0gJ0ZpcmVmb3gnICYmIERldGVjdFJUQy5icm93c2VyLnZlcnNpb24gPj0gNTIpIHtcbiAgICAgICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZ0F1dG8uZ2V0U2NyZWVuSWQoKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbWVyYU9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VuZEF1ZGlvOiBjYW1lcmFPcHRpb25zLmF1ZGlvLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRWaWRlbzogY2FtZXJhT3B0aW9ucy52aWRlbyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY3RpdmVBdWRpbzogY2FtZXJhT3B0aW9ucy5hdWRpb0FjdGl2ZSAhPSBudWxsID8gY2FtZXJhT3B0aW9ucy5hdWRpb0FjdGl2ZSA6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWN0aXZlVmlkZW86IGNhbWVyYU9wdGlvbnMudmlkZW9BY3RpdmUgIT0gbnVsbCA/IGNhbWVyYU9wdGlvbnMudmlkZW9BY3RpdmUgOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFDaGFubmVsOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlkZW86IHNjcmVlbkNvbnN0cmFpbnRzLnZpZGVvLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpbzogZmFsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0uY29uZmlndXJlU2NyZWVuT3B0aW9ucyhjYW1lcmFPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIGluaXRpYWxpemVkXCIpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLmVlLmVtaXRFdmVudCgnY2FuLXJlcXVlc3Qtc2NyZWVuJyk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcHVibGlzaGVyO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIubmFtZSA9PT0gJ0Nocm9tZScpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gU2NyZWVuIGlzIGJlaW5nIHJlcXVlc3RlZFxuXG4gICAgICAgICAgICAgICAgICAgIC8qc2NyZWVuU2hhcmluZy5pc0Nocm9tZUV4dGVuc2lvbkF2YWlsYWJsZSgoYXZhaWxhYmlsaXR5KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGF2YWlsYWJpbGl0eSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2F2YWlsYWJsZSc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignRVhURU5TSU9OIEFWQUlMQUJMRSEhIScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nLmdldFNjcmVlbkNvbnN0cmFpbnRzKChlcnJvciwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oc2NyZWVuQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndW5hdmFpbGFibGUnOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0VYVEVOU0lPTiBOT1QgQVZBSUxBQkxFISEhJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2lzRmlyZWZveCc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignSVQgSVMgRklSRUZPWCEhIScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nLmdldFNjcmVlbkNvbnN0cmFpbnRzKChlcnJvciwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oc2NyZWVuQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pOyovXG4gICAgICAgICAgICAgICAgICAgIHNjcmVlblNoYXJpbmdBdXRvLmdldFNjcmVlbklkKChlcnJvciwgc291cmNlSWQsIHNjcmVlbkNvbnN0cmFpbnRzKSA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVELCAnaHR0cHM6Ly9jaHJvbWUuZ29vZ2xlLmNvbS93ZWJzdG9yZS9kZXRhaWwvc2NyZWVuLWNhcHR1cmluZy9hamhpZmRkaW1rYXBnY2lmZ2NvZG1tZmRsa25haGZmaycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjYWxsYmFjaykgY2FsbGJhY2soZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgPT09ICdwZXJtaXNzaW9uLWRlbmllZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQsICdZb3UgbXVzdCBhbGxvdyBhY2Nlc3MgdG8gb25lIHdpbmRvdyBvZiB5b3VyIGRlc2t0b3AnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2FsbGJhY2spIGNhbGxiYWNrKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbWVyYU9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VuZEF1ZGlvOiBjYW1lcmFPcHRpb25zLmF1ZGlvICE9IG51bGwgPyBjYW1lcmFPcHRpb25zLmF1ZGlvIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kVmlkZW86IGNhbWVyYU9wdGlvbnMudmlkZW8gIT0gbnVsbCA/IGNhbWVyYU9wdGlvbnMudmlkZW8gOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjdGl2ZUF1ZGlvOiBjYW1lcmFPcHRpb25zLmF1ZGlvQWN0aXZlICE9IG51bGwgPyBjYW1lcmFPcHRpb25zLmF1ZGlvQWN0aXZlIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY3RpdmVWaWRlbzogY2FtZXJhT3B0aW9ucy52aWRlb0FjdGl2ZSAhPSBudWxsID8gY2FtZXJhT3B0aW9ucy52aWRlb0FjdGl2ZSA6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YUNoYW5uZWw6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWRlbzogc2NyZWVuQ29uc3RyYWludHMudmlkZW8sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvOiBmYWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5jb25maWd1cmVTY3JlZW5PcHRpb25zKGNhbWVyYU9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLmVlLmVtaXRFdmVudCgnY2FuLXJlcXVlc3Qtc2NyZWVuJyk7XG4gICAgICAgICAgICAgICAgICAgIH0sIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignZ2V0U2NyZWVuSWQgZXJyb3InLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBpbml0aWFsaXplZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHB1Ymxpc2hlcjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdTY3JlZW4gc2hhcmluZyBub3Qgc3VwcG9ydGVkIG9uICcgKyBEZXRlY3RSVEMuYnJvd3Nlci5uYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhY2FsbGJhY2spIGNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQsICdTY3JlZW4gc2hhcmluZyBub3Qgc3VwcG9ydGVkIG9uICcgKyBEZXRlY3RSVEMuYnJvd3Nlci5uYW1lICsgJyAnICsgRGV0ZWN0UlRDLmJyb3dzZXIudmVyc2lvbikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNhbWVyYU9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgc2VuZEF1ZGlvOiB0cnVlLFxuICAgICAgICAgICAgICAgIHNlbmRWaWRlbzogdHJ1ZSxcbiAgICAgICAgICAgICAgICBhY3RpdmVBdWRpbzogdHJ1ZSxcbiAgICAgICAgICAgICAgICBhY3RpdmVWaWRlbzogdHJ1ZSxcbiAgICAgICAgICAgICAgICBkYXRhQ2hhbm5lbDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzOiB7XG4gICAgICAgICAgICAgICAgICAgIGF1ZGlvOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICB2aWRlbzogeyB3aWR0aDogeyBpZGVhbDogMTI4MCB9IH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwdWJsaXNoZXIgPSBuZXcgUHVibGlzaGVyKHRoaXMub3BlblZpZHUuaW5pdFB1Ymxpc2hlclRhZ2dlZChwYXJlbnRJZCwgY2FtZXJhT3B0aW9ucywgdHJ1ZSwgY2FsbGJhY2spLCBwYXJlbnRJZCwgZmFsc2UpO1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiJ1B1Ymxpc2hlcicgaW5pdGlhbGl6ZWRcIik7XG5cbiAgICAgICAgICAgIHJldHVybiBwdWJsaXNoZXI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZWluaXRQdWJsaXNoZXIocHVibGlzaGVyOiBQdWJsaXNoZXIpOiBhbnkge1xuICAgICAgICBpZiAocHVibGlzaGVyLnN0cmVhbS50eXBlT2ZWaWRlbyAhPT0gJ1NDUkVFTicpIHtcbiAgICAgICAgICAgIHB1Ymxpc2hlciA9IG5ldyBQdWJsaXNoZXIodGhpcy5vcGVuVmlkdS5pbml0UHVibGlzaGVyVGFnZ2VkKHB1Ymxpc2hlci5zdHJlYW0uZ2V0UGFyZW50SWQoKSwgcHVibGlzaGVyLnN0cmVhbS5vdXRib3VuZE9wdGlvbnMsIGZhbHNlKSwgcHVibGlzaGVyLnN0cmVhbS5nZXRQYXJlbnRJZCgpLCBmYWxzZSk7XG4gICAgICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBpbml0aWFsaXplZFwiKTtcbiAgICAgICAgICAgIHJldHVybiBwdWJsaXNoZXI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwdWJsaXNoZXIgPSBuZXcgUHVibGlzaGVyKHRoaXMub3BlblZpZHUuaW5pdFB1Ymxpc2hlclNjcmVlbihwdWJsaXNoZXIuc3RyZWFtLmdldFBhcmVudElkKCksIGZhbHNlKSwgcHVibGlzaGVyLnN0cmVhbS5nZXRQYXJlbnRJZCgpLCB0cnVlKTtcbiAgICAgICAgICAgIGlmIChEZXRlY3RSVEMuYnJvd3Nlci5uYW1lID09PSAnRmlyZWZveCcgJiYgRGV0ZWN0UlRDLmJyb3dzZXIudmVyc2lvbiA+PSA1Mikge1xuICAgICAgICAgICAgICAgIHNjcmVlblNoYXJpbmdBdXRvLmdldFNjcmVlbklkKChlcnJvciwgc291cmNlSWQsIHNjcmVlbkNvbnN0cmFpbnRzKSA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5vdXRib3VuZE9wdGlvbnMubWVkaWFDb25zdHJhaW50cy52aWRlbyA9IHNjcmVlbkNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLmNvbmZpZ3VyZVNjcmVlbk9wdGlvbnMocHVibGlzaGVyLnN0cmVhbS5vdXRib3VuZE9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBpbml0aWFsaXplZFwiKTtcblxuICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLmVlLmVtaXRFdmVudCgnY2FuLXJlcXVlc3Qtc2NyZWVuJyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHB1Ymxpc2hlcjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIubmFtZSA9PT0gJ0Nocm9tZScpIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nQXV0by5nZXRTY3JlZW5JZCgoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5Db25zdHJhaW50cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IgPT09ICdub3QtaW5zdGFsbGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVELCAnaHR0cHM6Ly9jaHJvbWUuZ29vZ2xlLmNvbS93ZWJzdG9yZS9kZXRhaWwvc2NyZWVuLWNhcHR1cmluZy9hamhpZmRkaW1rYXBnY2lmZ2NvZG1tZmRsa25haGZmaycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgPT09ICdwZXJtaXNzaW9uLWRlbmllZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5vdXRib3VuZE9wdGlvbnMubWVkaWFDb25zdHJhaW50cy52aWRlbyA9IHNjcmVlbkNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLmNvbmZpZ3VyZVNjcmVlbk9wdGlvbnMocHVibGlzaGVyLnN0cmVhbS5vdXRib3VuZE9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0uZWUuZW1pdEV2ZW50KCdjYW4tcmVxdWVzdC1zY3JlZW4nKTtcbiAgICAgICAgICAgICAgICB9LCAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignZ2V0U2NyZWVuSWQgZXJyb3InLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBpbml0aWFsaXplZFwiKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcHVibGlzaGVyO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdTY3JlZW4gc2hhcmluZyBub3Qgc3VwcG9ydGVkIG9uICcgKyBEZXRlY3RSVEMuYnJvd3Nlci5uYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNoZWNrU3lzdGVtUmVxdWlyZW1lbnRzKCk6IG51bWJlciB7XG5cbiAgICAgICAgbGV0IGRlZmF1bHRXZWJSVENTdXBwb3J0OiBib29sZWFuID0gRGV0ZWN0UlRDLmlzV2ViUlRDU3VwcG9ydGVkO1xuICAgICAgICBsZXQgYnJvd3NlciA9IERldGVjdFJUQy5icm93c2VyLm5hbWU7XG4gICAgICAgIGxldCB2ZXJzaW9uID0gRGV0ZWN0UlRDLmJyb3dzZXIudmVyc2lvbjtcblxuICAgICAgICBpZiAoKGJyb3dzZXIgIT09ICdDaHJvbWUnKSAmJiAoYnJvd3NlciAhPT0gJ0ZpcmVmb3gnKSAmJiAoYnJvd3NlciAhPT0gJ09wZXJhJykpIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGRlZmF1bHRXZWJSVENTdXBwb3J0ID8gMSA6IDA7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBnZXREZXZpY2VzKGNhbGxiYWNrKSB7XG4gICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZW51bWVyYXRlRGV2aWNlcygpLnRoZW4oKGRldmljZUluZm9zKSA9PiB7XG4gICAgICAgICAgICBjYWxsYmFjayhudWxsLCBkZXZpY2VJbmZvcyk7XG4gICAgICAgIH0pLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIGdldHRpbmcgZGV2aWNlc1wiLCBlcnJvcik7XG4gICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGVuYWJsZVByb2RNb2RlKCkge1xuICAgICAgICBjb25zb2xlLmxvZyA9IGZ1bmN0aW9uICgpIHsgfTtcbiAgICAgICAgY29uc29sZS5kZWJ1ZyA9IGZ1bmN0aW9uICgpIHsgfTtcbiAgICAgICAgY29uc29sZS5pbmZvID0gZnVuY3Rpb24gKCkgeyB9O1xuICAgICAgICBjb25zb2xlLndhcm4gPSBmdW5jdGlvbiAoKSB7IH07XG4gICAgfVxuXG4gICAgaW5pdExvY2FsUmVjb3JkZXIoc3RyZWFtOiBTdHJlYW0pOiBMb2NhbFJlY29yZGVyIHtcbiAgICAgICAgcmV0dXJuIG5ldyBMb2NhbFJlY29yZGVyKHN0cmVhbSk7XG4gICAgfVxuXG59XG4iLCIvKlxuICogb3B0aW9uczogbmFtZTogWFhYIGRhdGE6IHRydWUgKE1heWJlIHRoaXMgaXMgYmFzZWQgb24gd2VicnRjKSBhdWRpbzogdHJ1ZSxcbiAqIHZpZGVvOiB0cnVlLCB1cmw6IFwiZmlsZTovLy8uLi5cIiA+IFBsYXllciBzY3JlZW46IHRydWUgPiBEZXNrdG9wIChpbXBsaWNpdFxuICogdmlkZW86dHJ1ZSwgYXVkaW86ZmFsc2UpIGF1ZGlvOiB0cnVlLCB2aWRlbzogdHJ1ZSA+IFdlYmNhbVxuICpcbiAqIHN0cmVhbS5oYXNBdWRpbygpOyBzdHJlYW0uaGFzVmlkZW8oKTsgc3RyZWFtLmhhc0RhdGEoKTtcbiAqL1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TdHJlYW0nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5cbmltcG9ydCBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCd3b2xmeTg3LWV2ZW50ZW1pdHRlcicpO1xuXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyIHtcblxuICAgIGVlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gICAgYWNjZXNzQWxsb3dlZCA9IGZhbHNlO1xuICAgIGVsZW1lbnQ6IEVsZW1lbnQ7XG4gICAgaWQ6IHN0cmluZztcbiAgICBzdHJlYW06IFN0cmVhbTtcbiAgICBzZXNzaW9uOiBTZXNzaW9uOyAvL0luaXRpYWxpemVkIGJ5IFNlc3Npb24ucHVibGlzaChQdWJsaXNoZXIpXG4gICAgaXNTY3JlZW5SZXF1ZXN0ZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtLCBwYXJlbnRJZDogc3RyaW5nLCBpc1NjcmVlblJlcXVlc3RlZDogYm9vbGVhbikge1xuICAgICAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTtcbiAgICAgICAgdGhpcy5pc1NjcmVlblJlcXVlc3RlZCA9IGlzU2NyZWVuUmVxdWVzdGVkO1xuXG4gICAgICAgIC8vIExpc3RlbnMgdG8gdGhlIGRlYWN0aXZhdGlvbiBvZiB0aGUgZGVmYXVsdCBiZWhhdmlvdXIgdXBvbiB0aGUgZGVsZXRpb24gb2YgYSBTdHJlYW0gb2JqZWN0XG4gICAgICAgIHRoaXMuZWUuYWRkTGlzdGVuZXIoJ3N0cmVhbS1kZXN0cm95ZWQtZGVmYXVsdCcsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGxldCBzOiBTdHJlYW0gPSBldmVudC5zdHJlYW07XG4gICAgICAgICAgICBzLmFkZE9uY2VFdmVudExpc3RlbmVyKCd2aWRlby1yZW1vdmVkJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnREZXN0cm95ZWQnKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcy5yZW1vdmVWaWRlbygpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocGFyZW50SWQpICE9IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuZWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHBhcmVudElkKSEhO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGlzaEF1ZGlvKHZhbHVlOiBib29sZWFuKSB7XG4gICAgICAgIHRoaXMuc3RyZWFtLmdldFdlYlJ0Y1BlZXIoKS5hdWRpb0VuYWJsZWQgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICBwdWJsaXNoVmlkZW8odmFsdWU6IGJvb2xlYW4pIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0V2ViUnRjUGVlcigpLnZpZGVvRW5hYmxlZCA9IHZhbHVlO1xuICAgIH1cblxuICAgIGRlc3Ryb3koKSB7XG4gICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbikgdGhpcy5zZXNzaW9uLnVucHVibGlzaCh0aGlzKTtcbiAgICAgICAgdGhpcy5zdHJlYW0uZGlzcG9zZSgpO1xuICAgICAgICB0aGlzLnN0cmVhbS5yZW1vdmVWaWRlbyh0aGlzLmVsZW1lbnQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBzdWJzY3JpYmVUb1JlbW90ZSgpIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uc3Vic2NyaWJlVG9NeVJlbW90ZSgpO1xuICAgIH1cblxuICAgIG9uKGV2ZW50TmFtZTogc3RyaW5nLCBjYWxsYmFjaykge1xuICAgICAgICB0aGlzLmVlLmFkZExpc3RlbmVyKGV2ZW50TmFtZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgZXZlbnROYW1lICsgXCInIHRyaWdnZXJlZCBieSAnUHVibGlzaGVyJ1wiLCBldmVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIGV2ZW50TmFtZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1B1Ymxpc2hlcidcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYWxsYmFjayhldmVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoZXZlbnROYW1lID09ICdzdHJlYW1DcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzUHVibGlzaGVyUHVibGlzaGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbeyBzdHJlYW06IHRoaXMuc3RyZWFtIH1dKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uYWRkRXZlbnRMaXN0ZW5lcignc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFt7IHN0cmVhbTogdGhpcy5zdHJlYW0gfV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChldmVudE5hbWUgPT0gJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNWaWRlb0VMZW1lbnRDcmVhdGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudENyZWF0ZWQnLCBbe1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50OiB0aGlzLnN0cmVhbS5nZXRWaWRlb0VsZW1lbnQoKVxuICAgICAgICAgICAgICAgIH1dKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uYWRkRXZlbnRMaXN0ZW5lcigndmlkZW8tZWxlbWVudC1jcmVhdGVkLWJ5LXN0cmVhbScsIChlbGVtZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaWQgPSBlbGVtZW50LmlkO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFt7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50OiBlbGVtZW50LmVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChldmVudE5hbWUgPT0gJ3ZpZGVvUGxheWluZycpIHtcbiAgICAgICAgICAgIHZhciB2aWRlbyA9IHRoaXMuc3RyZWFtLmdldFZpZGVvRWxlbWVudCgpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLnN0cmVhbS5kaXNwbGF5TXlSZW1vdGUoKSAmJiB2aWRlbyAmJlxuICAgICAgICAgICAgICAgIHZpZGVvLmN1cnJlbnRUaW1lID4gMCAmJlxuICAgICAgICAgICAgICAgIHZpZGVvLnBhdXNlZCA9PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHZpZGVvLmVuZGVkID09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdmlkZW8ucmVhZHlTdGF0ZSA9PSA0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvUGxheWluZycsIFt7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQ6IHRoaXMuc3RyZWFtLmdldFZpZGVvRWxlbWVudCgpXG4gICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5hZGRFdmVudExpc3RlbmVyKCd2aWRlby1pcy1wbGF5aW5nJywgKGVsZW1lbnQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvUGxheWluZycsIFt7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50OiBlbGVtZW50LmVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChldmVudE5hbWUgPT0gJ3JlbW90ZVZpZGVvUGxheWluZycpIHtcbiAgICAgICAgICAgIHZhciB2aWRlbyA9IHRoaXMuc3RyZWFtLmdldFZpZGVvRWxlbWVudCgpO1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpICYmIHZpZGVvICYmXG4gICAgICAgICAgICAgICAgdmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdmlkZW8ucGF1c2VkID09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdmlkZW8uZW5kZWQgPT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB2aWRlby5yZWFkeVN0YXRlID09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncmVtb3RlVmlkZW9QbGF5aW5nJywgW3tcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudDogdGhpcy5zdHJlYW0uZ2V0VmlkZW9FbGVtZW50KClcbiAgICAgICAgICAgICAgICB9XSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmFkZEV2ZW50TGlzdGVuZXIoJ3JlbW90ZS12aWRlby1pcy1wbGF5aW5nJywgKGVsZW1lbnQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlbW90ZVZpZGVvUGxheWluZycsIFt7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50OiBlbGVtZW50LmVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChldmVudE5hbWUgPT0gJ2FjY2Vzc0FsbG93ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uYWNjZXNzSXNBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uYWRkRXZlbnRMaXN0ZW5lcignYWNjZXNzLWFsbG93ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnYWNjZXNzQWxsb3dlZCcpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChldmVudE5hbWUgPT0gJ2FjY2Vzc0RlbmllZCcpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5hY2Nlc3NJc0RlbmllZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NEZW5pZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uYWRkRXZlbnRMaXN0ZW5lcignYWNjZXNzLWRlbmllZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NEZW5pZWQnKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn0iLCJpbXBvcnQgeyBTZXNzaW9uSW50ZXJuYWwsIFNlc3Npb25PcHRpb25zLCBTaWduYWxPcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TZXNzaW9uSW50ZXJuYWwnO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TdHJlYW0nO1xuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvT3BlblZpZHVFcnJvcic7XG5cbmltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdSc7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuL1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTdWJzY3JpYmVyIH0gZnJvbSAnLi9TdWJzY3JpYmVyJztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5pbXBvcnQgKiBhcyBEZXRlY3RSVEMgZnJvbSAnLi4vS3VyZW50b1V0aWxzL0RldGVjdFJUQyc7XG5cbmV4cG9ydCBjbGFzcyBTZXNzaW9uIHtcblxuICAgIHNlc3Npb25JZDogU3RyaW5nO1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICBwcml2YXRlIGVlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBzZXNzaW9uOiBTZXNzaW9uSW50ZXJuYWwsIHByaXZhdGUgb3BlblZpZHU6IE9wZW5WaWR1KSB7XG4gICAgICAgIHRoaXMuc2Vzc2lvbklkID0gc2Vzc2lvbi5nZXRTZXNzaW9uSWQoKTtcblxuICAgICAgICAvLyBMaXN0ZW5zIHRvIHRoZSBkZWFjdGl2YXRpb24gb2YgdGhlIGRlZmF1bHQgYmVoYXZpb3VyIHVwb24gdGhlIGRlbGV0aW9uIG9mIGEgU3RyZWFtIG9iamVjdFxuICAgICAgICB0aGlzLnNlc3Npb24uYWRkRXZlbnRMaXN0ZW5lcignc3RyZWFtLWRlc3Ryb3llZC1kZWZhdWx0JywgZXZlbnQgPT4ge1xuICAgICAgICAgICAgZXZlbnQuc3RyZWFtLnJlbW92ZVZpZGVvKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIExpc3RlbnMgdG8gdGhlIGRlYWN0aXZhdGlvbiBvZiB0aGUgZGVmYXVsdCBiZWhhdmlvdXIgdXBvbiB0aGUgZGlzY29ubmVjdGlvbiBvZiBhIFNlc3Npb25cbiAgICAgICAgdGhpcy5zZXNzaW9uLmFkZEV2ZW50TGlzdGVuZXIoJ3Nlc3Npb24tZGlzY29ubmVjdGVkLWRlZmF1bHQnLCAoKSA9PiB7XG4gICAgICAgICAgICBsZXQgczogU3RyZWFtO1xuICAgICAgICAgICAgZm9yIChsZXQgc3RyZWFtSWQgaW4gdGhpcy5zZXNzaW9uLmdldFJlbW90ZVN0cmVhbXMoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5nZXRSZW1vdGVTdHJlYW1zKClbc3RyZWFtSWRdLnJlbW92ZVZpZGVvKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uICYmIChPYmplY3Qua2V5cyh0aGlzLmNvbm5lY3Rpb24uZ2V0U3RyZWFtcygpKS5sZW5ndGggPiAwKSkge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHN0cmVhbUlkIGluIHRoaXMuY29ubmVjdGlvbi5nZXRTdHJlYW1zKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmdldFN0cmVhbXMoKVtzdHJlYW1JZF0ucmVtb3ZlVmlkZW8oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFNldHMgb3IgdXBkYXRlcyB0aGUgdmFsdWUgb2YgJ2Nvbm5lY3Rpb24nIHByb3BlcnR5LiBUcmlnZ2VyZWQgYnkgU2Vzc2lvbkludGVybmFsIHdoZW4gc3VjY2VzZnVsIGNvbm5lY3Rpb25cbiAgICAgICAgdGhpcy5zZXNzaW9uLmFkZEV2ZW50TGlzdGVuZXIoJ3VwZGF0ZS1jb25uZWN0aW9uLW9iamVjdCcsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IGV2ZW50LmNvbm5lY3Rpb247XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGNvbm5lY3QodG9rZW46IHN0cmluZywgY2FsbGJhY2s6IGFueSk7XG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YTogYW55LCBjYWxsYmFjazogYW55KTtcblxuICAgIGNvbm5lY3QocGFyYW0xLCBwYXJhbTIsIHBhcmFtMz8pIHtcbiAgICAgICAgLy8gRWFybHkgY29uZmlndXJhdGlvbiB0byBkZWFjdGl2YXRlIGF1dG9tYXRpYyBzdWJzY3JpcHRpb24gdG8gc3RyZWFtc1xuICAgICAgICBpZiAocGFyYW0zKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5vcGVuVmlkdS5jaGVja1N5c3RlbVJlcXVpcmVtZW50cygpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmNvbmZpZ3VyZSh7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb25JZDogdGhpcy5zZXNzaW9uLmdldFNlc3Npb25JZCgpLFxuICAgICAgICAgICAgICAgICAgICBwYXJ0aWNpcGFudElkOiBwYXJhbTEsXG4gICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiB0aGlzLnNlc3Npb24uc3RyaW5nQ2xpZW50TWV0YWRhdGEocGFyYW0yKSxcbiAgICAgICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9TdHJlYW1zOiBmYWxzZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5jb25uZWN0KHBhcmFtMSwgcGFyYW0zKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcGFyYW0zKG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkJST1dTRVJfTk9UX1NVUFBPUlRFRCwgJ0Jyb3dzZXIgJyArIERldGVjdFJUQy5icm93c2VyLm5hbWUgKyAnICcgKyBEZXRlY3RSVEMuYnJvd3Nlci52ZXJzaW9uICsgJyBpcyBub3Qgc3VwcG9ydGVkIGluIE9wZW5WaWR1JykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHRoaXMub3BlblZpZHUuY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5jb25maWd1cmUoe1xuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uSWQ6IHRoaXMuc2Vzc2lvbi5nZXRTZXNzaW9uSWQoKSxcbiAgICAgICAgICAgICAgICAgICAgcGFydGljaXBhbnRJZDogcGFyYW0xLFxuICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogJycsXG4gICAgICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvU3RyZWFtczogZmFsc2VcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uY29ubmVjdChwYXJhbTEsIHBhcmFtMik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBhcmFtMihuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5CUk9XU0VSX05PVF9TVVBQT1JURUQsICdCcm93c2VyICcgKyBEZXRlY3RSVEMuYnJvd3Nlci5uYW1lICsgJyAnICsgRGV0ZWN0UlRDLmJyb3dzZXIudmVyc2lvbiArICcgaXMgbm90IHN1cHBvcnRlZCBpbiBPcGVuVmlkdScpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGRpc2Nvbm5lY3QoKSB7XG4gICAgICAgIHRoaXMub3BlblZpZHUub3BlblZpZHUuY2xvc2UoZmFsc2UpO1xuICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzZXNzaW9uRGlzY29ubmVjdGVkJywgW3tcbiAgICAgICAgICAgIHByZXZlbnREZWZhdWx0OiAoKSA9PiB7IHRoaXMuc2Vzc2lvbi5yZW1vdmVFdmVudCgnc2Vzc2lvbi1kaXNjb25uZWN0ZWQtZGVmYXVsdCcpOyB9XG4gICAgICAgIH1dKTtcbiAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc2Vzc2lvbi1kaXNjb25uZWN0ZWQtZGVmYXVsdCcsIFt7fV0pO1xuICAgIH1cblxuICAgIHB1Ymxpc2gocHVibGlzaGVyOiBQdWJsaXNoZXIpIHtcbiAgICAgICAgaWYgKCFwdWJsaXNoZXIuc3RyZWFtLmlzUHVibGlzaGVyUHVibGlzaGVkKSB7IC8vICdTZXNzaW9uLnVucHVibGlzaChQdWJsaXNoZXIpJyBoYXMgTk9UIGJlZW4gY2FsbGVkXG4gICAgICAgICAgICBpZiAocHVibGlzaGVyLmlzU2NyZWVuUmVxdWVzdGVkKSB7IC8vIFNjcmVlbiBzaGFyaW5nIFB1Ymxpc2hlclxuICAgICAgICAgICAgICAgIGlmICghcHVibGlzaGVyLnN0cmVhbS5pc1NjcmVlblJlcXVlc3RlZFJlYWR5KSB7IC8vIFNjcmVlbiB2aWRlbyBzdHJlYW0gaXMgbm90IGF2YWlsYWJsZSB5ZXRcbiAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5hZGRPbmNlRXZlbnRMaXN0ZW5lcignc2NyZWVuLXJlYWR5JywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1QdWJsaXNoKHB1Ymxpc2hlcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7IC8vIC8vIFNjcmVlbiB2aWRlbyBzdHJlYW0gaXMgYWxyZWFkeSBhdmFpbGFibGVcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1QdWJsaXNoKHB1Ymxpc2hlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHsgLy8gQXVkaW8tVmlkZW8gUHVibGlzaGVyXG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1QdWJsaXNoKHB1Ymxpc2hlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7IC8vICdTZXNzaW9uLnVucHVibGlzaChQdWJsaXNoZXIpJyBoYXMgYmVlbiBjYWxsZWRcbiAgICAgICAgICAgIHB1Ymxpc2hlciA9IHRoaXMub3BlblZpZHUucmVpbml0UHVibGlzaGVyKHB1Ymxpc2hlcik7XG5cbiAgICAgICAgICAgIGlmIChwdWJsaXNoZXIuaXNTY3JlZW5SZXF1ZXN0ZWQgJiYgIXB1Ymxpc2hlci5zdHJlYW0uaXNTY3JlZW5SZXF1ZXN0ZWRSZWFkeSkgeyAvLyBTY3JlZW4gc2hhcmluZyBQdWJsaXNoZXIgYW5kIHZpZGVvIHN0cmVhbSBub3QgYXZhaWxhYmxlIHlldFxuICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0uYWRkT25jZUV2ZW50TGlzdGVuZXIoJ3NjcmVlbi1yZWFkeScsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1QdWJsaXNoKHB1Ymxpc2hlcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2UgeyAvLyBWaWRlbyBzdHJlYW0gYWxyZWFkeSBhdmFpbGFibGVcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbVB1Ymxpc2gocHVibGlzaGVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc3RyZWFtUHVibGlzaChwdWJsaXNoZXI6IFB1Ymxpc2hlcikge1xuICAgICAgICBwdWJsaXNoZXIuc2Vzc2lvbiA9IHRoaXM7XG4gICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgIHB1Ymxpc2hlci5zdHJlYW0ucHVibGlzaCgpO1xuICAgIH1cblxuICAgIHVucHVibGlzaChwdWJsaXNoZXI6IFB1Ymxpc2hlcikge1xuICAgICAgICB0aGlzLnNlc3Npb24udW5wdWJsaXNoKHB1Ymxpc2hlcik7XG4gICAgfVxuXG4gICAgb24oZXZlbnROYW1lOiBzdHJpbmcsIGNhbGxiYWNrKSB7XG4gICAgICAgIHRoaXMuc2Vzc2lvbi5hZGRFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgZXZlbnROYW1lICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyBldmVudE5hbWUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdTZXNzaW9uJ1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhbGxiYWNrKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgb25jZShldmVudE5hbWU6IHN0cmluZywgY2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5zZXNzaW9uLmFkZE9uY2VFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgY2FsbGJhY2soZXZlbnQpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBvZmYoZXZlbnROYW1lOiBzdHJpbmcsIGV2ZW50SGFuZGxlcikge1xuICAgICAgICB0aGlzLnNlc3Npb24ucmVtb3ZlTGlzdGVuZXIoZXZlbnROYW1lLCBldmVudEhhbmRsZXIpO1xuICAgIH1cblxuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgaHRtbElkOiBzdHJpbmcsIHZpZGVvT3B0aW9uczogYW55KTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIGh0bWxJZDogc3RyaW5nKTogU3Vic2NyaWJlcjtcblxuICAgIHN1YnNjcmliZShwYXJhbTEsIHBhcmFtMiwgcGFyYW0zPyk6IFN1YnNjcmliZXIge1xuICAgICAgICAvLyBTdWJzY3JpcHRpb25cbiAgICAgICAgdGhpcy5zZXNzaW9uLnN1YnNjcmliZShwYXJhbTEpO1xuICAgICAgICBsZXQgc3Vic2NyaWJlciA9IG5ldyBTdWJzY3JpYmVyKHBhcmFtMSwgcGFyYW0yKTtcbiAgICAgICAgcGFyYW0xLnBsYXlPbmx5VmlkZW8ocGFyYW0yLCBudWxsKTtcbiAgICAgICAgcmV0dXJuIHN1YnNjcmliZXI7XG4gICAgfVxuXG4gICAgdW5zdWJzY3JpYmUoc3Vic2NyaWJlcjogU3Vic2NyaWJlcikge1xuICAgICAgICB0aGlzLnNlc3Npb24udW5zdWJzY3JpYmUoc3Vic2NyaWJlci5zdHJlYW0pO1xuICAgICAgICBzdWJzY3JpYmVyLnN0cmVhbS5yZW1vdmVWaWRlbygpO1xuICAgIH1cblxuICAgIHNpZ25hbChzaWduYWw6IFNpZ25hbE9wdGlvbnMsIGNvbXBsZXRpb25IYW5kbGVyPzogRnVuY3Rpb24pIHtcbiAgICAgICAgdmFyIHNpZ25hbE1lc3NhZ2UgPSB7fTtcblxuICAgICAgICBpZiAoc2lnbmFsLnRvICYmIHNpZ25hbC50by5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBsZXQgY29ubmVjdGlvbklkczogc3RyaW5nW10gPSBbXTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2lnbmFsLnRvLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbklkcy5wdXNoKHNpZ25hbC50b1tpXS5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2lnbmFsTWVzc2FnZVsndG8nXSA9IGNvbm5lY3Rpb25JZHM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0byddID0gW107XG4gICAgICAgIH1cblxuICAgICAgICBzaWduYWxNZXNzYWdlWydkYXRhJ10gPSBzaWduYWwuZGF0YSA/IHNpZ25hbC5kYXRhIDogJyc7XG4gICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3R5cGUnXSA9IHNpZ25hbC50eXBlID8gc2lnbmFsLnR5cGUgOiAnJztcblxuICAgICAgICB0aGlzLm9wZW5WaWR1Lm9wZW5WaWR1LnNlbmRNZXNzYWdlKEpTT04uc3RyaW5naWZ5KHNpZ25hbE1lc3NhZ2UpKTtcbiAgICB9XG5cbn1cbiIsImltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvU3RyZWFtJztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cbmV4cG9ydCBjbGFzcyBTdWJzY3JpYmVyIHtcblxuICAgIHByaXZhdGUgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgICBlbGVtZW50OiBFbGVtZW50O1xuICAgIGlkOiBzdHJpbmc7XG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICBjb25zdHJ1Y3RvcihzdHJlYW06IFN0cmVhbSwgcGFyZW50SWQ6IHN0cmluZykge1xuICAgICAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTtcbiAgICAgICAgaWYgKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHBhcmVudElkKSAhPSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLmVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChwYXJlbnRJZCkhITtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIExpc3RlbnMgdG8gZGVsZXRpb24gb2YgdGhlIEhUTUwgdmlkZW8gZWxlbWVudCBvZiB0aGUgU3Vic2NyaWJlclxuICAgICAgICB0aGlzLnN0cmVhbS5hZGRFdmVudExpc3RlbmVyKCd2aWRlby1yZW1vdmVkJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudERlc3Ryb3llZCcpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBvbihldmVudE5hbWU6IHN0cmluZywgY2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5lZS5hZGRMaXN0ZW5lcihldmVudE5hbWUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIGV2ZW50TmFtZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1N1YnNjcmliZXInXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgZXZlbnROYW1lICsgXCInIHRyaWdnZXJlZCBieSAnU3Vic2NyaWJlcidcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYWxsYmFjayhldmVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoZXZlbnROYW1lID09ICd2aWRlb0VsZW1lbnRDcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzVmlkZW9FTGVtZW50Q3JlYXRlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW3tcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudDogdGhpcy5zdHJlYW0uZ2V0VmlkZW9FbGVtZW50KClcbiAgICAgICAgICAgICAgICB9XSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmFkZE9uY2VFdmVudExpc3RlbmVyKCd2aWRlby1lbGVtZW50LWNyZWF0ZWQtYnktc3RyZWFtJywgZWxlbWVudCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaWQgPSBlbGVtZW50LmlkO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFt7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50OiBlbGVtZW50XG4gICAgICAgICAgICAgICAgICAgIH1dKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoZXZlbnROYW1lID09ICd2aWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICB2YXIgdmlkZW8gPSB0aGlzLnN0cmVhbS5nZXRWaWRlb0VsZW1lbnQoKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgJiYgdmlkZW8gJiZcbiAgICAgICAgICAgICAgICB2aWRlby5jdXJyZW50VGltZSA+IDAgJiYgXG4gICAgICAgICAgICAgICAgdmlkZW8ucGF1c2VkID09IGZhbHNlICYmIFxuICAgICAgICAgICAgICAgIHZpZGVvLmVuZGVkID09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdmlkZW8ucmVhZHlTdGF0ZSA9PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudDogdGhpcy5zdHJlYW0uZ2V0VmlkZW9FbGVtZW50KClcbiAgICAgICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5hZGRPbmNlRXZlbnRMaXN0ZW5lcigndmlkZW8taXMtcGxheWluZycsIChlbGVtZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudDogZWxlbWVudC5lbGVtZW50XG4gICAgICAgICAgICAgICAgICAgIH1dKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn0iLCJpbXBvcnQgeyBTdHJlYW0sIFN0cmVhbU9wdGlvbnNTZXJ2ZXIsIEluYm91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgT3BlblZpZHVJbnRlcm5hbCB9IGZyb20gJy4vT3BlblZpZHVJbnRlcm5hbCc7XG5pbXBvcnQgeyBTZXNzaW9uSW50ZXJuYWwgfSBmcm9tICcuL1Nlc3Npb25JbnRlcm5hbCc7XG5cbnR5cGUgT2JqTWFwPFQ+ID0geyBbczogc3RyaW5nXTogVDsgfVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbm5lY3Rpb25PcHRpb25zIHtcbiAgICBpZDogc3RyaW5nO1xuICAgIG1ldGFkYXRhOiBzdHJpbmc7XG4gICAgc3RyZWFtczogU3RyZWFtT3B0aW9uc1NlcnZlcltdO1xufVxuXG5leHBvcnQgY2xhc3MgQ29ubmVjdGlvbiB7XG5cbiAgICBwdWJsaWMgY29ubmVjdGlvbklkOiBzdHJpbmc7XG4gICAgcHVibGljIGRhdGE6IHN0cmluZztcbiAgICBwdWJsaWMgY3JlYXRpb25UaW1lOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBzdHJlYW1zOiBPYmpNYXA8U3RyZWFtPiA9IHt9O1xuICAgIHByaXZhdGUgaW5ib3VuZFN0cmVhbXNPcHRzOiBJbmJvdW5kU3RyZWFtT3B0aW9ucztcblxuICAgIGNvbnN0cnVjdG9yKCBwcml2YXRlIG9wZW5WaWR1OiBPcGVuVmlkdUludGVybmFsLCBwcml2YXRlIGxvY2FsOiBib29sZWFuLCBwcml2YXRlIHJvb206IFNlc3Npb25JbnRlcm5hbCwgcHJpdmF0ZSBvcHRpb25zPzogQ29ubmVjdGlvbk9wdGlvbnMgKSB7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCBcIidDb25uZWN0aW9uJyBjcmVhdGVkIChcIiArICggbG9jYWwgPyBcImxvY2FsXCIgOiBcInJlbW90ZVwiICkgKyBcIilcIiArICggbG9jYWwgPyBcIlwiIDogXCIsIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgKG9wdGlvbnMgPyBvcHRpb25zLmlkIDogJycpICsgXCJdIFwiICkpO1xuXG4gICAgICAgIGlmICggb3B0aW9ucyAmJiAhbG9jYWwgKSB7XG5cbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbklkID0gb3B0aW9ucy5pZDtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLm1ldGFkYXRhKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRhID0gb3B0aW9ucy5tZXRhZGF0YTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvcHRpb25zLnN0cmVhbXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRSZW1vdGVTdHJlYW1zKG9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIFxuICAgIH1cblxuICAgIGFkZFN0cmVhbSggc3RyZWFtOiBTdHJlYW0gKSB7XG4gICAgICAgIHN0cmVhbS5jb25uZWN0aW9uID0gdGhpcztcbiAgICAgICAgdGhpcy5zdHJlYW1zW3N0cmVhbS5zdHJlYW1JZF0gPSBzdHJlYW07XG4gICAgICAgIC8vdGhpcy5yb29tLmdldFN0cmVhbXMoKVtzdHJlYW0uc3RyZWFtSWRdID0gc3RyZWFtO1xuICAgIH1cblxuICAgIHJlbW92ZVN0cmVhbSgga2V5OiBzdHJpbmcgKSB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLnN0cmVhbXNba2V5XTtcbiAgICAgICAgLy9kZWxldGUgdGhpcy5yb29tLmdldFN0cmVhbXMoKVtrZXldO1xuICAgICAgICBkZWxldGUgdGhpcy5pbmJvdW5kU3RyZWFtc09wdHM7XG4gICAgfVxuXG4gICAgc2V0T3B0aW9ucyhvcHRpb25zOiBDb25uZWN0aW9uT3B0aW9ucykge1xuICAgICAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuICAgIH1cblxuICAgIGdldFN0cmVhbXMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0cmVhbXM7XG4gICAgfVxuXG4gICAgZGlzcG9zZSgpIHtcbiAgICAgICAgZm9yICggbGV0IGtleSBpbiB0aGlzLnN0cmVhbXMgKSB7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbXNba2V5XS5kaXNwb3NlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzZW5kSWNlQ2FuZGlkYXRlKCBjYW5kaWRhdGUgKSB7XG5cbiAgICAgICAgY29uc29sZS5kZWJ1ZygoIHRoaXMubG9jYWwgPyBcIkxvY2FsXCIgOiBcIlJlbW90ZVwiICksIFwiY2FuZGlkYXRlIGZvclwiLFxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQsIEpTT04uc3RyaW5naWZ5KCBjYW5kaWRhdGUgKSApO1xuXG4gICAgICAgIHRoaXMub3BlblZpZHUuc2VuZFJlcXVlc3QoIFwib25JY2VDYW5kaWRhdGVcIiwge1xuICAgICAgICAgICAgZW5kcG9pbnROYW1lOiB0aGlzLmNvbm5lY3Rpb25JZCxcbiAgICAgICAgICAgIGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSxcbiAgICAgICAgICAgIHNkcE1pZDogY2FuZGlkYXRlLnNkcE1pZCxcbiAgICAgICAgICAgIHNkcE1MaW5lSW5kZXg6IGNhbmRpZGF0ZS5zZHBNTGluZUluZGV4XG4gICAgICAgIH0sIGZ1bmN0aW9uKCBlcnJvciwgcmVzcG9uc2UgKSB7XG4gICAgICAgICAgICBpZiAoIGVycm9yICkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoIFwiRXJyb3Igc2VuZGluZyBJQ0UgY2FuZGlkYXRlOiBcIlxuICAgICAgICAgICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KCBlcnJvciApICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGluaXRSZW1vdGVTdHJlYW1zKG9wdGlvbnM6IENvbm5lY3Rpb25PcHRpb25zKSB7XG4gICAgICAgIGxldCBvcHRzOiBTdHJlYW1PcHRpb25zU2VydmVyO1xuICAgICAgICBmb3IgKCBvcHRzIG9mIG9wdGlvbnMuc3RyZWFtcyApIHtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbGV0IHN0cmVhbU9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIGlkOiBvcHRzLmlkLFxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb246IHRoaXMsXG4gICAgICAgICAgICAgICAgcmVjdkF1ZGlvOiAoIG9wdHMuYXVkaW9BY3RpdmUgPT0gbnVsbCA/IHRydWUgOiBvcHRzLmF1ZGlvQWN0aXZlICksXG4gICAgICAgICAgICAgICAgcmVjdlZpZGVvOiAoIG9wdHMudmlkZW9BY3RpdmUgPT0gbnVsbCA/IHRydWUgOiBvcHRzLnZpZGVvQWN0aXZlICksXG4gICAgICAgICAgICAgICAgdHlwZU9mVmlkZW86IG9wdHMudHlwZU9mVmlkZW8sXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgc3RyZWFtID0gbmV3IFN0cmVhbSh0aGlzLm9wZW5WaWR1LCBmYWxzZSwgdGhpcy5yb29tLCBzdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgdGhpcy5hZGRTdHJlYW0oc3RyZWFtKTtcbiAgICAgICAgICAgIHRoaXMuaW5ib3VuZFN0cmVhbXNPcHRzID0gc3RyZWFtT3B0aW9ucztcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnQ29ubmVjdGlvbicgd2l0aCAnY29ubmVjdGlvbklkJyBbXCIgKyB0aGlzLmNvbm5lY3Rpb25JZCArIFwiXSBpcyBub3cgY29uZmlndXJlZCBmb3IgcmVjZWl2aW5nIFN0cmVhbXMgd2l0aCBvcHRpb25zOiBcIiwgdGhpcy5pbmJvdW5kU3RyZWFtc09wdHMgKTtcbiAgICB9XG59IiwiaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSBcIi4vU3RyZWFtXCI7XG5cbmRlY2xhcmUgdmFyIE1lZGlhUmVjb3JkZXI6IGFueTtcblxuZXhwb3J0IGNvbnN0IGVudW0gTG9jYWxSZWNvZGVyU3RhdGUge1xuICAgIFJFQURZID0gJ1JFQURZJyxcbiAgICBSRUNPUkRJTkcgPSAnUkVDT1JESU5HJyxcbiAgICBQQVVTRUQgPSAnUEFVU0VEJyxcbiAgICBGSU5JU0hFRCA9ICdGSU5JU0hFRCdcbn1cblxuZXhwb3J0IGNsYXNzIExvY2FsUmVjb3JkZXIge1xuXG4gICAgc3RhdGU6IExvY2FsUmVjb2RlclN0YXRlO1xuXG4gICAgcHJpdmF0ZSBzdHJlYW06IFN0cmVhbTtcbiAgICBwcml2YXRlIGNvbm5lY3Rpb25JZDogc3RyaW5nO1xuXG4gICAgcHJpdmF0ZSBtZWRpYVJlY29yZGVyOiBhbnk7XG4gICAgcHJpdmF0ZSBjaHVua3M6IGFueVtdID0gW107XG4gICAgcHJpdmF0ZSBibG9iOiBCbG9iO1xuICAgIHByaXZhdGUgY291bnQ6IG51bWJlciA9IDA7XG4gICAgcHJpdmF0ZSBpZDogc3RyaW5nO1xuXG4gICAgcHJpdmF0ZSB2aWRlb1ByZXZpZXdTcmM6IHN0cmluZztcbiAgICBwcml2YXRlIGh0bWxQYXJlbnRFbGVtZW50SWQ6IHN0cmluZztcbiAgICBwcml2YXRlIHZpZGVvUHJldmlldzogSFRNTFZpZGVvRWxlbWVudDtcblxuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtKSB7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLmNvbm5lY3Rpb25JZCA9ICghIXRoaXMuc3RyZWFtLmNvbm5lY3Rpb24pID8gdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgOiAnZGVmYXVsdC1jb25uZWN0aW9uJztcbiAgICAgICAgdGhpcy5pZCA9IHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ18nICsgdGhpcy5jb25uZWN0aW9uSWQgKyAnX2xvY2FscmVjb3JkJztcbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb2RlclN0YXRlLlJFQURZO1xuICAgIH1cblxuICAgIHJlY29yZCgpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBNZWRpYVJlY29yZGVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignTWVkaWFSZWNvcmRlciBub3Qgc3VwcG9ydGVkIG9uIHlvdXIgYnJvd3Nlci4gU2VlIGNvbXBhdGliaWxpdHkgaW4gaHR0cHM6Ly9jYW5pdXNlLmNvbS8jc2VhcmNoPU1lZGlhUmVjb3JkZXInKTtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignTWVkaWFSZWNvcmRlciBub3Qgc3VwcG9ydGVkIG9uIHlvdXIgYnJvd3Nlci4gU2VlIGNvbXBhdGliaWxpdHkgaW4gaHR0cHM6Ly9jYW5pdXNlLmNvbS8jc2VhcmNoPU1lZGlhUmVjb3JkZXInKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb2RlclN0YXRlLlJFQURZKSB7XG4gICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnJlY29yZCgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1JFQURZXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuY2xlYW4oKVxcJyBvciBpbml0IGEgbmV3IExvY2FsUmVjb3JkZXIgYmVmb3JlJykpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUubG9nKFwiU3RhcnRpbmcgbG9jYWwgcmVjb3JkaW5nIG9mIHN0cmVhbSAnXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArIFwiJyBvZiBjb25uZWN0aW9uICdcIiArIHRoaXMuY29ubmVjdGlvbklkICsgXCInXCIpO1xuICAgICAgICBpZiAodHlwZW9mIE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkID09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGxldCBvcHRpb25zO1xuICAgICAgICAgICAgaWYgKE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkKCd2aWRlby93ZWJtO2NvZGVjcz12cDknKSkge1xuICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7IG1pbWVUeXBlOiAndmlkZW8vd2VibTtjb2RlY3M9dnA5JyB9O1xuICAgICAgICAgICAgfSBlbHNlIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9aDI2NCcpKSB7XG4gICAgICAgICAgICAgICAgb3B0aW9ucyA9IHsgbWltZVR5cGU6ICd2aWRlby93ZWJtO2NvZGVjcz1oMjY0JyB9O1xuICAgICAgICAgICAgfSBlbHNlIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9dnA4JykpIHtcbiAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOCcgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdVc2luZyBtaW1lVHlwZSAnICsgb3B0aW9ucy5taW1lVHlwZSk7XG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLCBvcHRpb25zKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignaXNUeXBlU3VwcG9ydGVkIGlzIG5vdCBzdXBwb3J0ZWQsIHVzaW5nIGRlZmF1bHQgY29kZWNzIGZvciBicm93c2VyJyk7XG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5zdGFydCgxMCk7XG5cbiAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZGF0YWF2YWlsYWJsZSA9IChlKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNodW5rcy5wdXNoKGUuZGF0YSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZXJyb3IgPSAoZSkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignTWVkaWFSZWNvcmRlciBlcnJvcjogJywgZSk7XG4gICAgICAgIH07XG5cblxuICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdGFydCA9ICgpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHN0YXJ0ZWQgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyBcIilcIik7XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RvcCA9ICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMub25TdG9wRGVmYXVsdCgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnBhdXNlID0gKCkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgcGF1c2VkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgXCIpXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ucmVzdW1lID0gKCkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgcmVzdW1lZCAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArIFwiKVwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbndhcm5pbmcgPSAoZSkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgd2FybmluZzogJyArIGUpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29kZXJTdGF0ZS5SRUNPUkRJTkc7XG4gICAgfVxuXG4gICAgc3RvcCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvZGVyU3RhdGUuUkVBRFkgfHwgdGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5zdG9wKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVDT1JESU5HXFwnIG9yIFxcJ1BBVVNFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0YXJ0KClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdG9wID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm9uU3RvcERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5zdG9wKCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwYXVzZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb2RlclN0YXRlLlJFQ09SRElORykge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5wYXVzZSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1JFQ09SRElOR1xcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0YXJ0KClcXCcgb3IgXFwnTG9jYWxSZWNvcmRlci5yZXN1bWUoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnBhdXNlKCk7XG4gICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29kZXJTdGF0ZS5QQVVTRUQ7XG4gICAgfVxuXG4gICAgcmVzdW1lKCkge1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnJlc3VtZSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1BBVVNFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnBhdXNlKClcXCcgYmVmb3JlJykpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5yZXN1bWUoKTtcbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb2RlclN0YXRlLlJFQ09SRElORztcbiAgICB9XG5cbiAgICBwcmV2aWV3KHBhcmVudEVsZW1lbnQpOiBIVE1MVmlkZW9FbGVtZW50IHtcblxuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucHJldmlldygpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlldy5pZCA9IHRoaXMuaWQ7XG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LmF1dG9wbGF5ID0gdHJ1ZTtcblxuICAgICAgICBpZiAodHlwZW9mIHBhcmVudEVsZW1lbnQgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIHRoaXMuaHRtbFBhcmVudEVsZW1lbnRJZCA9IHBhcmVudEVsZW1lbnQ7XG5cbiAgICAgICAgICAgIGxldCBwYXJlbnRFbGVtZW50RG9tID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocGFyZW50RWxlbWVudCk7XG4gICAgICAgICAgICBpZiAocGFyZW50RWxlbWVudERvbSkge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gcGFyZW50RWxlbWVudERvbS5hcHBlbmRDaGlsZCh0aGlzLnZpZGVvUHJldmlldyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmh0bWxQYXJlbnRFbGVtZW50SWQgPSBwYXJlbnRFbGVtZW50LmlkO1xuICAgICAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMudmlkZW9QcmV2aWV3KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LnNyYyA9IHRoaXMudmlkZW9QcmV2aWV3U3JjO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnZpZGVvUHJldmlldztcbiAgICB9XG5cbiAgICBjbGVhbigpIHtcbiAgICAgICAgbGV0IGYgPSAoKSA9PiB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5ibG9iO1xuICAgICAgICAgICAgdGhpcy5jaHVua3MgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuY291bnQgPSAwO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMubWVkaWFSZWNvcmRlcjtcbiAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29kZXJTdGF0ZS5SRUFEWTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvZGVyU3RhdGUuUkVDT1JESU5HIHx8IHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb2RlclN0YXRlLlBBVVNFRCkge1xuICAgICAgICAgICAgdGhpcy5zdG9wKCkudGhlbigoKSA9PiBmKCkpLmNhdGNoKCgpID0+IGYoKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBkb3dubG9hZCgpIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb2RlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLmRvd25sb2FkKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbGV0IGE6IEhUTUxBbmNob3JFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImFcIik7XG4gICAgICAgICAgICBhLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGEpO1xuXG4gICAgICAgICAgICBsZXQgdXJsID0gd2luZG93LlVSTC5jcmVhdGVPYmplY3RVUkwodGhpcy5ibG9iKTtcbiAgICAgICAgICAgIGEuaHJlZiA9IHVybDtcbiAgICAgICAgICAgIGEuZG93bmxvYWQgPSB0aGlzLmlkICsgJy53ZWJtJztcbiAgICAgICAgICAgIGEuY2xpY2soKTtcbiAgICAgICAgICAgIHdpbmRvdy5VUkwucmV2b2tlT2JqZWN0VVJMKHVybCk7XG5cbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoYSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBnZXRCbG9iKCk6IEJsb2Ige1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignQ2FsbCBcXCdMb2NhbFJlY29yZC5zdG9wKClcXCcgYmVmb3JlIGdldHRpbmcgQmxvYiBmaWxlJykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYmxvYjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHVwbG9hZEFzQmluYXJ5KGVuZHBvaW50OiBzdHJpbmcsIGhlYWRlcnM/OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb2RlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKCdcXCdMb2NhbFJlY29yZC51cGxvYWRBc0JpbmFyeSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbGV0IGh0dHAgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgICAgICBodHRwLm9wZW4oXCJQT1NUXCIsIGVuZHBvaW50LCB0cnVlKTtcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGhlYWRlcnMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhoZWFkZXJzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaHR0cC5zZXRSZXF1ZXN0SGVhZGVyKGtleSwgaGVhZGVyc1trZXldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGh0dHAub25yZWFkeXN0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5zdGF0dXMudG9TdHJpbmcoKS5jaGFyQXQoMCkgPT09ICcyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN1Y2Nlc3MgcmVzcG9uc2UgZnJvbSBzZXJ2ZXIgKEhUVFAgc3RhdHVzIHN0YW5kYXJkOiAyWFggaXMgc3VjY2VzcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGh0dHAucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKFwiVXBsb2FkIGVycm9yOiBcIiArIGh0dHAuc3RhdHVzKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaHR0cC5zZW5kKHRoaXMuYmxvYik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHVwbG9hZEFzTXVsdGlwYXJ0ZmlsZShlbmRwb2ludDogc3RyaW5nLCBoZWFkZXJzPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29kZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQudXBsb2FkQXNNdWx0aXBhcnRmaWxlKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBsZXQgaHR0cCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgIGh0dHAub3BlbihcIlBPU1RcIiwgZW5kcG9pbnQsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBoZWFkZXJzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMoaGVhZGVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcihrZXksIGhlYWRlcnNba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBsZXQgc2VuZGFibGUgPSBuZXcgRm9ybURhdGEoKTtcbiAgICAgICAgICAgICAgICBzZW5kYWJsZS5hcHBlbmQoXCJmaWxlXCIsIHRoaXMuYmxvYiwgdGhpcy5pZCArIFwiLndlYm1cIik7XG5cbiAgICAgICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAuc3RhdHVzLnRvU3RyaW5nKCkuY2hhckF0KDApID09PSAnMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzIHJlc3BvbnNlIGZyb20gc2VydmVyIChIVFRQIHN0YXR1cyBzdGFuZGFyZDogMlhYIGlzIHN1Y2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcihcIlVwbG9hZCBlcnJvcjogXCIgKyBodHRwLnN0YXR1cykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaHR0cC5zZW5kKHNlbmRhYmxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvblN0b3BEZWZhdWx0KCkge1xuICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciBzdG9wcGVkICAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArIFwiKVwiKTtcblxuICAgICAgICB0aGlzLmJsb2IgPSBuZXcgQmxvYih0aGlzLmNodW5rcywgeyB0eXBlOiBcInZpZGVvL3dlYm1cIiB9KTtcbiAgICAgICAgdGhpcy5jaHVua3MgPSBbXTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlld1NyYyA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG5cbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb2RlclN0YXRlLkZJTklTSEVEO1xuICAgIH1cblxufVxuIiwiZXhwb3J0IGNvbnN0IGVudW0gT3BlblZpZHVFcnJvck5hbWUge1xuICAgIEJST1dTRVJfTk9UX1NVUFBPUlRFRCA9ICdCUk9XU0VSX05PVF9TVVBQT1JURUQnLFxuICAgIENBTUVSQV9BQ0NFU1NfREVOSUVEID0gJ0NBTUVSQV9BQ0NFU1NfREVOSUVEJyxcbiAgICBNSUNST1BIT05FX0FDQ0VTU19ERU5JRUQgPSAnTUlDUk9QSE9ORV9BQ0NFU1NfREVOSUVEJyxcbiAgICBTQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgPSAnU0NSRUVOX0NBUFRVUkVfREVOSUVEJyxcbiAgICBOT19WSURFT19ERVZJQ0UgPSAnTk9fVklERU9fREVWSUNFJyxcbiAgICBOT19JTlBVVF9ERVZJQ0UgPSAnTk9fSU5QVVRfREVWSUNFJyxcbiAgICBTQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVEID0gJ1NDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQnLFxuICAgIFNDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCA9ICdTQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQnLFxuICAgIEdFTkVSSUNfRVJST1IgPSAnR0VORVJJQ19FUlJPUidcbn1cblxuZXhwb3J0IGNsYXNzIE9wZW5WaWR1RXJyb3Ige1xuXG4gICAgbmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG4gICAgbWVzc2FnZTogc3RyaW5nO1xuXG4gICAgY29uc3RydWN0b3IobmFtZTogT3BlblZpZHVFcnJvck5hbWUsIG1lc3NhZ2U6IHN0cmluZykge1xuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTcgT3BlblZpZHUgKGh0dHA6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cbmltcG9ydCB7IFNlc3Npb25JbnRlcm5hbCwgU2Vzc2lvbk9wdGlvbnMgfSBmcm9tICcuL1Nlc3Npb25JbnRlcm5hbCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi9Db25uZWN0aW9uJztcbmltcG9ydCB7IE9wZW5WaWR1RXJyb3IsIE9wZW5WaWR1RXJyb3JOYW1lIH0gZnJvbSAnLi9PcGVuVmlkdUVycm9yJztcbmltcG9ydCB7IFN0cmVhbSwgT3V0Ym91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0ICogYXMgUnBjQnVpbGRlciBmcm9tICcuLi9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjJztcblxuZXhwb3J0IHR5cGUgQ2FsbGJhY2s8VD4gPSAoZXJyb3I/OiBhbnksIG9wZW5WaWR1PzogVCkgPT4gdm9pZDtcblxuZXhwb3J0IGNsYXNzIE9wZW5WaWR1SW50ZXJuYWwge1xuXG4gICAgcHJpdmF0ZSB3c1VyaTtcbiAgICBwcml2YXRlIHNlc3Npb246IFNlc3Npb25JbnRlcm5hbDtcbiAgICBwcml2YXRlIGpzb25ScGNDbGllbnQ6IGFueTtcbiAgICBwcml2YXRlIHJwY1BhcmFtczogYW55O1xuICAgIHByaXZhdGUgY2FsbGJhY2s6IENhbGxiYWNrPE9wZW5WaWR1SW50ZXJuYWw+O1xuICAgIHByaXZhdGUgbG9jYWxTdHJlYW06IFN0cmVhbTtcbiAgICBwcml2YXRlIHNlY3JldDogc3RyaW5nO1xuICAgIHByaXZhdGUgcmVjb3JkZXI6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIC8qIE5FVyBNRVRIT0RTICovXG4gICAgaW5pdFNlc3Npb24oc2Vzc2lvbklkKSB7XG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIidTZXNzaW9uJyBpbml0aWFsaXplZCB3aXRoICdzZXNzaW9uSWQnIFtcIiArIHNlc3Npb25JZCArIFwiXVwiKTtcbiAgICAgICAgdGhpcy5zZXNzaW9uID0gbmV3IFNlc3Npb25JbnRlcm5hbCh0aGlzLCBzZXNzaW9uSWQpO1xuICAgICAgICByZXR1cm4gdGhpcy5zZXNzaW9uO1xuICAgIH1cblxuICAgIGluaXRQdWJsaXNoZXJUYWdnZWQocGFyZW50SWQ6IHN0cmluZywgY2FtZXJhT3B0aW9uczogT3V0Ym91bmRTdHJlYW1PcHRpb25zLCBuZXdTdHJlYW06IGJvb2xlYW4sIGNhbGxiYWNrPzogRnVuY3Rpb24pOiBTdHJlYW0ge1xuXG4gICAgICAgIGlmIChuZXdTdHJlYW0pIHtcbiAgICAgICAgICAgIGlmIChjYW1lcmFPcHRpb25zID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBjYW1lcmFPcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICBzZW5kQXVkaW86IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIHNlbmRWaWRlbzogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgYWN0aXZlQXVkaW86IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIGFjdGl2ZVZpZGVvOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBkYXRhQ2hhbm5lbDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czoge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXVkaW86IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICB2aWRlbzogeyB3aWR0aDogeyBpZGVhbDogMTI4MCB9IH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMubG9jYWxTdHJlYW0gPSBuZXcgU3RyZWFtKHRoaXMsIHRydWUsIHRoaXMuc2Vzc2lvbiwgY2FtZXJhT3B0aW9ucyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmxvY2FsU3RyZWFtLnJlcXVlc3RDYW1lcmFBY2Nlc3MoKGVycm9yLCBsb2NhbFN0cmVhbSkgPT4ge1xuICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgLy8gTmVpdGhlciBsb2NhbFN0cmVhbSBvciBtaWNyb3Bob25lIGRldmljZSBpcyBhbGxvd2VkL2FibGUgdG8gY2FwdHVyZSBtZWRpYVxuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayhlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubG9jYWxTdHJlYW0uZWUuZW1pdEV2ZW50KCdhY2Nlc3MtZGVuaWVkLWJ5LXB1Ymxpc2hlcicpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsU3RyZWFtLnNldFZpZGVvRWxlbWVudCh0aGlzLmNhbWVyYVJlYWR5KGxvY2FsU3RyZWFtISwgcGFyZW50SWQpKTtcbiAgICAgICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2sodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpcy5sb2NhbFN0cmVhbTtcbiAgICB9XG5cbiAgICBpbml0UHVibGlzaGVyU2NyZWVuKHBhcmVudElkOiBzdHJpbmcsIG5ld1N0cmVhbTogYm9vbGVhbiwgY2FsbGJhY2s/KTogU3RyZWFtIHtcblxuICAgICAgICBpZiAobmV3U3RyZWFtKSB7XG4gICAgICAgICAgICB0aGlzLmxvY2FsU3RyZWFtID0gbmV3IFN0cmVhbSh0aGlzLCB0cnVlLCB0aGlzLnNlc3Npb24sICdzY3JlZW4tb3B0aW9ucycpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5sb2NhbFN0cmVhbS5hZGRPbmNlRXZlbnRMaXN0ZW5lcignY2FuLXJlcXVlc3Qtc2NyZWVuJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5sb2NhbFN0cmVhbS5yZXF1ZXN0Q2FtZXJhQWNjZXNzKChlcnJvciwgbG9jYWxTdHJlYW0pID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2NhbFN0cmVhbS5lZS5lbWl0RXZlbnQoJ2FjY2Vzcy1kZW5pZWQtYnktcHVibGlzaGVyJyk7XG4gICAgICAgICAgICAgICAgICAgIGxldCBlcnJvck5hbWU6IE9wZW5WaWR1RXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVEO1xuICAgICAgICAgICAgICAgICAgICBsZXQgZXJyb3JNZXNzYWdlID0gJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCc7XG4gICAgICAgICAgICAgICAgICAgIGxldCBlID0gbmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvY2FsU3RyZWFtLnNldFZpZGVvRWxlbWVudCh0aGlzLmNhbWVyYVJlYWR5KGxvY2FsU3RyZWFtISwgcGFyZW50SWQpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMubG9jYWxTdHJlYW0uZ2V0U2VuZEF1ZGlvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSB1c2VyIHdhbnRzIHRvIHNlbmQgYXVkaW8gd2l0aCB0aGUgc2NyZWVuIGNhcHR1cmluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoeyBhdWRpbzogdHJ1ZSwgdmlkZW86IGZhbHNlIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4odXNlclN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9jYWxTdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5hZGRUcmFjayh1c2VyU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE11dGUgYXVkaW8gaWYgJ2FjdGl2ZUF1ZGlvJyBwcm9wZXJ0eSBpcyBmYWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodXNlclN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZXJTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXS5lbmFibGVkID0gdGhpcy5sb2NhbFN0cmVhbS5vdXRib3VuZE9wdGlvbnMuYWN0aXZlQXVkaW87XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvY2FsU3RyZWFtLmlzU2NyZWVuUmVxdWVzdGVkUmVhZHkgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvY2FsU3RyZWFtLmVlLmVtaXRFdmVudCgnc2NyZWVuLXJlYWR5Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2sodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2NhbFN0cmVhbS5lZS5lbWl0RXZlbnQoJ2FjY2Vzcy1kZW5pZWQtYnktcHVibGlzaGVyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBhY2Nlc3NpbmcgdGhlIG1pY3JvcGhvbmVcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlcnJvck5hbWU6IE9wZW5WaWR1RXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuTUlDUk9QSE9ORV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvY2FsU3RyZWFtLmlzU2NyZWVuUmVxdWVzdGVkUmVhZHkgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2NhbFN0cmVhbS5lZS5lbWl0RXZlbnQoJ3NjcmVlbi1yZWFkeScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2sodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxTdHJlYW07XG4gICAgfVxuXG4gICAgY2FtZXJhUmVhZHkobG9jYWxTdHJlYW06IFN0cmVhbSwgcGFyZW50SWQ6IHN0cmluZykge1xuICAgICAgICB0aGlzLmxvY2FsU3RyZWFtID0gbG9jYWxTdHJlYW07XG4gICAgICAgIGxldCB2aWRlb0VsZW1lbnQgPSB0aGlzLmxvY2FsU3RyZWFtLnBsYXlPbmx5VmlkZW8ocGFyZW50SWQsIG51bGwpO1xuICAgICAgICB0aGlzLmxvY2FsU3RyZWFtLmVtaXRTdHJlYW1SZWFkeUV2ZW50KCk7XG4gICAgICAgIHJldHVybiB2aWRlb0VsZW1lbnQ7XG4gICAgfVxuXG4gICAgZ2V0TG9jYWxTdHJlYW0oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxvY2FsU3RyZWFtO1xuICAgIH1cblxuICAgIC8qIE5FVyBNRVRIT0RTICovXG5cbiAgICBnZXRXc1VyaSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud3NVcmk7XG4gICAgfVxuXG4gICAgc2V0V3NVcmkod3NVcmk6IHN0cmluZykge1xuICAgICAgICB0aGlzLndzVXJpID0gd3NVcmk7XG4gICAgfVxuXG4gICAgZ2V0U2VjcmV0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zZWNyZXQ7XG4gICAgfVxuXG4gICAgc2V0U2VjcmV0KHNlY3JldDogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc2VjcmV0ID0gc2VjcmV0O1xuICAgIH1cblxuICAgIGdldFJlY29yZGVyKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yZWNvcmRlcjtcbiAgICB9XG5cbiAgICBzZXRSZWNvcmRlcihyZWNvcmRlcjogYm9vbGVhbikge1xuICAgICAgICB0aGlzLnJlY29yZGVyID0gcmVjb3JkZXI7XG4gICAgfVxuXG4gICAgZ2V0T3BlblZpZHVTZXJ2ZXJVUkwoKSB7XG4gICAgICAgIHJldHVybiAnaHR0cHM6Ly8nICsgdGhpcy53c1VyaS5zcGxpdChcIndzczovL1wiKVsxXS5zcGxpdChcIi9yb29tXCIpWzBdO1xuICAgIH1cblxuICAgIGdldFJvb20oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNlc3Npb247XG4gICAgfVxuXG4gICAgY29ubmVjdChjYWxsYmFjazogQ2FsbGJhY2s8T3BlblZpZHVJbnRlcm5hbD4pOiB2b2lkIHtcblxuICAgICAgICB0aGlzLmNhbGxiYWNrID0gY2FsbGJhY2s7XG5cbiAgICAgICAgdGhpcy5pbml0SnNvblJwY0NsaWVudCh0aGlzLndzVXJpKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRKc29uUnBjQ2xpZW50KHdzVXJpOiBzdHJpbmcpOiB2b2lkIHtcblxuICAgICAgICBsZXQgY29uZmlnID0ge1xuICAgICAgICAgICAgaGVhcnRiZWF0OiAzMDAwLFxuICAgICAgICAgICAgc2VuZENsb3NlTWVzc2FnZTogZmFsc2UsXG4gICAgICAgICAgICB3czoge1xuICAgICAgICAgICAgICAgIHVyaTogd3NVcmksXG4gICAgICAgICAgICAgICAgdXNlU29ja0pTOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBvbmNvbm5lY3RlZDogdGhpcy5jb25uZWN0Q2FsbGJhY2suYmluZCh0aGlzKSxcbiAgICAgICAgICAgICAgICBvbmRpc2Nvbm5lY3Q6IHRoaXMuZGlzY29ubmVjdENhbGxiYWNrLmJpbmQodGhpcyksXG4gICAgICAgICAgICAgICAgb25yZWNvbm5lY3Rpbmc6IHRoaXMucmVjb25uZWN0aW5nQ2FsbGJhY2suYmluZCh0aGlzKSxcbiAgICAgICAgICAgICAgICBvbnJlY29ubmVjdGVkOiB0aGlzLnJlY29ubmVjdGVkQ2FsbGJhY2suYmluZCh0aGlzKVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJwYzoge1xuICAgICAgICAgICAgICAgIHJlcXVlc3RUaW1lb3V0OiAxNTAwMCxcbiAgICAgICAgICAgICAgICAvL25vdGlmaWNhdGlvbnNcbiAgICAgICAgICAgICAgICBwYXJ0aWNpcGFudEpvaW5lZDogdGhpcy5vblBhcnRpY2lwYW50Sm9pbmVkLmJpbmQodGhpcyksXG4gICAgICAgICAgICAgICAgcGFydGljaXBhbnRQdWJsaXNoZWQ6IHRoaXMub25QYXJ0aWNpcGFudFB1Ymxpc2hlZC5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgICAgIHBhcnRpY2lwYW50VW5wdWJsaXNoZWQ6IHRoaXMub25QYXJ0aWNpcGFudFVucHVibGlzaGVkLmJpbmQodGhpcyksXG4gICAgICAgICAgICAgICAgcGFydGljaXBhbnRMZWZ0OiB0aGlzLm9uUGFydGljaXBhbnRMZWZ0LmJpbmQodGhpcyksXG4gICAgICAgICAgICAgICAgcGFydGljaXBhbnRFdmljdGVkOiB0aGlzLm9uUGFydGljaXBhbnRFdmljdGVkLmJpbmQodGhpcyksXG4gICAgICAgICAgICAgICAgc2VuZE1lc3NhZ2U6IHRoaXMub25OZXdNZXNzYWdlLmJpbmQodGhpcyksXG4gICAgICAgICAgICAgICAgaWNlQ2FuZGlkYXRlOiB0aGlzLmljZUNhbmRpZGF0ZUV2ZW50LmJpbmQodGhpcyksXG4gICAgICAgICAgICAgICAgbWVkaWFFcnJvcjogdGhpcy5vbk1lZGlhRXJyb3IuYmluZCh0aGlzKSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLmpzb25ScGNDbGllbnQgPSBuZXcgUnBjQnVpbGRlci5jbGllbnRzLkpzb25ScGNDbGllbnQoY29uZmlnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNvbm5lY3RDYWxsYmFjayhlcnJvcikge1xuICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgIHRoaXMuY2FsbGJhY2soZXJyb3IpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5jYWxsYmFjayhudWxsKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgaXNSb29tQXZhaWxhYmxlKCkge1xuICAgICAgICBpZiAodGhpcy5zZXNzaW9uICE9PSB1bmRlZmluZWQgJiYgdGhpcy5zZXNzaW9uIGluc3RhbmNlb2YgU2Vzc2lvbkludGVybmFsKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignU2Vzc2lvbiBpbnN0YW5jZSBub3QgZm91bmQnKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZGlzY29ubmVjdENhbGxiYWNrKCkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QnKTtcbiAgICAgICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vbkxvc3RDb25uZWN0aW9uKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhbGVydCgnQ29ubmVjdGlvbiBlcnJvci4gUGxlYXNlIHJlbG9hZCBwYWdlLicpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZWNvbm5lY3RpbmdDYWxsYmFjaygpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgY29ubmVjdGlvbiBsb3N0IChyZWNvbm5lY3RpbmcpJyk7XG4gICAgICAgIGlmICh0aGlzLmlzUm9vbUF2YWlsYWJsZSgpKSB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24ub25Mb3N0Q29ubmVjdGlvbigpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgcmVjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgcmVjb25uZWN0ZWQnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uUGFydGljaXBhbnRKb2luZWQocGFyYW1zKSB7XG4gICAgICAgIGlmICh0aGlzLmlzUm9vbUF2YWlsYWJsZSgpKSB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudEpvaW5lZChwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvblBhcnRpY2lwYW50UHVibGlzaGVkKHBhcmFtcykge1xuICAgICAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRQdWJsaXNoZWQocGFyYW1zKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgb25QYXJ0aWNpcGFudFVucHVibGlzaGVkKHBhcmFtcykge1xuICAgICAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRVbnB1Ymxpc2hlZChwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvblBhcnRpY2lwYW50TGVmdChwYXJhbXMpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50TGVmdChwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvblBhcnRpY2lwYW50RXZpY3RlZChwYXJhbXMpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50RXZpY3RlZChwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvbk5ld01lc3NhZ2UocGFyYW1zKSB7XG4gICAgICAgIGlmICh0aGlzLmlzUm9vbUF2YWlsYWJsZSgpKSB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24ub25OZXdNZXNzYWdlKHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGljZUNhbmRpZGF0ZUV2ZW50KHBhcmFtcykge1xuICAgICAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLnJlY3ZJY2VDYW5kaWRhdGUocGFyYW1zKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgb25Sb29tQ2xvc2VkKHBhcmFtcykge1xuICAgICAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9uUm9vbUNsb3NlZChwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvbk1lZGlhRXJyb3IocGFyYW1zKSB7XG4gICAgICAgIGlmICh0aGlzLmlzUm9vbUF2YWlsYWJsZSgpKSB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24ub25NZWRpYUVycm9yKHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIHNldFJwY1BhcmFtcyhwYXJhbXM6IGFueSkge1xuICAgICAgICB0aGlzLnJwY1BhcmFtcyA9IHBhcmFtcztcbiAgICB9XG5cbiAgICBzZW5kUmVxdWVzdChtZXRob2QsIHBhcmFtcywgY2FsbGJhY2s/KSB7XG5cbiAgICAgICAgaWYgKHBhcmFtcyAmJiBwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgICAgICAgY2FsbGJhY2sgPSBwYXJhbXM7XG4gICAgICAgICAgICBwYXJhbXMgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG5cbiAgICAgICAgaWYgKHRoaXMucnBjUGFyYW1zICYmIHRoaXMucnBjUGFyYW1zICE9PSBudWxsICYmIHRoaXMucnBjUGFyYW1zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGZvciAobGV0IGluZGV4IGluIHRoaXMucnBjUGFyYW1zKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucnBjUGFyYW1zLmhhc093blByb3BlcnR5KGluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJhbXNbaW5kZXhdID0gdGhpcy5ycGNQYXJhbXNbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdSUEMgcGFyYW0gYWRkZWQgdG8gcmVxdWVzdCB7JyArIGluZGV4ICsgJzogJyArIHRoaXMucnBjUGFyYW1zW2luZGV4XSArICd9Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyByZXF1ZXN0OiB7bWV0aG9kOlwiJyArIG1ldGhvZCArICdcIiwgcGFyYW1zOiAnICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSArICd9Jyk7XG5cbiAgICAgICAgdGhpcy5qc29uUnBjQ2xpZW50LnNlbmQobWV0aG9kLCBwYXJhbXMsIGNhbGxiYWNrKTtcbiAgICB9XG5cbiAgICBjbG9zZShmb3JjZWQpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5sZWF2ZShmb3JjZWQsIHRoaXMuanNvblJwY0NsaWVudCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgZGlzY29ubmVjdFBhcnRpY2lwYW50KHN0cmVhbSkge1xuICAgICAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmRpc2Nvbm5lY3Qoc3RyZWFtKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vQ0hBVFxuICAgIHNlbmRNZXNzYWdlKG1lc3NhZ2UpIHtcbiAgICAgICAgdGhpcy5zZW5kUmVxdWVzdCgnc2VuZE1lc3NhZ2UnLCB7XG4gICAgICAgICAgICBtZXNzYWdlOiBtZXNzYWdlXG4gICAgICAgIH0sIGZ1bmN0aW9uIChlcnJvciwgcmVzcG9uc2UpIHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKGNhbWVyYU9wdGlvbnM6IGFueSkge1xuICAgICAgICBsZXQgbWVkaWFDb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgIGF1ZGlvOiBjYW1lcmFPcHRpb25zLmF1ZGlvLFxuICAgICAgICAgICAgdmlkZW86IHt9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFjYW1lcmFPcHRpb25zLnZpZGVvKSB7XG4gICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvID0gZmFsc2VcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxldCB3LCBoO1xuICAgICAgICAgICAgc3dpdGNoIChjYW1lcmFPcHRpb25zLnF1YWxpdHkpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdMT1cnOlxuICAgICAgICAgICAgICAgICAgICB3ID0gMzIwO1xuICAgICAgICAgICAgICAgICAgICBoID0gMjQwO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdNRURJVU0nOlxuICAgICAgICAgICAgICAgICAgICB3ID0gNjQwO1xuICAgICAgICAgICAgICAgICAgICBoID0gNDgwO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdISUdIJzpcbiAgICAgICAgICAgICAgICAgICAgdyA9IDEyODA7XG4gICAgICAgICAgICAgICAgICAgIGggPSA3MjA7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHcgPSA2NDA7XG4gICAgICAgICAgICAgICAgICAgIGggPSA0ODA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvWyd3aWR0aCddID0geyBleGFjdDogdyB9O1xuICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50cy52aWRlb1snaGVpZ2h0J10gPSB7IGV4YWN0OiBoIH07XG4gICAgICAgICAgICAvL21lZGlhQ29uc3RyYWludHMudmlkZW9bJ2ZyYW1lUmF0ZSddID0geyBpZGVhbDogTnVtYmVyKCg8SFRNTElucHV0RWxlbWVudD5kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZnJhbWVSYXRlJykpLnZhbHVlKSB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtZWRpYUNvbnN0cmFpbnRzO1xuICAgIH1cblxufVxuIiwiaW1wb3J0IHsgU3RyZWFtLCBTdHJlYW1PcHRpb25zU2VydmVyIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgT3BlblZpZHVJbnRlcm5hbCB9IGZyb20gJy4vT3BlblZpZHVJbnRlcm5hbCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uLCBDb25uZWN0aW9uT3B0aW9ucyB9IGZyb20gJy4vQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdS9QdWJsaXNoZXInO1xuXG5pbXBvcnQgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnd29sZnk4Ny1ldmVudGVtaXR0ZXInKTtcblxudHlwZSBPYmpNYXA8VD4gPSB7IFtzOiBzdHJpbmddOiBUOyB9XG5cbmNvbnN0IFNFQ1JFVF9QQVJBTSA9ICc/c2VjcmV0PSc7XG5jb25zdCBSRUNPUkRFUl9QQVJBTSA9ICcmcmVjb3JkZXI9JztcblxuZXhwb3J0IGludGVyZmFjZSBTZXNzaW9uT3B0aW9ucyB7XG4gICAgc2Vzc2lvbklkOiBzdHJpbmc7XG4gICAgcGFydGljaXBhbnRJZDogc3RyaW5nO1xuICAgIG1ldGFkYXRhOiBzdHJpbmc7XG4gICAgc3Vic2NyaWJlVG9TdHJlYW1zPzogYm9vbGVhbjtcbiAgICB1cGRhdGVTcGVha2VySW50ZXJ2YWw/OiBudW1iZXI7XG4gICAgdGhyZXNob2xkU3BlYWtlcj86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTaWduYWxPcHRpb25zIHtcbiAgICB0eXBlPzogc3RyaW5nO1xuICAgIHRvPzogQ29ubmVjdGlvbltdO1xuICAgIGRhdGE/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjbGFzcyBTZXNzaW9uSW50ZXJuYWwge1xuXG4gICAgcHJpdmF0ZSBpZDogc3RyaW5nO1xuICAgIHByaXZhdGUgc2Vzc2lvbklkOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICBwcml2YXRlIHJlbW90ZVN0cmVhbXM6IE9iak1hcDxTdHJlYW0+ID0ge307XG4gICAgcHJpdmF0ZSBwYXJ0aWNpcGFudHMgPSB7fTtcbiAgICBwcml2YXRlIHB1Ymxpc2hlcnNTcGVha2luZzogQ29ubmVjdGlvbltdID0gW107XG4gICAgcHJpdmF0ZSBjb25uZWN0ZWQgPSBmYWxzZTtcbiAgICBwdWJsaWMgbG9jYWxQYXJ0aWNpcGFudDogQ29ubmVjdGlvbjtcbiAgICBwcml2YXRlIHN1YnNjcmliZVRvU3RyZWFtczogYm9vbGVhbjtcbiAgICBwcml2YXRlIHVwZGF0ZVNwZWFrZXJJbnRlcnZhbDogbnVtYmVyO1xuICAgIHB1YmxpYyB0aHJlc2hvbGRTcGVha2VyOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBvcHRpb25zOiBTZXNzaW9uT3B0aW9ucztcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgb3BlblZpZHU6IE9wZW5WaWR1SW50ZXJuYWwsIHNlc3Npb25JZDogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc2Vzc2lvbklkID0gdGhpcy5nZXRVcmxXaXRob3V0U2VjcmV0KHNlc3Npb25JZCk7XG4gICAgICAgIHRoaXMubG9jYWxQYXJ0aWNpcGFudCA9IG5ldyBDb25uZWN0aW9uKHRoaXMub3BlblZpZHUsIHRydWUsIHRoaXMpO1xuICAgICAgICBpZiAoIXRoaXMub3BlblZpZHUuZ2V0V3NVcmkoKSAmJiAhIXNlc3Npb25JZCkge1xuICAgICAgICAgICAgdGhpcy5wcm9jZXNzT3BlblZpZHVVcmwoc2Vzc2lvbklkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgcHJvY2Vzc09wZW5WaWR1VXJsKHVybDogc3RyaW5nKSB7XG4gICAgICAgIGxldCBzZWNyZXQgPSB0aGlzLmdldFNlY3JldEZyb21VcmwodXJsKTtcbiAgICAgICAgbGV0IHJlY29yZGVyID0gdGhpcy5nZXRSZWNvcmRlckZyb21VcmwodXJsKTtcbiAgICAgICAgaWYgKCEoc2VjcmV0ID09IG51bGwpKSB7XG4gICAgICAgICAgICB0aGlzLm9wZW5WaWR1LnNldFNlY3JldChzZWNyZXQpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghKHJlY29yZGVyID09IG51bGwpKSB7XG4gICAgICAgICAgICB0aGlzLm9wZW5WaWR1LnNldFJlY29yZGVyKHJlY29yZGVyKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9wZW5WaWR1LnNldFdzVXJpKHRoaXMuZ2V0RmluYWxVcmwodXJsKSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRTZWNyZXRGcm9tVXJsKHVybDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgbGV0IHNlY3JldCA9ICcnO1xuICAgICAgICBpZiAodXJsLmluZGV4T2YoU0VDUkVUX1BBUkFNKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIGxldCBlbmRPZlNlY3JldCA9IHVybC5sYXN0SW5kZXhPZihSRUNPUkRFUl9QQVJBTSk7XG4gICAgICAgICAgICBpZiAoZW5kT2ZTZWNyZXQgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgc2VjcmV0ID0gdXJsLnN1YnN0cmluZyh1cmwubGFzdEluZGV4T2YoU0VDUkVUX1BBUkFNKSArIFNFQ1JFVF9QQVJBTS5sZW5ndGgsIGVuZE9mU2VjcmV0KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VjcmV0ID0gdXJsLnN1YnN0cmluZyh1cmwubGFzdEluZGV4T2YoU0VDUkVUX1BBUkFNKSArIFNFQ1JFVF9QQVJBTS5sZW5ndGgsIHVybC5sZW5ndGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzZWNyZXQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSZWNvcmRlckZyb21VcmwodXJsOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAgICAgbGV0IHJlY29yZGVyID0gJyc7XG4gICAgICAgIGlmICh1cmwuaW5kZXhPZihSRUNPUkRFUl9QQVJBTSkgIT09IC0xKSB7XG4gICAgICAgICAgICByZWNvcmRlciA9IHVybC5zdWJzdHJpbmcodXJsLmxhc3RJbmRleE9mKFJFQ09SREVSX1BBUkFNKSArIFJFQ09SREVSX1BBUkFNLmxlbmd0aCwgdXJsLmxlbmd0aCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBCb29sZWFuKHJlY29yZGVyKS52YWx1ZU9mKCk7O1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0VXJsV2l0aG91dFNlY3JldCh1cmw6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIGlmICghdXJsKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdzZXNzaW9uSWQgaXMgbm90IGRlZmluZWQnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodXJsLmluZGV4T2YoU0VDUkVUX1BBUkFNKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHVybCA9IHVybC5zdWJzdHJpbmcoMCwgdXJsLmxhc3RJbmRleE9mKFNFQ1JFVF9QQVJBTSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1cmw7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRGaW5hbFVybCh1cmw6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIHVybCA9IHRoaXMuZ2V0VXJsV2l0aG91dFNlY3JldCh1cmwpLnN1YnN0cmluZygwLCB1cmwubGFzdEluZGV4T2YoJy8nKSkgKyAnL3Jvb20nO1xuICAgICAgICBpZiAodXJsLmluZGV4T2YoXCIubmdyb2suaW9cIikgIT09IC0xKSB7XG4gICAgICAgICAgICAvLyBPcGVuVmlkdSBzZXJ2ZXIgVVJMIHJlZmVyZXMgdG8gYSBuZ3JvayBJUDogc2VjdXJlIHdzcyBwcm90b2NvbCBhbmQgZGVsZXRlIHBvcnQgb2YgVVJMXG4gICAgICAgICAgICB1cmwgPSB1cmwucmVwbGFjZShcIndzOi8vXCIsIFwid3NzOi8vXCIpO1xuICAgICAgICAgICAgbGV0IHJlZ2V4ID0gL1xcLm5ncm9rXFwuaW86XFxkKy87XG4gICAgICAgICAgICB1cmwgPSB1cmwucmVwbGFjZShyZWdleCwgXCIubmdyb2suaW9cIik7XG4gICAgICAgIH0gZWxzZSBpZiAoKHVybC5pbmRleE9mKFwibG9jYWxob3N0XCIpICE9PSAtMSkgfHwgKHVybC5pbmRleE9mKFwiMTI3LjAuMC4xXCIpICE9IC0xKSkge1xuICAgICAgICAgICAgLy8gT3BlblZpZHUgc2VydmVyIFVSTCByZWZlcmVzIHRvIGxvY2FsaG9zdCBJUFxuXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVybDtcbiAgICB9XG5cblxuXG4gICAgLyogTkVXIE1FVEhPRFMgKi9cbiAgICBjb25uZWN0KHRva2VuLCBjYWxsYmFjaykge1xuXG4gICAgICAgIHRoaXMub3BlblZpZHUuY29ubmVjdCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCdFUlJPUiBDT05ORUNUSU5HIFRPIE9QRU5WSURVJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcblxuICAgICAgICAgICAgICAgIGlmICghdG9rZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgdG9rZW4gPSB0aGlzLnJhbmRvbVRva2VuKCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbGV0IGpvaW5QYXJhbXMgPSB7XG4gICAgICAgICAgICAgICAgICAgIHRva2VuOiB0b2tlbixcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbjogdGhpcy5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiB0aGlzLm9wdGlvbnMubWV0YWRhdGEsXG4gICAgICAgICAgICAgICAgICAgIHNlY3JldDogdGhpcy5vcGVuVmlkdS5nZXRTZWNyZXQoKSxcbiAgICAgICAgICAgICAgICAgICAgcmVjb3JkZXI6IHRoaXMub3BlblZpZHUuZ2V0UmVjb3JkZXIoKSxcbiAgICAgICAgICAgICAgICAgICAgZGF0YUNoYW5uZWxzOiBmYWxzZVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmxvY2FsUGFydGljaXBhbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5rZXlzKHRoaXMubG9jYWxQYXJ0aWNpcGFudC5nZXRTdHJlYW1zKCkpLnNvbWUoc3RyZWFtSWQgPT5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc1tzdHJlYW1JZF0uaXNEYXRhQ2hhbm5lbEVuYWJsZWQoKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGpvaW5QYXJhbXMuZGF0YUNoYW5uZWxzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMub3BlblZpZHUuc2VuZFJlcXVlc3QoJ2pvaW5Sb29tJywgam9pblBhcmFtcywgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3RlZCA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBleFBhcnRpY2lwYW50czogQ29ubmVjdGlvbk9wdGlvbnNbXSA9IHJlc3BvbnNlLnZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJTVBPUlRBTlQ6IFVwZGF0ZSBjb25uZWN0aW9uSWQgd2l0aCB2YWx1ZSBzZW5kIGJ5IHNlcnZlclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2NhbFBhcnRpY2lwYW50LmNvbm5lY3Rpb25JZCA9IHJlc3BvbnNlLmlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYXJ0aWNpcGFudHNbcmVzcG9uc2UuaWRdID0gdGhpcy5sb2NhbFBhcnRpY2lwYW50O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgcm9vbUV2ZW50ID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcnRpY2lwYW50czogbmV3IEFycmF5PENvbm5lY3Rpb24+KCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtczogbmV3IEFycmF5PFN0cmVhbT4oKVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgbGVuZ3RoID0gZXhQYXJ0aWNpcGFudHMubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLm9wZW5WaWR1LCBmYWxzZSwgdGhpcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhQYXJ0aWNpcGFudHNbaV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24uY3JlYXRpb25UaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBhcnRpY2lwYW50c1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF0gPSBjb25uZWN0aW9uO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vbUV2ZW50LnBhcnRpY2lwYW50cy5wdXNoKGNvbm5lY3Rpb24pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHN0cmVhbXMgPSBjb25uZWN0aW9uLmdldFN0cmVhbXMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBrZXkgaW4gc3RyZWFtcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb29tRXZlbnQuc3RyZWFtcy5wdXNoKHN0cmVhbXNba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN1YnNjcmliZVRvU3RyZWFtcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtc1trZXldLnN1YnNjcmliZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBVcGRhdGUgbG9jYWwgQ29ubmVjdGlvbiBvYmplY3QgcHJvcGVydGllcyB3aXRoIHZhbHVlcyByZXR1cm5lZCBieSBzZXJ2ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9jYWxQYXJ0aWNpcGFudC5kYXRhID0gcmVzcG9uc2UubWV0YWRhdGE7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvY2FsUGFydGljaXBhbnQuY3JlYXRpb25UaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVwZGF0ZXMgdGhlIHZhbHVlIG9mIHByb3BlcnR5ICdjb25uZWN0aW9uJyBpbiBTZXNzaW9uIG9iamVjdFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3VwZGF0ZS1jb25uZWN0aW9uLW9iamVjdCcsIFt7IGNvbm5lY3Rpb246IHRoaXMubG9jYWxQYXJ0aWNpcGFudCB9XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBPd24gY29ubmVjdGlvbiBjcmVhdGVkIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkNyZWF0ZWQnLCBbeyBjb25uZWN0aW9uOiB0aGlzLmxvY2FsUGFydGljaXBhbnQgfV0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmUgY29ubmVjdGlvbiBjcmVhdGVkIGV2ZW50IGZvciBlYWNoIGV4aXN0aW5nIGNvbm5lY3Rpb24gaW4gdGhlIHNlc3Npb25cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IHBhcnQgb2Ygcm9vbUV2ZW50LnBhcnRpY2lwYW50cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFt7IGNvbm5lY3Rpb246IHBhcnQgfV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAvL2lmICh0aGlzLnN1YnNjcmliZVRvU3RyZWFtcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgc3RyZWFtIG9mIHJvb21FdmVudC5zdHJlYW1zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbeyBzdHJlYW0gfV0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3RvcmUgdGhlIHJlbW90ZSBzdHJlYW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVN0cmVhbXNbc3RyZWFtLnN0cmVhbUlkXSA9IHN0cmVhbTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2sodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyogTkVXIE1FVEhPRFMgKi9cblxuXG5cblxuXG4gICAgY29uZmlndXJlKG9wdGlvbnM6IFNlc3Npb25PcHRpb25zKSB7XG4gICAgICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgICAgIHRoaXMuaWQgPSBvcHRpb25zLnNlc3Npb25JZDtcbiAgICAgICAgdGhpcy5zdWJzY3JpYmVUb1N0cmVhbXMgPSBvcHRpb25zLnN1YnNjcmliZVRvU3RyZWFtcyA9PSBudWxsID8gdHJ1ZSA6IG9wdGlvbnMuc3Vic2NyaWJlVG9TdHJlYW1zO1xuICAgICAgICB0aGlzLnVwZGF0ZVNwZWFrZXJJbnRlcnZhbCA9IG9wdGlvbnMudXBkYXRlU3BlYWtlckludGVydmFsIHx8IDE1MDA7XG4gICAgICAgIHRoaXMudGhyZXNob2xkU3BlYWtlciA9IG9wdGlvbnMudGhyZXNob2xkU3BlYWtlciB8fCAtNTA7XG4gICAgICAgIHRoaXMuYWN0aXZhdGVVcGRhdGVNYWluU3BlYWtlcigpO1xuXG4gICAgICAgIGlmICghdGhpcy5vcGVuVmlkdS5nZXRXc1VyaSgpKSB7XG4gICAgICAgICAgICB0aGlzLnByb2Nlc3NPcGVuVmlkdVVybChvcHRpb25zLnNlc3Npb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBnZXRJZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaWQ7XG4gICAgfVxuXG4gICAgZ2V0U2Vzc2lvbklkKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zZXNzaW9uSWQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhY3RpdmF0ZVVwZGF0ZU1haW5TcGVha2VyKCkge1xuXG4gICAgICAgIC8qc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucHVibGlzaGVyc1NwZWFraW5nLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFt7XG4gICAgICAgICAgICAgICAgICAgIHBhcnRpY2lwYW50SWQ6IHRoaXMucHVibGlzaGVyc1NwZWFraW5nW3RoaXMucHVibGlzaGVyc1NwZWFraW5nLmxlbmd0aCAtIDFdXG4gICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB0aGlzLnVwZGF0ZVNwZWFrZXJJbnRlcnZhbCk7Ki9cbiAgICB9XG5cbiAgICBnZXRMb2NhbFBhcnRpY2lwYW50KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sb2NhbFBhcnRpY2lwYW50O1xuICAgIH1cblxuICAgIGFkZEV2ZW50TGlzdGVuZXIoZXZlbnROYW1lLCBsaXN0ZW5lcikge1xuICAgICAgICB0aGlzLmVlLm9uKGV2ZW50TmFtZSwgbGlzdGVuZXIpO1xuICAgIH1cblxuICAgIGFkZE9uY2VFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgbGlzdGVuZXIpIHtcbiAgICAgICAgdGhpcy5lZS5vbmNlKGV2ZW50TmFtZSwgbGlzdGVuZXIpO1xuICAgIH1cblxuICAgIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSwgbGlzdGVuZXIpIHtcbiAgICAgICAgdGhpcy5lZS5vZmYoZXZlbnROYW1lLCBsaXN0ZW5lcik7XG4gICAgfVxuXG4gICAgcmVtb3ZlRXZlbnQoZXZlbnROYW1lKSB7XG4gICAgICAgIHRoaXMuZWUucmVtb3ZlRXZlbnQoZXZlbnROYW1lKTtcbiAgICB9XG5cbiAgICBlbWl0RXZlbnQoZXZlbnROYW1lLCBldmVudHNBcnJheSkge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudChldmVudE5hbWUsIGV2ZW50c0FycmF5KTtcbiAgICB9XG5cblxuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSkge1xuICAgICAgICBzdHJlYW0uc3Vic2NyaWJlKCk7XG4gICAgfVxuXG4gICAgdW5zdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0pIHtcbiAgICAgICAgY29uc29sZS5pbmZvKFwiVW5zdWJzY3JpYmluZyBmcm9tIFwiICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgdGhpcy5vcGVuVmlkdS5zZW5kUmVxdWVzdCgndW5zdWJzY3JpYmVGcm9tVmlkZW8nLCB7XG4gICAgICAgICAgICBzZW5kZXI6IHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZFxuICAgICAgICB9LFxuICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3IgdW5zdWJzY3JpYmluZyBmcm9tIFN1YnNjcmliZXJcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIlVuc3Vic2NyaWJlZCBjb3JyZWN0bHkgZnJvbSBcIiArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN0cmVhbS5kaXNwb3NlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBvblBhcnRpY2lwYW50UHVibGlzaGVkKHJlc3BvbnNlOiBDb25uZWN0aW9uT3B0aW9ucykge1xuXG4gICAgICAgIC8vIEdldCB0aGUgZXhpc3RpbmcgQ29ubmVjdGlvbiBjcmVhdGVkIG9uICdvblBhcnRpY2lwYW50Sm9pbmVkJyBmb3JcbiAgICAgICAgLy8gZXhpc3RpbmcgcGFydGljaXBhbnRzIG9yIGNyZWF0ZSBhIG5ldyBvbmUgZm9yIG5ldyBwYXJ0aWNpcGFudHNcbiAgICAgICAgbGV0IGNvbm5lY3Rpb246IENvbm5lY3Rpb24gPSB0aGlzLnBhcnRpY2lwYW50c1tyZXNwb25zZS5pZF07XG4gICAgICAgIGlmIChjb25uZWN0aW9uICE9IG51bGwpIHtcbiAgICAgICAgICAgIC8vIFVwZGF0ZSBleGlzdGluZyBDb25uZWN0aW9uXG4gICAgICAgICAgICByZXNwb25zZS5tZXRhZGF0YSA9IGNvbm5lY3Rpb24uZGF0YTtcbiAgICAgICAgICAgIGNvbm5lY3Rpb24uc2V0T3B0aW9ucyhyZXNwb25zZSk7XG4gICAgICAgICAgICBjb25uZWN0aW9uLmluaXRSZW1vdGVTdHJlYW1zKHJlc3BvbnNlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIENyZWF0ZSBuZXcgQ29ubmVjdGlvblxuICAgICAgICAgICAgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMub3BlblZpZHUsIGZhbHNlLCB0aGlzLCByZXNwb25zZSk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcGlkID0gY29ubmVjdGlvbi5jb25uZWN0aW9uSWQ7XG4gICAgICAgIGlmICghKHBpZCBpbiB0aGlzLnBhcnRpY2lwYW50cykpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoXCJSZW1vdGUgQ29ubmVjdGlvbiBub3QgZm91bmQgaW4gY29ubmVjdGlvbnMgbGlzdCBieSBpdHMgaWQgW1wiICsgcGlkICsgXCJdXCIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZyhcIlJlbW90ZSBDb25uZWN0aW9uIGZvdW5kIGluIGNvbm5lY3Rpb25zIGxpc3QgYnkgaXRzIGlkIFtcIiArIHBpZCArIFwiXVwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucGFydGljaXBhbnRzW3BpZF0gPSBjb25uZWN0aW9uO1xuXG4gICAgICAgIGxldCBzdHJlYW1zID0gY29ubmVjdGlvbi5nZXRTdHJlYW1zKCk7XG4gICAgICAgIGZvciAobGV0IGtleSBpbiBzdHJlYW1zKSB7XG4gICAgICAgICAgICBsZXQgc3RyZWFtID0gc3RyZWFtc1trZXldO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMucmVtb3RlU3RyZWFtc1tzdHJlYW0uc3RyZWFtSWRdKSB7XG4gICAgICAgICAgICAgICAgLy8gQXZvaWQgcmFjZSBjb25kaXRpb24gYmV0d2VlbiBzdHJlYW0uc3Vic2NyaWJlKCkgaW4gXCJvblBhcnRpY2lwYW50UHVibGlzaGVkXCIgYW5kIGluIFwiam9pblJvb21cIiBycGMgY2FsbGJhY2tcbiAgICAgICAgICAgICAgICAvLyBUaGlzIGNvbmRpdGlvbiBpcyBmYWxzZSBpZiBvcGVudmlkdS1zZXJ2ZXIgc2VuZHMgXCJwYXJ0aWNpcGFudFB1Ymxpc2hlZFwiIGV2ZW50IHRvIGEgc3Vic2NyaWJlciBwYXJ0aWNpcGFudCB0aGF0IGhhc1xuICAgICAgICAgICAgICAgIC8vIGFscmVhZHkgc3Vic2NyaWJlZCB0byBjZXJ0YWluIHN0cmVhbSBpbiB0aGUgY2FsbGJhY2sgb2YgXCJqb2luUm9vbVwiIG1ldGhvZFxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3Vic2NyaWJlVG9TdHJlYW1zKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbS5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbeyBzdHJlYW0gfV0pO1xuXG4gICAgICAgICAgICAgICAgLy8gU3RvcmUgdGhlIHJlbW90ZSBzdHJlYW1cbiAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVN0cmVhbXNbc3RyZWFtLnN0cmVhbUlkXSA9IHN0cmVhbTtcblxuICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvblBhcnRpY2lwYW50VW5wdWJsaXNoZWQobXNnKSB7XG4gICAgICAgIGxldCBjb25uZWN0aW9uOiBDb25uZWN0aW9uID0gdGhpcy5wYXJ0aWNpcGFudHNbbXNnLm5hbWVdO1xuXG4gICAgICAgIGlmIChjb25uZWN0aW9uICE9PSB1bmRlZmluZWQpIHtcblxuICAgICAgICAgICAgbGV0IHN0cmVhbXMgPSBjb25uZWN0aW9uLmdldFN0cmVhbXMoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGtleSBpbiBzdHJlYW1zKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFt7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbTogc3RyZWFtc1trZXldLFxuICAgICAgICAgICAgICAgICAgICBwcmV2ZW50RGVmYXVsdDogKCkgPT4geyB0aGlzLmVlLnJlbW92ZUV2ZW50KCdzdHJlYW0tZGVzdHJveWVkLWRlZmF1bHQnKTsgfVxuICAgICAgICAgICAgICAgIH1dKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtLWRlc3Ryb3llZC1kZWZhdWx0JywgW3tcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtOiBzdHJlYW1zW2tleV1cbiAgICAgICAgICAgICAgICB9XSk7XG5cbiAgICAgICAgICAgICAgICAvLyBEZWxldGluZyB0aGUgcmVtb3RlIHN0cmVhbVxuICAgICAgICAgICAgICAgIGxldCBzdHJlYW1JZDogc3RyaW5nID0gc3RyZWFtc1trZXldLnN0cmVhbUlkO1xuICAgICAgICAgICAgICAgIGxldCBzdHJlYW06IFN0cmVhbSA9IHRoaXMucmVtb3RlU3RyZWFtc1tzdHJlYW1JZF07XG5cbiAgICAgICAgICAgICAgICBzdHJlYW0uZGlzcG9zZSgpO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnJlbW90ZVN0cmVhbXNbc3RyZWFtLnN0cmVhbUlkXTtcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLnJlbW92ZVN0cmVhbShzdHJlYW0uc3RyZWFtSWQpO1xuXG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJQYXJ0aWNpcGFudCBcIiArIG1zZy5uYW1lXG4gICAgICAgICAgICAgICAgKyBcIiB1bmtub3duLiBQYXJ0aWNpcGFudHM6IFwiXG4gICAgICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeSh0aGlzLnBhcnRpY2lwYW50cykpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgb25QYXJ0aWNpcGFudEpvaW5lZChyZXNwb25zZTogQ29ubmVjdGlvbk9wdGlvbnMpIHtcblxuICAgICAgICBsZXQgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMub3BlblZpZHUsIGZhbHNlLCB0aGlzLCByZXNwb25zZSk7XG4gICAgICAgIGNvbm5lY3Rpb24uY3JlYXRpb25UaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgICAgICAgbGV0IHBpZCA9IGNvbm5lY3Rpb24uY29ubmVjdGlvbklkO1xuICAgICAgICBpZiAoIShwaWQgaW4gdGhpcy5wYXJ0aWNpcGFudHMpKSB7XG4gICAgICAgICAgICB0aGlzLnBhcnRpY2lwYW50c1twaWRdID0gY29ubmVjdGlvbjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vdXNlIGV4aXN0aW5nIHNvIHRoYXQgd2UgZG9uJ3QgbG9zZSBzdHJlYW1zIGluZm9cbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkNvbm5lY3Rpb24gYWxyZWFkeSBleGlzdHMgaW4gY29ubmVjdGlvbnMgbGlzdCB3aXRoIFwiICtcbiAgICAgICAgICAgICAgICBcInRoZSBzYW1lIGNvbm5lY3Rpb25JZCwgb2xkOlwiLCB0aGlzLnBhcnRpY2lwYW50c1twaWRdLCBcIiwgam9pbmVkIG5vdzpcIiwgY29ubmVjdGlvbik7XG4gICAgICAgICAgICBjb25uZWN0aW9uID0gdGhpcy5wYXJ0aWNpcGFudHNbcGlkXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdwYXJ0aWNpcGFudC1qb2luZWQnLCBbe1xuICAgICAgICAgICAgY29ubmVjdGlvbjogY29ubmVjdGlvblxuICAgICAgICB9XSk7XG5cbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25DcmVhdGVkJywgW3tcbiAgICAgICAgICAgIGNvbm5lY3Rpb246IGNvbm5lY3Rpb25cbiAgICAgICAgfV0pO1xuXG4gICAgfVxuXG4gICAgb25QYXJ0aWNpcGFudExlZnQobXNnKSB7XG5cbiAgICAgICAgbGV0IGNvbm5lY3Rpb246IENvbm5lY3Rpb24gPSB0aGlzLnBhcnRpY2lwYW50c1ttc2cubmFtZV07XG5cbiAgICAgICAgaWYgKGNvbm5lY3Rpb24gIT09IHVuZGVmaW5lZCkge1xuXG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncGFydGljaXBhbnQtbGVmdCcsIFt7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbjogY29ubmVjdGlvblxuICAgICAgICAgICAgfV0pO1xuXG4gICAgICAgICAgICBsZXQgc3RyZWFtcyA9IGNvbm5lY3Rpb24uZ2V0U3RyZWFtcygpO1xuICAgICAgICAgICAgZm9yIChsZXQga2V5IGluIHN0cmVhbXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3tcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtOiBzdHJlYW1zW2tleV0sXG4gICAgICAgICAgICAgICAgICAgIHByZXZlbnREZWZhdWx0OiAoKSA9PiB7IHRoaXMuZWUucmVtb3ZlRXZlbnQoJ3N0cmVhbS1kZXN0cm95ZWQtZGVmYXVsdCcpOyB9XG4gICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW0tZGVzdHJveWVkLWRlZmF1bHQnLCBbe1xuICAgICAgICAgICAgICAgICAgICBzdHJlYW06IHN0cmVhbXNba2V5XVxuICAgICAgICAgICAgICAgIH1dKTtcblxuICAgICAgICAgICAgICAgIC8vIERlbGV0aW5nIHRoZSByZW1vdGUgc3RyZWFtXG4gICAgICAgICAgICAgICAgbGV0IHN0cmVhbUlkOiBzdHJpbmcgPSBzdHJlYW1zW2tleV0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc1tzdHJlYW1JZF07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbm5lY3Rpb24uZGlzcG9zZSgpO1xuXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5wYXJ0aWNpcGFudHNbbXNnLm5hbWVdO1xuXG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkRlc3Ryb3llZCcsIFt7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbjogY29ubmVjdGlvblxuICAgICAgICAgICAgfV0pO1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJQYXJ0aWNpcGFudCBcIiArIG1zZy5uYW1lXG4gICAgICAgICAgICAgICAgKyBcIiB1bmtub3duLiBQYXJ0aWNpcGFudHM6IFwiXG4gICAgICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeSh0aGlzLnBhcnRpY2lwYW50cykpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIG9uUGFydGljaXBhbnRFdmljdGVkKG1zZykge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncGFydGljaXBhbnQtZXZpY3RlZCcsIFt7XG4gICAgICAgICAgICBsb2NhbFBhcnRpY2lwYW50OiB0aGlzLmxvY2FsUGFydGljaXBhbnRcbiAgICAgICAgfV0pO1xuICAgIH07XG5cbiAgICBvbk5ld01lc3NhZ2UobXNnKSB7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKFwiTmV3IHNpZ25hbDogXCIgKyBKU09OLnN0cmluZ2lmeShtc2cpKTtcblxuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2lnbmFsJywgW3tcbiAgICAgICAgICAgIGRhdGE6IG1zZy5kYXRhLFxuICAgICAgICAgICAgZnJvbTogdGhpcy5wYXJ0aWNpcGFudHNbbXNnLmZyb21dLFxuICAgICAgICAgICAgdHlwZTogbXNnLnR5cGVcbiAgICAgICAgfV0pO1xuXG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzaWduYWw6JyArIG1zZy50eXBlLCBbe1xuICAgICAgICAgICAgZGF0YTogbXNnLmRhdGEsXG4gICAgICAgICAgICBmcm9tOiB0aGlzLnBhcnRpY2lwYW50c1ttc2cuZnJvbV0sXG4gICAgICAgICAgICB0eXBlOiBtc2cudHlwZVxuICAgICAgICB9XSk7XG5cbiAgICB9XG5cbiAgICByZWN2SWNlQ2FuZGlkYXRlKG1zZykge1xuXG4gICAgICAgIGxldCBjYW5kaWRhdGUgPSB7XG4gICAgICAgICAgICBjYW5kaWRhdGU6IG1zZy5jYW5kaWRhdGUsXG4gICAgICAgICAgICBzZHBNaWQ6IG1zZy5zZHBNaWQsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBtc2cuc2RwTUxpbmVJbmRleFxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGNvbm5lY3Rpb24gPSB0aGlzLnBhcnRpY2lwYW50c1ttc2cuZW5kcG9pbnROYW1lXTtcbiAgICAgICAgaWYgKCFjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiUGFydGljaXBhbnQgbm90IGZvdW5kIGZvciBlbmRwb2ludCBcIiArXG4gICAgICAgICAgICAgICAgbXNnLmVuZHBvaW50TmFtZSArIFwiLiBJY2UgY2FuZGlkYXRlIHdpbGwgYmUgaWdub3JlZC5cIixcbiAgICAgICAgICAgICAgICBjYW5kaWRhdGUpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHN0cmVhbXMgPSBjb25uZWN0aW9uLmdldFN0cmVhbXMoKTtcbiAgICAgICAgZm9yIChsZXQga2V5IGluIHN0cmVhbXMpIHtcbiAgICAgICAgICAgIGxldCBzdHJlYW0gPSBzdHJlYW1zW2tleV07XG4gICAgICAgICAgICBzdHJlYW0uZ2V0V2ViUnRjUGVlcigpLmFkZEljZUNhbmRpZGF0ZShjYW5kaWRhdGUsIGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3IgYWRkaW5nIGNhbmRpZGF0ZSBmb3IgXCIgKyBrZXlcbiAgICAgICAgICAgICAgICAgICAgICAgICsgXCIgc3RyZWFtIG9mIGVuZHBvaW50IFwiICsgbXNnLmVuZHBvaW50TmFtZVxuICAgICAgICAgICAgICAgICAgICAgICAgKyBcIjogXCIgKyBlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvblJvb21DbG9zZWQobXNnKSB7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKFwiU2Vzc2lvbiBjbG9zZWQ6IFwiICsgSlNPTi5zdHJpbmdpZnkobXNnKSk7XG4gICAgICAgIGxldCByb29tID0gbXNnLnJvb207XG4gICAgICAgIGlmIChyb29tICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyb29tLWNsb3NlZCcsIFt7XG4gICAgICAgICAgICAgICAgcm9vbTogcm9vbVxuICAgICAgICAgICAgfV0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiU2Vzc2lvbiB1bmRlZmluZWQgb24gc2Vzc2lvbiBjbG9zZWRcIiwgbXNnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG9uTG9zdENvbm5lY3Rpb24oKSB7XG5cbiAgICAgICAgaWYgKCF0aGlzLmNvbm5lY3RlZCkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdOb3QgY29ubmVjdGVkIHRvIHNlc3Npb246IGlmIHlvdSBhcmUgbm90IGRlYnVnZ2luZywgdGhpcyBpcyBwcm9iYWJseSBhIGNlcnRpZmljYXRlIGVycm9yJyk7XG4gICAgICAgICAgICBpZiAod2luZG93LmNvbmZpcm0oJ0lmIHlvdSBhcmUgbm90IGRlYnVnZ2luZywgdGhpcyBpcyBwcm9iYWJseSBhIGNlcnRpZmljYXRlIGVycm9yIGF0IFxcXCInICsgdGhpcy5vcGVuVmlkdS5nZXRPcGVuVmlkdVNlcnZlclVSTCgpICsgJ1xcXCJcXG5cXG5DbGljayBPSyB0byBuYXZpZ2F0ZSBhbmQgYWNjZXB0IGl0JykpIHtcbiAgICAgICAgICAgICAgICBsb2NhdGlvbi5hc3NpZ24odGhpcy5vcGVuVmlkdS5nZXRPcGVuVmlkdVNlcnZlclVSTCgpICsgJy9hY2NlcHQtY2VydGlmaWNhdGUnKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlLndhcm4oJ0xvc3QgY29ubmVjdGlvbiBpbiBTZXNzaW9uICcgKyB0aGlzLmlkKTtcbiAgICAgICAgbGV0IHJvb20gPSB0aGlzLmlkO1xuICAgICAgICBpZiAocm9vbSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnbG9zdC1jb25uZWN0aW9uJywgW3sgcm9vbSB9XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1Nlc3Npb24gdW5kZWZpbmVkIHdoZW4gbG9zdCBjb25uZWN0aW9uJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvbk1lZGlhRXJyb3IocGFyYW1zKSB7XG5cbiAgICAgICAgY29uc29sZS5lcnJvcihcIk1lZGlhIGVycm9yOiBcIiArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykpO1xuICAgICAgICBsZXQgZXJyb3IgPSBwYXJhbXMuZXJyb3I7XG4gICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Vycm9yLW1lZGlhJywgW3tcbiAgICAgICAgICAgICAgICBlcnJvcjogZXJyb3JcbiAgICAgICAgICAgIH1dKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIlJlY2VpdmVkIHVuZGVmaW5lZCBtZWRpYSBlcnJvci4gUGFyYW1zOlwiLCBwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBmb3JjZWQgbWVhbnMgdGhlIHVzZXIgd2FzIGV2aWN0ZWQsIG5vIG5lZWQgdG8gc2VuZCB0aGUgJ2xlYXZlUm9vbScgcmVxdWVzdFxuICAgICAqL1xuICAgIGxlYXZlKGZvcmNlZCwganNvblJwY0NsaWVudCkge1xuXG4gICAgICAgIGZvcmNlZCA9ICEhZm9yY2VkO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIkxlYXZpbmcgU2Vzc2lvbiAoZm9yY2VkPVwiICsgZm9yY2VkICsgXCIpXCIpO1xuXG4gICAgICAgIGlmICh0aGlzLmNvbm5lY3RlZCAmJiAhZm9yY2VkKSB7XG4gICAgICAgICAgICB0aGlzLm9wZW5WaWR1LnNlbmRSZXF1ZXN0KCdsZWF2ZVJvb20nLCBmdW5jdGlvbiAoZXJyb3IsIHJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBqc29uUnBjQ2xpZW50LmNsb3NlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGpzb25ScGNDbGllbnQuY2xvc2UoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgICAgICBpZiAodGhpcy5wYXJ0aWNpcGFudHMpIHtcbiAgICAgICAgICAgIGZvciAobGV0IHBpZCBpbiB0aGlzLnBhcnRpY2lwYW50cykge1xuICAgICAgICAgICAgICAgIHRoaXMucGFydGljaXBhbnRzW3BpZF0uZGlzcG9zZSgpO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnBhcnRpY2lwYW50c1twaWRdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZGlzY29ubmVjdChzdHJlYW06IFN0cmVhbSkge1xuXG4gICAgICAgIGxldCBjb25uZWN0aW9uID0gc3RyZWFtLmdldFBhcnRpY2lwYW50KCk7XG4gICAgICAgIGlmICghY29ubmVjdGlvbikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIlN0cmVhbSB0byBkaXNjb25uZWN0IGhhcyBubyBwYXJ0aWNpcGFudFwiLCBzdHJlYW0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZGVsZXRlIHRoaXMucGFydGljaXBhbnRzW2Nvbm5lY3Rpb24uY29ubmVjdGlvbklkXTtcbiAgICAgICAgY29ubmVjdGlvbi5kaXNwb3NlKCk7XG5cbiAgICAgICAgaWYgKGNvbm5lY3Rpb24gPT09IHRoaXMubG9jYWxQYXJ0aWNpcGFudCkge1xuXG4gICAgICAgICAgICBjb25zb2xlLmluZm8oXCJVbnB1Ymxpc2hpbmcgbXkgbWVkaWEgKEknbSBcIiArIGNvbm5lY3Rpb24uY29ubmVjdGlvbklkICsgXCIpXCIpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMubG9jYWxQYXJ0aWNpcGFudDtcbiAgICAgICAgICAgIHRoaXMub3BlblZpZHUuc2VuZFJlcXVlc3QoJ3VucHVibGlzaFZpZGVvJywgZnVuY3Rpb24gKGVycm9yLCByZXNwb25zZSkge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJNZWRpYSB1bnB1Ymxpc2hlZCBjb3JyZWN0bHlcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMudW5zdWJzY3JpYmUoc3RyZWFtKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHVucHVibGlzaChwdWJsaXNoZXI6IFB1Ymxpc2hlcikge1xuXG4gICAgICAgIGxldCBzdHJlYW0gPSBwdWJsaXNoZXIuc3RyZWFtO1xuXG4gICAgICAgIGlmICghc3RyZWFtLmNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBudWxsXCIsIHN0cmVhbSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSBpZiAoc3RyZWFtLmNvbm5lY3Rpb24gIT09IHRoaXMubG9jYWxQYXJ0aWNpcGFudCkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIlRoZSBhc3NvY2lhdGVkIENvbm5lY3Rpb24gb2JqZWN0IG9mIHRoaXMgUHVibGlzaGVyIGlzIG5vdCB5b3VyIGxvY2FsIENvbm5lY3Rpb24uXCIgK1xuICAgICAgICAgICAgICAgIFwiT25seSBtb2RlcmF0b3JzIGNhbiBmb3JjZSB1bnB1Ymxpc2ggb24gcmVtb3RlIFN0cmVhbXMgdmlhICdmb3JjZVVucHVibGlzaCcgbWV0aG9kXCIsIHN0cmVhbSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdHJlYW0uZGlzcG9zZSgpO1xuXG4gICAgICAgICAgICBjb25zb2xlLmluZm8oXCJVbnB1Ymxpc2hpbmcgbG9jYWwgbWVkaWEgKFwiICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkICsgXCIpXCIpO1xuXG4gICAgICAgICAgICB0aGlzLm9wZW5WaWR1LnNlbmRSZXF1ZXN0KCd1bnB1Ymxpc2hWaWRlbycsIGZ1bmN0aW9uIChlcnJvciwgcmVzcG9uc2UpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiTWVkaWEgdW5wdWJsaXNoZWQgY29ycmVjdGx5XCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBzdHJlYW0uaXNSZWFkeVRvUHVibGlzaCA9IGZhbHNlO1xuICAgICAgICAgICAgc3RyZWFtLmlzU2NyZWVuUmVxdWVzdGVkUmVhZHkgPSBmYWxzZTtcblxuICAgICAgICAgICAgZGVsZXRlIHN0cmVhbS5jb25uZWN0aW9uLmdldFN0cmVhbXMoKVtzdHJlYW0uc3RyZWFtSWRdO1xuXG4gICAgICAgICAgICBwdWJsaXNoZXIuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbe1xuICAgICAgICAgICAgICAgIHN0cmVhbTogcHVibGlzaGVyLnN0cmVhbSxcbiAgICAgICAgICAgICAgICBwcmV2ZW50RGVmYXVsdDogKCkgPT4geyB0aGlzLmVlLnJlbW92ZUV2ZW50KCdzdHJlYW0tZGVzdHJveWVkLWRlZmF1bHQnKTsgfVxuICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgcHVibGlzaGVyLmVlLmVtaXRFdmVudCgnc3RyZWFtLWRlc3Ryb3llZC1kZWZhdWx0JywgW3tcbiAgICAgICAgICAgICAgICBzdHJlYW06IHB1Ymxpc2hlci5zdHJlYW1cbiAgICAgICAgICAgIH1dKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGdldFJlbW90ZVN0cmVhbXMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJlbW90ZVN0cmVhbXM7XG4gICAgfVxuXG4gICAgYWRkUGFydGljaXBhbnRTcGVha2luZyhwYXJ0aWNpcGFudElkKSB7XG4gICAgICAgIHRoaXMucHVibGlzaGVyc1NwZWFraW5nLnB1c2gocGFydGljaXBhbnRJZCk7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgW3tcbiAgICAgICAgICAgIHBhcnRpY2lwYW50SWQ6IHBhcnRpY2lwYW50SWRcbiAgICAgICAgfV0pO1xuICAgIH1cblxuICAgIHJlbW92ZVBhcnRpY2lwYW50U3BlYWtpbmcocGFydGljaXBhbnRJZCkge1xuICAgICAgICBsZXQgcG9zID0gLTE7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5wdWJsaXNoZXJzU3BlYWtpbmcubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnB1Ymxpc2hlcnNTcGVha2luZ1tpXSA9PSBwYXJ0aWNpcGFudElkKSB7XG4gICAgICAgICAgICAgICAgcG9zID0gaTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAocG9zICE9IC0xKSB7XG4gICAgICAgICAgICB0aGlzLnB1Ymxpc2hlcnNTcGVha2luZy5zcGxpY2UocG9zLCAxKTtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCBbe1xuICAgICAgICAgICAgICAgIHBhcnRpY2lwYW50SWQ6IHBhcnRpY2lwYW50SWRcbiAgICAgICAgICAgIH1dKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHN0cmluZ0NsaWVudE1ldGFkYXRhKG1ldGFkYXRhKTogc3RyaW5nIHtcbiAgICAgICAgaWYgKCEodHlwZW9mIG1ldGFkYXRhID09PSAnc3RyaW5nJykpIHtcbiAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShtZXRhZGF0YSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbWV0YWRhdGE7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHJhbmRvbVRva2VuKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiBNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zbGljZSgyKSArIE1hdGgucmFuZG9tKCkudG9TdHJpbmcoMzYpLnNsaWNlKDIpO1xuICAgIH1cblxufVxuIiwiLypcbiAqIG9wdGlvbnM6IG5hbWU6IFhYWCBkYXRhOiB0cnVlIChNYXliZSB0aGlzIGlzIGJhc2VkIG9uIHdlYnJ0YykgYXVkaW86IHRydWUsXG4gKiB2aWRlbzogdHJ1ZSwgdXJsOiBcImZpbGU6Ly8vLi4uXCIgPiBQbGF5ZXIgc2NyZWVuOiB0cnVlID4gRGVza3RvcCAoaW1wbGljaXRcbiAqIHZpZGVvOnRydWUsIGF1ZGlvOmZhbHNlKSBhdWRpbzogdHJ1ZSwgdmlkZW86IHRydWUgPiBXZWJjYW1cbiAqXG4gKiBzdHJlYW0uaGFzQXVkaW8oKTsgc3RyZWFtLmhhc1ZpZGVvKCk7IHN0cmVhbS5oYXNEYXRhKCk7XG4gKi9cbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuL0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbkludGVybmFsIH0gZnJvbSAnLi9TZXNzaW9uSW50ZXJuYWwnO1xuaW1wb3J0IHsgT3BlblZpZHVJbnRlcm5hbCwgQ2FsbGJhY2sgfSBmcm9tICcuL09wZW5WaWR1SW50ZXJuYWwnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgV2ViUnRjU3RhdHMgfSBmcm9tICcuL1dlYlJ0Y1N0YXRzJztcbmltcG9ydCBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCd3b2xmeTg3LWV2ZW50ZW1pdHRlcicpO1xuaW1wb3J0ICogYXMga3VyZW50b1V0aWxzIGZyb20gJy4uL0t1cmVudG9VdGlscy9rdXJlbnRvLXV0aWxzLWpzJztcblxuaW1wb3J0ICogYXMgYWRhcHRlciBmcm9tICd3ZWJydGMtYWRhcHRlcic7XG5cbmRlY2xhcmUgdmFyIG5hdmlnYXRvcjogYW55O1xuZGVjbGFyZSB2YXIgUlRDU2Vzc2lvbkRlc2NyaXB0aW9uOiBhbnk7XG5cbmlmICh3aW5kb3cpIHtcbiAgICB3aW5kb3dbXCJhZGFwdGVyXCJdID0gYWRhcHRlcjtcbn1cblxuZnVuY3Rpb24ganEoaWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGlkLnJlcGxhY2UoLyhAfDp8XFwufFxcW3xcXF18LCkvZywgXCJcXFxcJDFcIik7XG59XG5cbmZ1bmN0aW9uIHNob3coaWQ6IHN0cmluZykge1xuICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGpxKGlkKSkhLnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xufVxuXG5mdW5jdGlvbiBoaWRlKGlkOiBzdHJpbmcpIHtcbiAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChqcShpZCkpIS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFN0cmVhbU9wdGlvbnNTZXJ2ZXIge1xuICAgIGlkOiBzdHJpbmc7XG4gICAgYXVkaW9BY3RpdmU6IGJvb2xlYW47XG4gICAgdmlkZW9BY3RpdmU6IGJvb2xlYW47XG4gICAgdHlwZU9mVmlkZW86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJbmJvdW5kU3RyZWFtT3B0aW9ucyB7XG4gICAgaWQ6IHN0cmluZztcbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuICAgIHJlY3ZBdWRpbzogYm9vbGVhbjtcbiAgICByZWN2VmlkZW86IGJvb2xlYW47XG4gICAgdHlwZU9mVmlkZW86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPdXRib3VuZFN0cmVhbU9wdGlvbnMge1xuICAgIGFjdGl2ZUF1ZGlvOiBib29sZWFuO1xuICAgIGFjdGl2ZVZpZGVvOiBib29sZWFuO1xuICAgIGRhdGFDaGFubmVsOiBib29sZWFuO1xuICAgIG1lZGlhQ29uc3RyYWludHM6IGFueTtcbiAgICBzZW5kQXVkaW86IGJvb2xlYW47XG4gICAgc2VuZFZpZGVvOiBib29sZWFuO1xufVxuXG5leHBvcnQgY2xhc3MgU3RyZWFtIHtcblxuICAgIHB1YmxpYyBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuICAgIHB1YmxpYyBzdHJlYW1JZDogc3RyaW5nO1xuICAgIHB1YmxpYyBoYXNWaWRlbzogYm9vbGVhbjtcbiAgICBwdWJsaWMgaGFzQXVkaW86IGJvb2xlYW47XG4gICAgcHVibGljIHR5cGVPZlZpZGVvOiBzdHJpbmc7IC8vICdDQU1FUkEnIG9yICdTQ1JFRU4nXG5cbiAgICBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICBwcml2YXRlIG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbTtcbiAgICBwcml2YXRlIHdwOiBhbnk7XG4gICAgcHJpdmF0ZSB2aWRlbzogSFRNTFZpZGVvRWxlbWVudDtcbiAgICBwcml2YXRlIHNwZWVjaEV2ZW50OiBhbnk7XG4gICAgcHJpdmF0ZSBzaG93TXlSZW1vdGUgPSBmYWxzZTtcbiAgICBwcml2YXRlIGxvY2FsTWlycm9yZWQgPSBmYWxzZTtcbiAgICBwcml2YXRlIGNoYW5JZCA9IDA7XG4gICAgcHJpdmF0ZSBkYXRhQ2hhbm5lbE9wZW5lZCA9IGZhbHNlO1xuXG4gICAgaW5ib3VuZE9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zO1xuICAgIG91dGJvdW5kT3B0aW9uczogT3V0Ym91bmRTdHJlYW1PcHRpb25zO1xuXG4gICAgcHJpdmF0ZSBwYXJlbnRJZDogc3RyaW5nO1xuICAgIHB1YmxpYyBpc1JlYWR5VG9QdWJsaXNoOiBib29sZWFuID0gZmFsc2U7XG4gICAgcHVibGljIGlzUHVibGlzaGVyUHVibGlzaGVkOiBib29sZWFuID0gZmFsc2U7XG4gICAgcHVibGljIGlzVmlkZW9FTGVtZW50Q3JlYXRlZDogYm9vbGVhbiA9IGZhbHNlO1xuICAgIHB1YmxpYyBhY2Nlc3NJc0FsbG93ZWQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBwdWJsaWMgYWNjZXNzSXNEZW5pZWQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBwdWJsaWMgaXNTY3JlZW5SZXF1ZXN0ZWRSZWFkeTogYm9vbGVhbiA9IGZhbHNlO1xuICAgIHByaXZhdGUgaXNTY3JlZW5SZXF1ZXN0ZWQgPSBmYWxzZTtcblxuICAgIHByaXZhdGUgd2ViUnRjU3RhdHM6IFdlYlJ0Y1N0YXRzO1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBvcGVuVmlkdTogT3BlblZpZHVJbnRlcm5hbCwgcHJpdmF0ZSBsb2NhbDogYm9vbGVhbiwgcHJpdmF0ZSByb29tOiBTZXNzaW9uSW50ZXJuYWwsIG9wdGlvbnM6IGFueSkge1xuICAgICAgICBpZiAob3B0aW9ucyAhPT0gJ3NjcmVlbi1vcHRpb25zJykge1xuICAgICAgICAgICAgLy8gT3V0Ym91bmQgc3RyZWFtIChub3Qgc2NyZWVuIHNoYXJlKSBvciBJbmJvdW5kIHN0cmVhbVxuICAgICAgICAgICAgaWYgKCdpZCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5ib3VuZE9wdGlvbnMgPSBvcHRpb25zO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLm91dGJvdW5kT3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnN0cmVhbUlkID0gKG9wdGlvbnMuaWQgIT0gbnVsbCkgPyBvcHRpb25zLmlkIDogKChvcHRpb25zLnNlbmRWaWRlbykgPyBcIkNBTUVSQVwiIDogXCJNSUNST1wiKTtcbiAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSAob3B0aW9ucy50eXBlT2ZWaWRlbyAhPSBudWxsKSA/IG9wdGlvbnMudHlwZU9mVmlkZW8gOiAnJztcblxuICAgICAgICAgICAgaWYgKCdyZWN2QXVkaW8nIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICAvLyBTZXQgQ29ubmVjdGlvbiBmb3IgYW4gSW5ib3VuZCBzdHJlYW0gKGZvciBPdXRib3VuZCBzdHJlYW1zIHdpbGwgYmUgc2V0IG9uIFNlc3Npb24uUHVibGlzaChQdWJsaXNoZXIpKVxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IG9wdGlvbnMuY29ubmVjdGlvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE91dGJvdW5kIHN0cmVhbSBmb3Igc2NyZWVuIHNoYXJlXG4gICAgICAgICAgICB0aGlzLmlzU2NyZWVuUmVxdWVzdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSAnU0NSRUVOJztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ21lZGlhc3RyZWFtLXVwZGF0ZWQnLCAoKSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy52aWRlbykgdGhpcy52aWRlby5zcmNPYmplY3QgPSB0aGlzLm1lZGlhU3RyZWFtO1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZyhcIlZpZGVvIHNyY09iamVjdCBbXCIgKyB0aGlzLm1lZGlhU3RyZWFtICsgXCJdIGFkZGVkIHRvIHN0cmVhbSBbXCIgKyB0aGlzLnN0cmVhbUlkICsgXCJdXCIpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBlbWl0U3RyZWFtUmVhZHlFdmVudCgpIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbS1yZWFkeScpO1xuICAgIH1cblxuICAgIHJlbW92ZVZpZGVvKHBhcmVudEVsZW1lbnQ6IHN0cmluZyk7XG4gICAgcmVtb3ZlVmlkZW8ocGFyZW50RWxlbWVudDogRWxlbWVudCk7XG4gICAgcmVtb3ZlVmlkZW8oKTtcblxuICAgIHJlbW92ZVZpZGVvKHBhcmVudEVsZW1lbnQ/KSB7XG4gICAgICAgIGlmICh0aGlzLnZpZGVvKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHBhcmVudEVsZW1lbnQgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChwYXJlbnRFbGVtZW50KSEucmVtb3ZlQ2hpbGQodGhpcy52aWRlbyk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvLXJlbW92ZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocGFyZW50RWxlbWVudCBpbnN0YW5jZW9mIEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICBwYXJlbnRFbGVtZW50LnJlbW92ZUNoaWxkKHRoaXMudmlkZW8pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlby1yZW1vdmVkJyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCFwYXJlbnRFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgaWYgKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMucGFyZW50SWQpKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMucGFyZW50SWQpIS5yZW1vdmVDaGlsZCh0aGlzLnZpZGVvKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvLXJlbW92ZWQnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWxldGUgdGhpcy52aWRlbztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGdldFZpZGVvRWxlbWVudCgpOiBIVE1MVmlkZW9FbGVtZW50IHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmlkZW87XG4gICAgfVxuXG4gICAgc2V0VmlkZW9FbGVtZW50KHZpZGVvKSB7XG4gICAgICAgIGlmICghIXZpZGVvKSB0aGlzLnZpZGVvID0gdmlkZW87XG4gICAgfVxuXG4gICAgZ2V0UGFyZW50SWQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBhcmVudElkO1xuICAgIH1cblxuICAgIGdldFJlY3ZWaWRlbygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaW5ib3VuZE9wdGlvbnMucmVjdlZpZGVvO1xuICAgIH1cblxuICAgIGdldFJlY3ZBdWRpbygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaW5ib3VuZE9wdGlvbnMucmVjdkF1ZGlvO1xuICAgIH1cblxuICAgIGdldFNlbmRWaWRlbygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3V0Ym91bmRPcHRpb25zLnNlbmRWaWRlbztcbiAgICB9XG5cbiAgICBnZXRTZW5kQXVkaW8oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm91dGJvdW5kT3B0aW9ucy5zZW5kQXVkaW87XG4gICAgfVxuXG5cbiAgICBzdWJzY3JpYmVUb015UmVtb3RlKCkge1xuICAgICAgICB0aGlzLnNob3dNeVJlbW90ZSA9IHRydWU7XG4gICAgfVxuXG4gICAgZGlzcGxheU15UmVtb3RlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zaG93TXlSZW1vdGU7XG4gICAgfVxuXG4gICAgbWlycm9yTG9jYWxTdHJlYW0od3IpIHtcbiAgICAgICAgdGhpcy5zaG93TXlSZW1vdGUgPSB0cnVlO1xuICAgICAgICB0aGlzLmxvY2FsTWlycm9yZWQgPSB0cnVlO1xuICAgICAgICBpZiAod3IpIHtcbiAgICAgICAgICAgIHRoaXMubWVkaWFTdHJlYW0gPSB3cjtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdtZWRpYXN0cmVhbS11cGRhdGVkJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpc0xvY2FsTWlycm9yZWQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxvY2FsTWlycm9yZWQ7XG4gICAgfVxuXG4gICAgZ2V0Q2hhbm5lbE5hbWUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0cmVhbUlkICsgJ18nICsgdGhpcy5jaGFuSWQrKztcbiAgICB9XG5cblxuICAgIGlzRGF0YUNoYW5uZWxFbmFibGVkKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5vdXRib3VuZE9wdGlvbnMuZGF0YUNoYW5uZWw7XG4gICAgfVxuXG5cbiAgICBpc0RhdGFDaGFubmVsT3BlbmVkKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kYXRhQ2hhbm5lbE9wZW5lZDtcbiAgICB9XG5cbiAgICBvbkRhdGFDaGFubmVsT3BlbihldmVudCkge1xuICAgICAgICBjb25zb2xlLmRlYnVnKCdEYXRhIGNoYW5uZWwgaXMgb3BlbmVkJyk7XG4gICAgICAgIHRoaXMuZGF0YUNoYW5uZWxPcGVuZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIG9uRGF0YUNoYW5uZWxDbG9zZWQoZXZlbnQpIHtcbiAgICAgICAgY29uc29sZS5kZWJ1ZygnRGF0YSBjaGFubmVsIGlzIGNsb3NlZCcpO1xuICAgICAgICB0aGlzLmRhdGFDaGFubmVsT3BlbmVkID0gZmFsc2U7XG4gICAgfVxuXG4gICAgc2VuZERhdGEoZGF0YSkge1xuICAgICAgICBpZiAodGhpcy53cCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1dlYlJUQyBwZWVyIGhhcyBub3QgYmVlbiBjcmVhdGVkIHlldCcpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5kYXRhQ2hhbm5lbE9wZW5lZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdEYXRhIGNoYW5uZWwgaXMgbm90IG9wZW5lZCcpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIlNlbmRpbmcgdGhyb3VnaCBkYXRhIGNoYW5uZWw6IFwiICsgZGF0YSk7XG4gICAgICAgIHRoaXMud3Auc2VuZChkYXRhKTtcbiAgICB9XG5cbiAgICBnZXRNZWRpYVN0cmVhbSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgZ2V0V2ViUnRjUGVlcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud3A7XG4gICAgfVxuXG4gICAgZ2V0UlRDUGVlckNvbm5lY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndwLnBlZXJDb25uZWN0aW9uO1xuICAgIH1cblxuICAgIGFkZEV2ZW50TGlzdGVuZXIoZXZlbnROYW1lOiBzdHJpbmcsIGxpc3RlbmVyOiBhbnkpIHtcbiAgICAgICAgdGhpcy5lZS5hZGRMaXN0ZW5lcihldmVudE5hbWUsIGxpc3RlbmVyKTtcbiAgICB9XG5cbiAgICBhZGRPbmNlRXZlbnRMaXN0ZW5lcihldmVudE5hbWU6IHN0cmluZywgbGlzdGVuZXI6IGFueSkge1xuICAgICAgICB0aGlzLmVlLmFkZE9uY2VMaXN0ZW5lcihldmVudE5hbWUsIGxpc3RlbmVyKTtcbiAgICB9XG5cbiAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpIHtcbiAgICAgICAgdGhpcy5lZS5yZW1vdmVBbGxMaXN0ZW5lcnMoZXZlbnROYW1lKTtcbiAgICB9XG5cbiAgICBzaG93U3Bpbm5lcihzcGlubmVyUGFyZW50SWQ6IHN0cmluZykge1xuICAgICAgICBsZXQgcHJvZ3Jlc3MgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgcHJvZ3Jlc3MuaWQgPSAncHJvZ3Jlc3MtJyArIHRoaXMuc3RyZWFtSWQ7XG4gICAgICAgIHByb2dyZXNzLnN0eWxlLmJhY2tncm91bmQgPSBcImNlbnRlciB0cmFuc3BhcmVudCB1cmwoJ2ltZy9zcGlubmVyLmdpZicpIG5vLXJlcGVhdFwiO1xuICAgICAgICBsZXQgc3Bpbm5lclBhcmVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHNwaW5uZXJQYXJlbnRJZCk7XG4gICAgICAgIGlmIChzcGlubmVyUGFyZW50KSB7XG4gICAgICAgICAgICBzcGlubmVyUGFyZW50LmFwcGVuZENoaWxkKHByb2dyZXNzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGhpZGVTcGlubmVyKHNwaW5uZXJJZD86IHN0cmluZykge1xuICAgICAgICBzcGlubmVySWQgPSAoc3Bpbm5lcklkID09PSB1bmRlZmluZWQpID8gdGhpcy5zdHJlYW1JZCA6IHNwaW5uZXJJZDtcbiAgICAgICAgaGlkZSgncHJvZ3Jlc3MtJyArIHNwaW5uZXJJZCk7XG4gICAgfVxuXG4gICAgcGxheU9ubHlWaWRlbyhwYXJlbnRFbGVtZW50LCB0aHVtYm5haWxJZCkge1xuICAgICAgICBpZiAoISFwYXJlbnRFbGVtZW50KSB7XG5cbiAgICAgICAgICAgIHRoaXMudmlkZW8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuXG4gICAgICAgICAgICB0aGlzLnZpZGVvLmlkID0gKHRoaXMubG9jYWwgPyAnbG9jYWwtJyA6ICdyZW1vdGUtJykgKyAndmlkZW8tJyArIHRoaXMuc3RyZWFtSWQ7XG4gICAgICAgICAgICB0aGlzLnZpZGVvLmF1dG9wbGF5ID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMudmlkZW8uY29udHJvbHMgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdtZWRpYXN0cmVhbS11cGRhdGVkJyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmxvY2FsICYmICF0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlby5tdXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlby5vbmNhbnBsYXkgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkxvY2FsICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW1JZCArIFwiXSB2aWRlbyBpcyBub3cgcGxheWluZ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvLWlzLXBsYXlpbmcnLCBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudDogdGhpcy52aWRlb1xuICAgICAgICAgICAgICAgICAgICB9XSk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlby50aXRsZSA9IHRoaXMuc3RyZWFtSWQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgcGFyZW50RWxlbWVudCA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgIHRoaXMucGFyZW50SWQgPSBwYXJlbnRFbGVtZW50O1xuXG4gICAgICAgICAgICAgICAgbGV0IHBhcmVudEVsZW1lbnREb20gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChwYXJlbnRFbGVtZW50KTtcbiAgICAgICAgICAgICAgICBpZiAocGFyZW50RWxlbWVudERvbSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnZpZGVvID0gcGFyZW50RWxlbWVudERvbS5hcHBlbmRDaGlsZCh0aGlzLnZpZGVvKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvLWVsZW1lbnQtY3JlYXRlZC1ieS1zdHJlYW0nLCBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudDogdGhpcy52aWRlb1xuICAgICAgICAgICAgICAgICAgICB9XSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaXNWaWRlb0VMZW1lbnRDcmVhdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMucGFyZW50SWQgPSBwYXJlbnRFbGVtZW50LmlkO1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW8gPSBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMudmlkZW8pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmlzUmVhZHlUb1B1Ymxpc2ggPSB0cnVlO1xuXG4gICAgICAgICAgICByZXR1cm4gdGhpcy52aWRlbztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHBsYXlUaHVtYm5haWwodGh1bWJuYWlsSWQpIHtcblxuICAgICAgICBsZXQgY29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIGNvbnRhaW5lci5jbGFzc05hbWUgPSBcInBhcnRpY2lwYW50XCI7XG4gICAgICAgIGNvbnRhaW5lci5pZCA9IHRoaXMuc3RyZWFtSWQ7XG4gICAgICAgIGxldCB0aHVtYm5haWwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aHVtYm5haWxJZCk7XG4gICAgICAgIGlmICh0aHVtYm5haWwpIHtcbiAgICAgICAgICAgIHRodW1ibmFpbC5hcHBlbmRDaGlsZChjb250YWluZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IG5hbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgY29udGFpbmVyLmFwcGVuZENoaWxkKG5hbWUpO1xuICAgICAgICBsZXQgdXNlck5hbWUgPSB0aGlzLnN0cmVhbUlkLnJlcGxhY2UoJ193ZWJjYW0nLCAnJyk7XG4gICAgICAgIGlmICh1c2VyTmFtZS5sZW5ndGggPj0gMTYpIHtcbiAgICAgICAgICAgIHVzZXJOYW1lID0gdXNlck5hbWUuc3Vic3RyaW5nKDAsIDE2KSArIFwiLi4uXCI7XG4gICAgICAgIH1cbiAgICAgICAgbmFtZS5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSh1c2VyTmFtZSkpO1xuICAgICAgICBuYW1lLmlkID0gXCJuYW1lLVwiICsgdGhpcy5zdHJlYW1JZDtcbiAgICAgICAgbmFtZS5jbGFzc05hbWUgPSBcIm5hbWVcIjtcbiAgICAgICAgbmFtZS50aXRsZSA9IHRoaXMuc3RyZWFtSWQ7XG5cbiAgICAgICAgdGhpcy5zaG93U3Bpbm5lcih0aHVtYm5haWxJZCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMucGxheU9ubHlWaWRlbyhjb250YWluZXIsIHRodW1ibmFpbElkKTtcbiAgICB9XG5cbiAgICBnZXRQYXJ0aWNpcGFudCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29ubmVjdGlvbjtcbiAgICB9XG5cbiAgICByZXF1ZXN0Q2FtZXJhQWNjZXNzKGNhbGxiYWNrOiBDYWxsYmFjazxTdHJlYW0+KSB7XG5cbiAgICAgICAgbGV0IGNvbnN0cmFpbnRzID0gdGhpcy5vdXRib3VuZE9wdGlvbnMubWVkaWFDb25zdHJhaW50cztcblxuICAgICAgICAvKmxldCBjb25zdHJhaW50czIgPSB7XG4gICAgICAgICAgICBhdWRpbzogdHJ1ZSxcbiAgICAgICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICAgICAgd2lkdGg6IHtcbiAgICAgICAgICAgICAgICAgICAgaWRlYWw6IDEyODBcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGZyYW1lUmF0ZToge1xuICAgICAgICAgICAgICAgICAgICBpZGVhbDogMTVcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07Ki9cblxuICAgICAgICB0aGlzLnVzZXJNZWRpYUhhc1ZpZGVvKChoYXNWaWRlbykgPT4ge1xuICAgICAgICAgICAgaWYgKCFoYXNWaWRlbykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLm91dGJvdW5kT3B0aW9ucy5zZW5kVmlkZW8pIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuTk9fVklERU9fREVWSUNFLCAnWW91IGhhdmUgcmVxdWVzdGVkIGNhbWVyYSBhY2Nlc3MgYnV0IHRoZXJlIGlzIG5vIHZpZGVvIGlucHV0IGRldmljZSBhdmFpbGFibGUuIFRyeWluZyB0byBjb25uZWN0IHdpdGggYW4gYXVkaW8gaW5wdXQgZGV2aWNlIG9ubHknKSwgdGhpcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5vdXRib3VuZE9wdGlvbnMuc2VuZEF1ZGlvKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk5PX0lOUFVUX0RFVklDRSwgJ1lvdSBtdXN0IGluaXQgUHVibGlzaGVyIG9iamVjdCB3aXRoIGF1ZGlvIG9yIHZpZGVvIHN0cmVhbXMgZW5hYmxlZCcpLCB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzLnZpZGVvID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub3V0Ym91bmRPcHRpb25zLnNlbmRWaWRlbyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlcXVlc3RDYW1lcmFBY2Nlc0F1eChjb25zdHJhaW50cywgY2FsbGJhY2spO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXF1ZXN0Q2FtZXJhQWNjZXNBdXgoY29uc3RyYWludHMsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZXF1ZXN0Q2FtZXJhQWNjZXNBdXgoY29uc3RyYWludHMsIGNhbGxiYWNrKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGNvbnN0cmFpbnRzKTtcbiAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoY29uc3RyYWludHMpXG4gICAgICAgICAgICAudGhlbih1c2VyU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbWVyYUFjY2Vzc1N1Y2Nlc3ModXNlclN0cmVhbSwgY2FsbGJhY2spO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NJc0RlbmllZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NJc0FsbG93ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBsZXQgZXJyb3JOYW1lOiBPcGVuVmlkdUVycm9yTmFtZTtcbiAgICAgICAgICAgICAgICBsZXQgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTs7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmlzU2NyZWVuUmVxdWVzdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IHRoaXMub3V0Ym91bmRPcHRpb25zLnNlbmRWaWRlbyA/IE9wZW5WaWR1RXJyb3JOYW1lLkNBTUVSQV9BQ0NFU1NfREVOSUVEIDogT3BlblZpZHVFcnJvck5hbWUuTUlDUk9QSE9ORV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRDsgLy8gVGhpcyBjb2RlIGlzIG9ubHkgcmVhY2hhYmxlIGZvciBGaXJlZm94XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSwgdW5kZWZpbmVkKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgY2FtZXJhQWNjZXNzU3VjY2Vzcyh1c2VyU3RyZWFtOiBNZWRpYVN0cmVhbSwgY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gICAgICAgIHRoaXMuYWNjZXNzSXNBbGxvd2VkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5hY2Nlc3NJc0RlbmllZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnYWNjZXNzLWFsbG93ZWQtYnktcHVibGlzaGVyJyk7XG5cbiAgICAgICAgaWYgKHVzZXJTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSAhPSBudWxsKSB7XG4gICAgICAgICAgICB1c2VyU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0uZW5hYmxlZCA9IHRoaXMub3V0Ym91bmRPcHRpb25zLmFjdGl2ZUF1ZGlvO1xuICAgICAgICB9XG4gICAgICAgIGlmICh1c2VyU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0gIT0gbnVsbCkge1xuICAgICAgICAgICAgdXNlclN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdLmVuYWJsZWQgPSB0aGlzLm91dGJvdW5kT3B0aW9ucy5hY3RpdmVWaWRlbztcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMubWVkaWFTdHJlYW0gPSB1c2VyU3RyZWFtO1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnbWVkaWFzdHJlYW0tdXBkYXRlZCcpO1xuXG4gICAgICAgIGNhbGxiYWNrKHVuZGVmaW5lZCwgdGhpcyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSB1c2VyTWVkaWFIYXNWaWRlbyhjYWxsYmFjaykge1xuICAgICAgICAvLyBJZiB0aGUgdXNlciBpcyBnb2luZyB0byBwdWJsaXNoIGl0cyBzY3JlZW4gdGhlcmUncyBhIHZpZGVvIHNvdXJjZVxuICAgICAgICBpZiAodGhpcy5pc1NjcmVlblJlcXVlc3RlZCkge1xuICAgICAgICAgICAgY2FsbGJhY2sodHJ1ZSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBMaXN0IGFsbCBpbnB1dCBkZXZpY2VzIGFuZCBzZXJhY2ggZm9yIGEgdmlkZW8ga2luZFxuICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKCkudGhlbihmdW5jdGlvbiAobWVkaWFEZXZpY2VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHZpZGVvSW5wdXQgPSBtZWRpYURldmljZXMuZmlsdGVyKGZ1bmN0aW9uIChkZXZpY2VJbmZvKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkZXZpY2VJbmZvLmtpbmQgPT09ICd2aWRlb2lucHV0JztcbiAgICAgICAgICAgICAgICB9KVswXTtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayh2aWRlb0lucHV0ICE9IG51bGwpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaXNoVmlkZW9DYWxsYmFjayhlcnJvciwgc2RwT2ZmZXJQYXJhbSwgd3ApIHtcblxuICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBjb25zb2xlLmVycm9yKFwiKHB1Ymxpc2gpIFNEUCBvZmZlciBlcnJvcjogXCJcbiAgICAgICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlLmRlYnVnKFwiU2VuZGluZyBTRFAgb2ZmZXIgdG8gcHVibGlzaCBhcyBcIlxuICAgICAgICAgICAgKyB0aGlzLnN0cmVhbUlkLCBzZHBPZmZlclBhcmFtKTtcblxuICAgICAgICB0aGlzLm9wZW5WaWR1LnNlbmRSZXF1ZXN0KFwicHVibGlzaFZpZGVvXCIsIHtcbiAgICAgICAgICAgIHNkcE9mZmVyOiBzZHBPZmZlclBhcmFtLFxuICAgICAgICAgICAgZG9Mb29wYmFjazogdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSB8fCBmYWxzZSxcbiAgICAgICAgICAgIGF1ZGlvQWN0aXZlOiB0aGlzLm91dGJvdW5kT3B0aW9ucy5zZW5kQXVkaW8sXG4gICAgICAgICAgICB2aWRlb0FjdGl2ZTogdGhpcy5vdXRib3VuZE9wdGlvbnMuc2VuZFZpZGVvLFxuICAgICAgICAgICAgdHlwZU9mVmlkZW86ICgodGhpcy5vdXRib3VuZE9wdGlvbnMuc2VuZFZpZGVvKSA/ICgodGhpcy5pc1NjcmVlblJlcXVlc3RlZCkgPyAnU0NSRUVOJyA6ICdDQU1FUkEnKSA6ICcnKVxuICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3Igb24gcHVibGlzaFZpZGVvOiBcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMucHJvY2Vzc1NkcEFuc3dlcihyZXNwb25zZS5zZHBBbnN3ZXIpO1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIHN1Y2Nlc2Z1bGx5IHB1Ymxpc2hlZCB0byBzZXNzaW9uXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBzdGFydFZpZGVvQ2FsbGJhY2soZXJyb3IsIHNkcE9mZmVyUGFyYW0sIHdwKSB7XG4gICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIGNvbnNvbGUuZXJyb3IoXCIoc3Vic2NyaWJlKSBTRFAgb2ZmZXIgZXJyb3I6IFwiXG4gICAgICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuZGVidWcoXCJTZW5kaW5nIFNEUCBvZmZlciB0byBzdWJzY3JpYmUgdG8gXCJcbiAgICAgICAgICAgICsgdGhpcy5zdHJlYW1JZCwgc2RwT2ZmZXJQYXJhbSk7XG4gICAgICAgIHRoaXMub3BlblZpZHUuc2VuZFJlcXVlc3QoXCJyZWNlaXZlVmlkZW9Gcm9tXCIsIHtcbiAgICAgICAgICAgIHNlbmRlcjogdGhpcy5zdHJlYW1JZCxcbiAgICAgICAgICAgIHNkcE9mZmVyOiBzZHBPZmZlclBhcmFtXG4gICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBvbiByZWN2VmlkZW9Gcm9tOiBcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMucHJvY2Vzc1NkcEFuc3dlcihyZXNwb25zZS5zZHBBbnN3ZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRXZWJSdGNQZWVyKHNkcE9mZmVyQ2FsbGJhY2spIHtcbiAgICAgICAgaWYgKHRoaXMubG9jYWwpIHtcblxuICAgICAgICAgICAgbGV0IHVzZXJNZWRpYUNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLm91dGJvdW5kT3B0aW9ucy5zZW5kQXVkaW8sXG4gICAgICAgICAgICAgICAgdmlkZW86IHRoaXMub3V0Ym91bmRPcHRpb25zLnNlbmRWaWRlb1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgb3B0aW9uczogYW55ID0ge1xuICAgICAgICAgICAgICAgIHZpZGVvU3RyZWFtOiB0aGlzLm1lZGlhU3RyZWFtLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IHVzZXJNZWRpYUNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgIG9uaWNlY2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLm91dGJvdW5kT3B0aW9ucy5kYXRhQ2hhbm5lbCkge1xuICAgICAgICAgICAgICAgIG9wdGlvbnMuZGF0YUNoYW5uZWxDb25maWcgPSB7XG4gICAgICAgICAgICAgICAgICAgIGlkOiB0aGlzLmdldENoYW5uZWxOYW1lKCksXG4gICAgICAgICAgICAgICAgICAgIG9ub3BlbjogdGhpcy5vbkRhdGFDaGFubmVsT3BlbixcbiAgICAgICAgICAgICAgICAgICAgb25jbG9zZTogdGhpcy5vbkRhdGFDaGFubmVsQ2xvc2VkXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBvcHRpb25zLmRhdGFDaGFubmVscyA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53cCA9IGt1cmVudG9VdGlscy5XZWJSdGNQZWVyLldlYlJ0Y1BlZXJTZW5kcmVjdihvcHRpb25zLCBlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud3AuZ2VuZXJhdGVPZmZlcihzZHBPZmZlckNhbGxiYWNrLmJpbmQodGhpcykpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLndwID0ga3VyZW50b1V0aWxzLldlYlJ0Y1BlZXIuV2ViUnRjUGVlclNlbmRvbmx5KG9wdGlvbnMsIGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy53cC5nZW5lcmF0ZU9mZmVyKHNkcE9mZmVyQ2FsbGJhY2suYmluZCh0aGlzKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmlzUHVibGlzaGVyUHVibGlzaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxldCBvZmZlckNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmluYm91bmRPcHRpb25zLnJlY3ZBdWRpbyxcbiAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5pbmJvdW5kT3B0aW9ucy5yZWN2VmlkZW9cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKFwiJ1Nlc3Npb24uc3Vic2NyaWJlKFN0cmVhbSknIGNhbGxlZC4gQ29uc3RyYWludHMgb2YgZ2VuZXJhdGUgU0RQIG9mZmVyXCIsXG4gICAgICAgICAgICAgICAgb2ZmZXJDb25zdHJhaW50cyk7XG4gICAgICAgICAgICBsZXQgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBvbmljZWNhbmRpZGF0ZTogdGhpcy5jb25uZWN0aW9uLnNlbmRJY2VDYW5kaWRhdGUuYmluZCh0aGlzLmNvbm5lY3Rpb24pLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IG9mZmVyQ29uc3RyYWludHNcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMud3AgPSBrdXJlbnRvVXRpbHMuV2ViUnRjUGVlci5XZWJSdGNQZWVyUmVjdm9ubHkob3B0aW9ucywgZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMud3AuZ2VuZXJhdGVPZmZlcihzZHBPZmZlckNhbGxiYWNrLmJpbmQodGhpcykpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS5kZWJ1ZyhcIldhaXRpbmcgZm9yIFNEUCBvZmZlciB0byBiZSBnZW5lcmF0ZWQgKFwiXG4gICAgICAgICAgICArICh0aGlzLmxvY2FsID8gXCJsb2NhbFwiIDogXCJyZW1vdGVcIikgKyBcIiAnU3RyZWFtJzogXCIgKyB0aGlzLnN0cmVhbUlkICsgXCIpXCIpO1xuICAgIH1cblxuICAgIHB1Ymxpc2goKSB7XG5cbiAgICAgICAgLy8gRklYTUU6IFRocm93IGVycm9yIHdoZW4gc3RyZWFtIGlzIG5vdCBsb2NhbFxuICAgICAgICBpZiAodGhpcy5pc1JlYWR5VG9QdWJsaXNoKSB7XG4gICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNQZWVyKHRoaXMucHVibGlzaFZpZGVvQ2FsbGJhY2spO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lZS5vbmNlKCdzdHJlYW0tcmVhZHknLCBzdHJlYW1FdmVudCA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5wdWJsaXNoKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEZJWE1FOiBOb3cgd2UgaGF2ZSBjb3VwbGVkIGNvbm5lY3RpbmcgdG8gYSByb29tIGFuZCBhZGRpbmcgYVxuICAgICAgICAvLyBzdHJlYW0gdG8gdGhpcyByb29tLiBCdXQgaW4gdGhlIG5ldyBBUEksIHRoZXJlIGFyZSB0d28gc3RlcHMuXG4gICAgICAgIC8vIFRoaXMgaXMgdGhlIHNlY29uZCBzdGVwLiBGb3Igbm93LCBpdCBkbyBub3RoaW5nLlxuXG4gICAgfVxuXG4gICAgc3Vic2NyaWJlKCkge1xuXG4gICAgICAgIC8vIEZJWE1FOiBJbiB0aGUgY3VycmVudCBpbXBsZW1lbnRhdGlvbiBhbGwgcGFydGljaXBhbnRzIGFyZSBzdWJzY3JpYmVkXG4gICAgICAgIC8vIGF1dG9tYXRpY2FsbHkgdG8gYWxsIG90aGVyIHBhcnRpY2lwYW50cy4gV2UgdXNlIHRoaXMgbWV0aG9kIG9ubHkgdG9cbiAgICAgICAgLy8gbmVnb3RpYXRlIFNEUFxuXG4gICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1BlZXIodGhpcy5zdGFydFZpZGVvQ2FsbGJhY2spO1xuICAgIH1cblxuICAgIHByb2Nlc3NTZHBBbnN3ZXIoc2RwQW5zd2VyKSB7XG5cbiAgICAgICAgbGV0IGFuc3dlciA9IG5ldyBSVENTZXNzaW9uRGVzY3JpcHRpb24oe1xuICAgICAgICAgICAgdHlwZTogJ2Fuc3dlcicsXG4gICAgICAgICAgICBzZHA6IHNkcEFuc3dlcixcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnNvbGUuZGVidWcodGhpcy5zdHJlYW1JZCArIFwiOiBzZXQgcGVlciBjb25uZWN0aW9uIHdpdGggcmVjdmQgU0RQIGFuc3dlclwiLFxuICAgICAgICAgICAgc2RwQW5zd2VyKTtcbiAgICAgICAgbGV0IHBhcnRpY2lwYW50SWQgPSB0aGlzLnN0cmVhbUlkO1xuICAgICAgICBsZXQgcGMgPSB0aGlzLndwLnBlZXJDb25uZWN0aW9uO1xuICAgICAgICBwYy5zZXRSZW1vdGVEZXNjcmlwdGlvbihhbnN3ZXIsICgpID0+IHtcbiAgICAgICAgICAgIC8vIEF2b2lkcyB0byBzdWJzY3JpYmUgdG8geW91ciBvd24gc3RyZWFtIHJlbW90ZWx5IFxuICAgICAgICAgICAgLy8gZXhjZXB0IHdoZW4gc2hvd015UmVtb3RlIGlzIHRydWVcbiAgICAgICAgICAgIGlmICghdGhpcy5sb2NhbCB8fCB0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbSA9IHBjLmdldFJlbW90ZVN0cmVhbXMoKVswXTtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKFwiUGVlciByZW1vdGUgc3RyZWFtXCIsIHRoaXMubWVkaWFTdHJlYW0pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubWVkaWFTdHJlYW0gIT0gdW5kZWZpbmVkKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ21lZGlhc3RyZWFtLXVwZGF0ZWQnKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdICE9IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudCA9IGt1cmVudG9VdGlscy5XZWJSdGNQZWVyLmhhcmsodGhpcy5tZWRpYVN0cmVhbSwgeyB0aHJlc2hvbGQ6IHRoaXMucm9vbS50aHJlc2hvbGRTcGVha2VyIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzcGVha2luZycsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL3RoaXMucm9vbS5hZGRQYXJ0aWNpcGFudFNwZWFraW5nKHBhcnRpY2lwYW50SWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucm9vbS5lbWl0RXZlbnQoJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uOiB0aGlzLmNvbm5lY3Rpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbUlkOiB0aGlzLnN0cmVhbUlkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3N0b3BwZWRfc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy90aGlzLnJvb20ucmVtb3ZlUGFydGljaXBhbnRTcGVha2luZyhwYXJ0aWNpcGFudElkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJvb20uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uOiB0aGlzLmNvbm5lY3Rpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbUlkOiB0aGlzLnN0cmVhbUlkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghIXRoaXMudmlkZW8pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gbGV0IHRodW1ibmFpbElkID0gdGhpcy52aWRlby50aHVtYjtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy52aWRlby5vbmNhbnBsYXkgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5sb2NhbCAmJiB0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiWW91ciBvd24gcmVtb3RlICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW1JZCArIFwiXSB2aWRlbyBpcyBub3cgcGxheWluZ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncmVtb3RlLXZpZGVvLWlzLXBsYXlpbmcnLCBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50OiB0aGlzLnZpZGVvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghdGhpcy5sb2NhbCAmJiAhdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyBcIl0gdmlkZW8gaXMgbm93IHBsYXlpbmdcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvLWlzLXBsYXlpbmcnLCBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50OiB0aGlzLnZpZGVvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy9zaG93KHRodW1ibmFpbElkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vdGhpcy5oaWRlU3Bpbm5lcih0aGlzLnN0cmVhbUlkKTtcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5yb29tLmVtaXRFdmVudCgnc3RyZWFtLXN1YnNjcmliZWQnLCBbe1xuICAgICAgICAgICAgICAgICAgICBzdHJlYW06IHRoaXNcbiAgICAgICAgICAgICAgICB9XSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG5cbiAgICAgICAgfSwgZXJyb3IgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcih0aGlzLnN0cmVhbUlkICsgXCI6IEVycm9yIHNldHRpbmcgU0RQIHRvIHRoZSBwZWVyIGNvbm5lY3Rpb246IFwiXG4gICAgICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB1bnB1Ymxpc2goKSB7XG4gICAgICAgIGlmICh0aGlzLndwKSB7XG4gICAgICAgICAgICB0aGlzLndwLmRpc3Bvc2UoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICh0aGlzLm1lZGlhU3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goZnVuY3Rpb24gKHRyYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AgJiYgdHJhY2suc3RvcCgpXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaChmdW5jdGlvbiAodHJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgdHJhY2suc3RvcCAmJiB0cmFjay5zdG9wKClcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuc3BlZWNoRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQuc3RvcCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZS5pbmZvKHRoaXMuc3RyZWFtSWQgKyBcIjogU3RyZWFtICdcIiArIHRoaXMuc3RyZWFtSWQgKyBcIicgdW5wdWJsaXNoZWRcIik7XG4gICAgfVxuXG4gICAgZGlzcG9zZSgpIHtcblxuICAgICAgICBmdW5jdGlvbiBkaXNwb3NlRWxlbWVudChlbGVtZW50KSB7XG4gICAgICAgICAgICBpZiAoZWxlbWVudCAmJiBlbGVtZW50LnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICBlbGVtZW50LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZWxlbWVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBkaXNwb3NlRWxlbWVudChcInByb2dyZXNzLVwiICsgdGhpcy5zdHJlYW1JZCk7XG5cbiAgICAgICAgaWYgKHRoaXMud3ApIHtcbiAgICAgICAgICAgIHRoaXMud3AuZGlzcG9zZSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHRoaXMubWVkaWFTdHJlYW0pIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKCkuZm9yRWFjaChmdW5jdGlvbiAodHJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgdHJhY2suc3RvcCAmJiB0cmFjay5zdG9wKClcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKGZ1bmN0aW9uICh0cmFjaykge1xuICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wICYmIHRyYWNrLnN0b3AoKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnN0b3BXZWJSdGNTdGF0cygpO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbygodGhpcy5sb2NhbCA/IFwiTG9jYWwgXCIgOiBcIlJlbW90ZSBcIikgKyBcIidTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW1JZCArIFwiXScgaGFzIGJlZW4gc3VjY2VzZnVsbHkgZGlzcG9zZWRcIik7XG4gICAgfVxuXG4gICAgY29uZmlndXJlU2NyZWVuT3B0aW9ucyhvcHRpb25zOiBPdXRib3VuZFN0cmVhbU9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5vdXRib3VuZE9wdGlvbnMgPSBvcHRpb25zO1xuICAgICAgICB0aGlzLnN0cmVhbUlkID0gXCJTQ1JFRU5cIjtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRXZWJSdGNTdGF0cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy53ZWJSdGNTdGF0cyA9IG5ldyBXZWJSdGNTdGF0cyh0aGlzKTtcbiAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5pbml0V2ViUnRjU3RhdHMoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0b3BXZWJSdGNTdGF0cygpIHtcbiAgICAgICAgaWYgKHRoaXMud2ViUnRjU3RhdHMgIT0gbnVsbCAmJiB0aGlzLndlYlJ0Y1N0YXRzLmlzRW5hYmxlZCgpKSB7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzLnN0b3BXZWJSdGNTdGF0cygpO1xuICAgICAgICB9XG4gICAgfVxuXG59XG4iLCJpbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgKiBhcyBhZGFwdGVyIGZyb20gJ3dlYnJ0Yy1hZGFwdGVyJztcbmltcG9ydCAqIGFzIERldGVjdFJUQyBmcm9tICcuLi9LdXJlbnRvVXRpbHMvRGV0ZWN0UlRDJztcblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1N0YXRzIHtcblxuICAgIHByaXZhdGUgd2ViUnRjU3RhdHNFbmFibGVkOiBib29sZWFuID0gZmFsc2U7XG4gICAgcHJpdmF0ZSB3ZWJSdGNTdGF0c0ludGVydmFsSWQ6IG51bWJlcjtcbiAgICBwcml2YXRlIHN0YXRzSW50ZXJ2YWw6IG51bWJlciA9IDE7XG4gICAgcHJpdmF0ZSBzdGF0czogYW55ID0ge1xuICAgICAgICBcImluYm91bmRcIjoge1xuICAgICAgICAgICAgXCJhdWRpb1wiOiB7XG4gICAgICAgICAgICAgICAgXCJieXRlc1JlY2VpdmVkXCI6IDAsXG4gICAgICAgICAgICAgICAgXCJwYWNrZXRzUmVjZWl2ZWRcIjogMCxcbiAgICAgICAgICAgICAgICBcInBhY2tldHNMb3N0XCI6IDBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBcInZpZGVvXCI6IHtcbiAgICAgICAgICAgICAgICBcImJ5dGVzUmVjZWl2ZWRcIjogMCxcbiAgICAgICAgICAgICAgICBcInBhY2tldHNSZWNlaXZlZFwiOiAwLFxuICAgICAgICAgICAgICAgIFwicGFja2V0c0xvc3RcIjogMCxcbiAgICAgICAgICAgICAgICBcImZyYW1lc0RlY29kZWRcIjogMCxcbiAgICAgICAgICAgICAgICBcIm5hY2tDb3VudFwiOiAwXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwib3V0Ym91bmRcIjoge1xuICAgICAgICAgICAgXCJhdWRpb1wiOiB7XG4gICAgICAgICAgICAgICAgXCJieXRlc1NlbnRcIjogMCxcbiAgICAgICAgICAgICAgICBcInBhY2tldHNTZW50XCI6IDAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCJ2aWRlb1wiOiB7XG4gICAgICAgICAgICAgICAgXCJieXRlc1NlbnRcIjogMCxcbiAgICAgICAgICAgICAgICBcInBhY2tldHNTZW50XCI6IDAsXG4gICAgICAgICAgICAgICAgXCJmcmFtZXNFbmNvZGVkXCI6IDAsXG4gICAgICAgICAgICAgICAgXCJuYWNrQ291bnRcIjogMFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBzdHJlYW06IFN0cmVhbSkgeyB9XG5cbiAgICBwdWJsaWMgaXNFbmFibGVkKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNTdGF0c0VuYWJsZWQ7XG4gICAgfVxuXG4gICAgcHVibGljIGluaXRXZWJSdGNTdGF0cygpOiB2b2lkIHtcblxuICAgICAgICBsZXQgZWxhc3Rlc3RJbnN0cnVtZW50YXRpb24gPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnZWxhc3Rlc3QtaW5zdHJ1bWVudGF0aW9uJyk7XG5cbiAgICAgICAgaWYgKGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uKSB7XG4gICAgICAgICAgICAvLyBFbGFzVGVzdCBpbnN0cnVtZW50YXRpb24gb2JqZWN0IGZvdW5kIGluIGxvY2FsIHN0b3JhZ2VcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiV2ViUnRjIHN0YXRzIGVuYWJsZWQgZm9yIHN0cmVhbSBcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgXCIgb2YgY29ubmVjdGlvbiBcIiArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0VuYWJsZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBsZXQgaW5zdHJ1bWVudGF0aW9uID0gSlNPTi5wYXJzZShlbGFzdGVzdEluc3RydW1lbnRhdGlvbik7XG4gICAgICAgICAgICB0aGlzLnN0YXRzSW50ZXJ2YWwgPSBpbnN0cnVtZW50YXRpb24ud2VicnRjLmludGVydmFsOyAgLy8gSW50ZXJ2YWwgaW4gc2Vjb25kc1xuXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJsb2NhbFN0b3JhZ2UgaXRlbTogXCIgKyBKU09OLnN0cmluZ2lmeShpbnN0cnVtZW50YXRpb24pKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0ludGVydmFsSWQgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kU3RhdHNUb0h0dHBFbmRwb2ludChpbnN0cnVtZW50YXRpb24pO1xuICAgICAgICAgICAgfSwgdGhpcy5zdGF0c0ludGVydmFsICogMTAwMCk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGUuZGVidWcoXCJXZWJSdGMgc3RhdHMgbm90IGVuYWJsZWRcIik7XG4gICAgfVxuXG4gICAgcHVibGljIHN0b3BXZWJSdGNTdGF0cygpIHtcbiAgICAgICAgaWYgKHRoaXMud2ViUnRjU3RhdHNFbmFibGVkKSB7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHRoaXMud2ViUnRjU3RhdHNJbnRlcnZhbElkKTtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIldlYlJ0YyBzdGF0cyBzdG9wcGVkIGZvciBkaXNwb3NlZCBzdHJlYW0gXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArIFwiIG9mIGNvbm5lY3Rpb24gXCIgKyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHNlbmRTdGF0c1RvSHR0cEVuZHBvaW50KGluc3RydW1lbnRhdGlvbik6IHZvaWQge1xuXG4gICAgICAgIGxldCBzZW5kUG9zdCA9IChqc29uKSA9PiB7XG4gICAgICAgICAgICBsZXQgaHR0cDogWE1MSHR0cFJlcXVlc3QgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgIGxldCB1cmw6IHN0cmluZyA9IGluc3RydW1lbnRhdGlvbi53ZWJydGMuaHR0cEVuZHBvaW50O1xuICAgICAgICAgICAgaHR0cC5vcGVuKFwiUE9TVFwiLCB1cmwsIHRydWUpO1xuXG4gICAgICAgICAgICBodHRwLnNldFJlcXVlc3RIZWFkZXIoXCJDb250ZW50LXR5cGVcIiwgXCJhcHBsaWNhdGlvbi9qc29uXCIpO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHsgLy8gQ2FsbCBhIGZ1bmN0aW9uIHdoZW4gdGhlIHN0YXRlIGNoYW5nZXMuXG4gICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PSA0ICYmIGh0dHAuc3RhdHVzID09IDIwMCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIldlYlJ0YyBzdGF0cyBzdWNjZXNmdWxseSBzZW50IHRvIFwiICsgdXJsICsgXCIgZm9yIHN0cmVhbSBcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgXCIgb2YgY29ubmVjdGlvbiBcIiArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBodHRwLnNlbmQoanNvbik7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgZiA9IChzdGF0cykgPT4ge1xuXG4gICAgICAgICAgICBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIubmFtZSA9PT0gJ0ZpcmVmb3gnKSB7XG4gICAgICAgICAgICAgICAgc3RhdHMuZm9yRWFjaCgoc3RhdCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGxldCBqc29uID0ge307XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKChzdGF0LnR5cGUgPT09ICdpbmJvdW5kLXJ0cCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXZvaWQgZmlyZWZveCBlbXB0eSBvdXRib3VuZC1ydHAgc3RhdGlzdGljc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQubmFja0NvdW50ICE9IG51bGwgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlzUmVtb3RlID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaWQuc3RhcnRzV2l0aCgnaW5ib3VuZCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5yZW1vdGVJZC5zdGFydHNXaXRoKCdpbmJvdW5kJylcbiAgICAgICAgICAgICAgICAgICAgICAgICkpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG1ldHJpY0lkID0gJ3dlYnJ0Y19pbmJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBqaXR0ZXIgPSBzdGF0LmppdHRlciAqIDEwMDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiYnl0ZXNSZWNlaXZlZFwiOiAoc3RhdC5ieXRlc1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImppdHRlclwiOiBqaXR0ZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJwYWNrZXRzUmVjZWl2ZWRcIjogKHN0YXQucGFja2V0c1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwicGFja2V0c0xvc3RcIjogKHN0YXQucGFja2V0c0xvc3QgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB1bml0cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImJ5dGVzUmVjZWl2ZWRcIjogXCJieXRlc1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiaml0dGVyXCI6IFwibXNcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInBhY2tldHNSZWNlaXZlZFwiOiBcInBhY2tldHNcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInBhY2tldHNMb3N0XCI6IFwicGFja2V0c1wiXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snZnJhbWVzRGVjb2RlZCddID0gKHN0YXQuZnJhbWVzRGVjb2RlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5mcmFtZXNEZWNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWyduYWNrQ291bnQnXSA9IChzdGF0Lm5hY2tDb3VudCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWydmcmFtZXNEZWNvZGVkJ10gPSBcImZyYW1lc1wiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWyduYWNrQ291bnQnXSA9IFwicGFja2V0c1wiO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQgPSBzdGF0LmZyYW1lc0RlY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCA9IHN0YXQubmFja0NvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQgPSBzdGF0LmJ5dGVzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCA9IHN0YXQucGFja2V0c1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzTG9zdCA9IHN0YXQucGFja2V0c0xvc3Q7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJAdGltZXN0YW1wXCI6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZXhlY1wiOiBpbnN0cnVtZW50YXRpb24uZXhlYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImNvbXBvbmVudFwiOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwic3RyZWFtXCI6IFwid2ViUnRjXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJ0eXBlXCI6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwic3RyZWFtX3R5cGVcIjogXCJjb21wb3NlZF9tZXRyaWNzXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJ1bml0c1wiOiB1bml0c1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAganNvblttZXRyaWNJZF0gPSBtZXRyaWNzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgoc3RhdC50eXBlID09PSAnb3V0Ym91bmQtcnRwJykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBdm9pZCBmaXJlZm94IGVtcHR5IGluYm91bmQtcnRwIHN0YXRpc3RpY3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlzUmVtb3RlID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaWQudG9Mb3dlckNhc2UoKS5pbmNsdWRlcygnb3V0Ym91bmQnKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgbWV0cmljSWQgPSAnd2VicnRjX291dGJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcblxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG1ldHJpY3MgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJieXRlc1NlbnRcIjogKHN0YXQuYnl0ZXNTZW50IC0gdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInBhY2tldHNTZW50XCI6IChzdGF0LnBhY2tldHNTZW50IC0gdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiYnl0ZXNTZW50XCI6IFwiYnl0ZXNcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInBhY2tldHNTZW50XCI6IFwicGFja2V0c1wiXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snZnJhbWVzRW5jb2RlZCddID0gKHN0YXQuZnJhbWVzRW5jb2RlZCAtIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0VuY29kZWQnXSA9IFwiZnJhbWVzXCI7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kLnZpZGVvLmZyYW1lc0VuY29kZWQgPSBzdGF0LmZyYW1lc0VuY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCA9IHN0YXQuYnl0ZXNTZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1NlbnQgPSBzdGF0LnBhY2tldHNTZW50O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiQHRpbWVzdGFtcFwiOiBuZXcgRGF0ZShzdGF0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImV4ZWNcIjogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJjb21wb25lbnRcIjogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInN0cmVhbVwiOiBcIndlYlJ0Y1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwidHlwZVwiOiBtZXRyaWNJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInN0cmVhbV90eXBlXCI6IFwiY29tcG9zZWRfbWV0cmljc1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwidW5pdHNcIjogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgc2VuZFBvc3QoSlNPTi5zdHJpbmdpZnkoanNvbikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKERldGVjdFJUQy5icm93c2VyLm5hbWUgPT09ICdDaHJvbWUnKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHN0YXRzKSkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgc3RhdCA9IHN0YXRzW2tleV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGF0LnR5cGUgPT09ICdzc3JjJykge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQganNvbiA9IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJ2J5dGVzUmVjZWl2ZWQnIGluIHN0YXQgJiYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ2F1ZGlvJyAmJiAnYXVkaW9PdXRwdXRMZXZlbCcgaW4gc3RhdCkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycgJiYgJ3FwU3VtJyBpbiBzdGF0KVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluYm91bmQtcnRwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG1ldHJpY0lkID0gJ3dlYnJ0Y19pbmJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImJ5dGVzUmVjZWl2ZWRcIjogKHN0YXQuYnl0ZXNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiaml0dGVyXCI6IHN0YXQuZ29vZ0ppdHRlckJ1ZmZlck1zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInBhY2tldHNSZWNlaXZlZFwiOiAoc3RhdC5wYWNrZXRzUmVjZWl2ZWQgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwicGFja2V0c0xvc3RcIjogKHN0YXQucGFja2V0c0xvc3QgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImJ5dGVzUmVjZWl2ZWRcIjogXCJieXRlc1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImppdHRlclwiOiBcIm1zXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwicGFja2V0c1JlY2VpdmVkXCI6IFwicGFja2V0c1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInBhY2tldHNMb3N0XCI6IFwicGFja2V0c1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snZnJhbWVzRGVjb2RlZCddID0gKHN0YXQuZnJhbWVzRGVjb2RlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5mcmFtZXNEZWNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snbmFja0NvdW50J10gPSAoc3RhdC5nb29nTmFja3NTZW50IC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWydmcmFtZXNEZWNvZGVkJ10gPSBcImZyYW1lc1wiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snbmFja0NvdW50J10gPSBcInBhY2tldHNcIjtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCA9IHN0YXQuZnJhbWVzRGVjb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCA9IHN0YXQuZ29vZ05hY2tzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQgPSBzdGF0LmJ5dGVzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQgPSBzdGF0LnBhY2tldHNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0ID0gc3RhdC5wYWNrZXRzTG9zdDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiQHRpbWVzdGFtcFwiOiBuZXcgRGF0ZShzdGF0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJleGVjXCI6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImNvbXBvbmVudFwiOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInN0cmVhbVwiOiBcIndlYlJ0Y1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInR5cGVcIjogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwic3RyZWFtX3R5cGVcIjogXCJjb21wb3NlZF9tZXRyaWNzXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwidW5pdHNcIjogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAganNvblttZXRyaWNJZF0gPSBtZXRyaWNzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VuZFBvc3QoSlNPTi5zdHJpbmdpZnkoanNvbikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgnYnl0ZXNTZW50JyBpbiBzdGF0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb3V0Ym91bmQtcnRwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG1ldHJpY0lkID0gJ3dlYnJ0Y19vdXRib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJieXRlc1NlbnRcIjogKHN0YXQuYnl0ZXNTZW50IC0gdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJwYWNrZXRzU2VudFwiOiAoc3RhdC5wYWNrZXRzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImJ5dGVzU2VudFwiOiBcImJ5dGVzXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwicGFja2V0c1NlbnRcIjogXCJwYWNrZXRzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNFbmNvZGVkJ10gPSAoc3RhdC5mcmFtZXNFbmNvZGVkIC0gdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0VuY29kZWQnXSA9IFwiZnJhbWVzXCI7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkID0gc3RhdC5mcmFtZXNFbmNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCA9IHN0YXQuYnl0ZXNTZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50ID0gc3RhdC5wYWNrZXRzU2VudDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiQHRpbWVzdGFtcFwiOiBuZXcgRGF0ZShzdGF0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJleGVjXCI6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImNvbXBvbmVudFwiOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInN0cmVhbVwiOiBcIndlYlJ0Y1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInR5cGVcIjogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwic3RyZWFtX3R5cGVcIjogXCJjb21wb3NlZF9tZXRyaWNzXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwidW5pdHNcIjogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAganNvblttZXRyaWNJZF0gPSBtZXRyaWNzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VuZFBvc3QoSlNPTi5zdHJpbmdpZnkoanNvbikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMuZ2V0U3RhdHNBZ25vc3RpYyh0aGlzLnN0cmVhbS5nZXRSVENQZWVyQ29ubmVjdGlvbigpLCBudWxsLCBmLCAoZXJyb3IpID0+IHsgY29uc29sZS5sb2coZXJyb3IpIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhbmRhcmRpemVSZXBvcnQocmVzcG9uc2UpIHtcbiAgICAgICAgaWYgKERldGVjdFJUQy5icm93c2VyLm5hbWUgPT09ICdGaXJlZm94Jykge1xuICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHN0YW5kYXJkUmVwb3J0ID0ge307XG4gICAgICAgIHJlc3BvbnNlLnJlc3VsdCgpLmZvckVhY2goZnVuY3Rpb24gKHJlcG9ydCkge1xuICAgICAgICAgICAgdmFyIHN0YW5kYXJkU3RhdHMgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IHJlcG9ydC5pZCxcbiAgICAgICAgICAgICAgICB0aW1lc3RhbXA6IHJlcG9ydC50aW1lc3RhbXAsXG4gICAgICAgICAgICAgICAgdHlwZTogcmVwb3J0LnR5cGVcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXBvcnQubmFtZXMoKS5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgICAgICAgICAgc3RhbmRhcmRTdGF0c1tuYW1lXSA9IHJlcG9ydC5zdGF0KG5hbWUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzdGFuZGFyZFJlcG9ydFtzdGFuZGFyZFN0YXRzLmlkXSA9IHN0YW5kYXJkU3RhdHM7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBzdGFuZGFyZFJlcG9ydDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFN0YXRzQWdub3N0aWMocGMsIHNlbGVjdG9yLCBzdWNjZXNzQ2IsIGZhaWx1cmVDYikge1xuICAgICAgICBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIubmFtZSA9PT0gJ0ZpcmVmb3gnKSB7XG4gICAgICAgICAgICAvLyBnZXRTdGF0cyB0YWtlcyBhcmdzIGluIGRpZmZlcmVudCBvcmRlciBpbiBDaHJvbWUgYW5kIEZpcmVmb3hcbiAgICAgICAgICAgIHJldHVybiBwYy5nZXRTdGF0cyhzZWxlY3RvciwgKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgdmFyIHJlcG9ydCA9IHRoaXMuc3RhbmRhcmRpemVSZXBvcnQocmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYihyZXBvcnQpO1xuICAgICAgICAgICAgfSwgZmFpbHVyZUNiKTtcbiAgICAgICAgfSBlbHNlIGlmIChEZXRlY3RSVEMuYnJvd3Nlci5uYW1lID09PSAnQ2hyb21lJykge1xuICAgICAgICAgICAgLy8gSW4gQ2hyb21lLCB0aGUgZmlyc3QgdHdvIGFyZ3VtZW50cyBhcmUgcmV2ZXJzZWRcbiAgICAgICAgICAgIHJldHVybiBwYy5nZXRTdGF0cygocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICB2YXIgcmVwb3J0ID0gdGhpcy5zdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NiKHJlcG9ydCk7XG4gICAgICAgICAgICB9LCBzZWxlY3RvciwgZmFpbHVyZUNiKTtcbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8vIExhc3QgdGltZSB1cGRhdGVkIGF0IEZlYiAxNiwgMjAxNywgMDg6MzI6MjNcblxuLy8gTGF0ZXN0IGZpbGUgY2FuIGJlIGZvdW5kIGhlcmU6IGh0dHBzOi8vY2RuLndlYnJ0Yy1leHBlcmltZW50LmNvbS9nZXRTY3JlZW5JZC5qc1xuXG4vLyBNdWF6IEtoYW4gICAgICAgICAtIHd3dy5NdWF6S2hhbi5jb21cbi8vIE1JVCBMaWNlbnNlICAgICAgIC0gd3d3LldlYlJUQy1FeHBlcmltZW50LmNvbS9saWNlbmNlXG4vLyBEb2N1bWVudGF0aW9uICAgICAtIGh0dHBzOi8vZ2l0aHViLmNvbS9tdWF6LWtoYW4vZ2V0U2NyZWVuSWQuXG5cbi8vIF9fX19fX19fX19fX19fXG4vLyBnZXRTY3JlZW5JZC5qc1xuXG4vKlxuZ2V0U2NyZWVuSWQoZnVuY3Rpb24gKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuX2NvbnN0cmFpbnRzKSB7XG4gICAgLy8gZXJyb3IgICAgPT0gbnVsbCB8fCAncGVybWlzc2lvbi1kZW5pZWQnIHx8ICdub3QtaW5zdGFsbGVkJyB8fCAnaW5zdGFsbGVkLWRpc2FibGVkJyB8fCAnbm90LWNocm9tZSdcbiAgICAvLyBzb3VyY2VJZCA9PSBudWxsIHx8ICdzdHJpbmcnIHx8ICdmaXJlZm94J1xuICAgIFxuICAgIGlmKHNvdXJjZUlkID09ICdmaXJlZm94Jykge1xuICAgICAgICBuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKHNjcmVlbl9jb25zdHJhaW50cywgb25TdWNjZXNzLCBvbkZhaWx1cmUpO1xuICAgIH1cbiAgICBlbHNlIG5hdmlnYXRvci53ZWJraXRHZXRVc2VyTWVkaWEoc2NyZWVuX2NvbnN0cmFpbnRzLCBvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG59KTtcbiovXG5cbndpbmRvdy5nZXRTY3JlZW5JZCA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIC8vIGZvciBGaXJlZm94OlxuICAgIC8vIHNvdXJjZUlkID09ICdmaXJlZm94J1xuICAgIC8vIHNjcmVlbl9jb25zdHJhaW50cyA9IHsuLi59XG4gICAgaWYgKCEhbmF2aWdhdG9yLm1vekdldFVzZXJNZWRpYSkge1xuICAgICAgICBjYWxsYmFjayhudWxsLCAnZmlyZWZveCcsIHtcbiAgICAgICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICAgICAgbW96TWVkaWFTb3VyY2U6ICd3aW5kb3cnLFxuICAgICAgICAgICAgICAgIG1lZGlhU291cmNlOiAnd2luZG93J1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG5cbiAgICBmdW5jdGlvbiBvbklGcmFtZUNhbGxiYWNrKGV2ZW50KSB7XG4gICAgICAgIGlmICghZXZlbnQuZGF0YSkgcmV0dXJuO1xuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQpIHtcbiAgICAgICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQgPT09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soJ3Blcm1pc3Npb24tZGVuaWVkJyk7XG4gICAgICAgICAgICB9IGVsc2UgY2FsbGJhY2sobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBnZXRTY3JlZW5Db25zdHJhaW50cyhudWxsLCBldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykge1xuICAgICAgICAgICAgY2FsbGJhY2soZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMsIG51bGwsIGdldFNjcmVlbkNvbnN0cmFpbnRzKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0aGlzIGV2ZW50IGxpc3RlbmVyIGlzIG5vIG1vcmUgbmVlZGVkXG4gICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgfVxuXG4gICAgc2V0VGltZW91dChwb3N0R2V0U291cmNlSWRNZXNzYWdlLCAxMDApO1xufTtcblxuZnVuY3Rpb24gZ2V0U2NyZWVuQ29uc3RyYWludHMoZXJyb3IsIHNvdXJjZUlkKSB7XG4gICAgdmFyIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgYXVkaW86IGZhbHNlLFxuICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgbWFuZGF0b3J5OiB7XG4gICAgICAgICAgICAgICAgY2hyb21lTWVkaWFTb3VyY2U6IGVycm9yID8gJ3NjcmVlbicgOiAnZGVza3RvcCcsXG4gICAgICAgICAgICAgICAgbWF4V2lkdGg6IHdpbmRvdy5zY3JlZW4ud2lkdGggPiAxOTIwID8gd2luZG93LnNjcmVlbi53aWR0aCA6IDE5MjAsXG4gICAgICAgICAgICAgICAgbWF4SGVpZ2h0OiB3aW5kb3cuc2NyZWVuLmhlaWdodCA+IDEwODAgPyB3aW5kb3cuc2NyZWVuLmhlaWdodCA6IDEwODBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcHRpb25hbDogW11cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBpZiAoc291cmNlSWQpIHtcbiAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNjcmVlbl9jb25zdHJhaW50cztcbn1cblxuZnVuY3Rpb24gcG9zdEdldFNvdXJjZUlkTWVzc2FnZSgpIHtcbiAgICBpZiAoIWlmcmFtZSkge1xuICAgICAgICBsb2FkSUZyYW1lKHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFpZnJhbWUuaXNMb2FkZWQpIHtcbiAgICAgICAgc2V0VGltZW91dChwb3N0R2V0U291cmNlSWRNZXNzYWdlLCAxMDApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICBjYXB0dXJlU291cmNlSWQ6IHRydWVcbiAgICB9LCAnKicpO1xufVxuXG52YXIgaWZyYW1lO1xuXG4vLyB0aGlzIGZ1bmN0aW9uIGlzIHVzZWQgaW4gUlRDTXVsdGlDb25uZWN0aW9uIHYzXG53aW5kb3cuZ2V0U2NyZWVuQ29uc3RyYWludHMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBsb2FkSUZyYW1lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZ2V0U2NyZWVuSWQoZnVuY3Rpb24gKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuX2NvbnN0cmFpbnRzKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBsb2FkSUZyYW1lKGxvYWRDYWxsYmFjaykge1xuICAgIGlmIChpZnJhbWUpIHtcbiAgICAgICAgbG9hZENhbGxiYWNrKCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpZnJhbWUnKTtcbiAgICBpZnJhbWUub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZnJhbWUuaXNMb2FkZWQgPSB0cnVlO1xuXG4gICAgICAgIGxvYWRDYWxsYmFjaygpO1xuICAgIH07XG4gICAgaWZyYW1lLnNyYyA9ICdodHRwczovL3d3dy53ZWJydGMtZXhwZXJpbWVudC5jb20vZ2V0U291cmNlSWQvJzsgLy8gaHR0cHM6Ly93d3d3LnlvdXJkb21haW4uY29tL2dldFNjcmVlbklkLmh0bWxcbiAgICBpZnJhbWUuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAoZG9jdW1lbnQuYm9keSB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLmFwcGVuZENoaWxkKGlmcmFtZSk7XG59XG5cbndpbmRvdy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAvLyBmb3IgRmlyZWZveDpcbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZW5hYmxlZCcpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0aGlzIGV2ZW50IGxpc3RlbmVyIGlzIG5vIG1vcmUgbmVlZGVkXG4gICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgfVxuXG4gICAgc2V0VGltZW91dChwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSwgMTAwKTtcbn07XG5cbmZ1bmN0aW9uIHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlKCkge1xuICAgIGlmICghaWZyYW1lKSB7XG4gICAgICAgIGxvYWRJRnJhbWUocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFpZnJhbWUuaXNMb2FkZWQpIHtcbiAgICAgICAgc2V0VGltZW91dChwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSwgMTAwKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzOiB0cnVlXG4gICAgfSwgJyonKTtcbn1cblxuZXhwb3J0cy5nZXRTY3JlZW5JZCA9IGdldFNjcmVlbklkO1xuZXhwb3J0cy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXM7XG4iXX0= diff --git a/openvidu-recording-java/src/main/resources/static/style.css b/openvidu-recording-java/src/main/resources/static/style.css new file mode 100644 index 00000000..9a832e9f --- /dev/null +++ b/openvidu-recording-java/src/main/resources/static/style.css @@ -0,0 +1,399 @@ +html { + position: relative; + min-height: 100%; +} + +body { + 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; + height: 100%; + margin-top: -70px; +} + +.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; + margin-top: 100px; +} + +#session-header { + margin-bottom: 20px; + height: 8%; + margin-top: 70px; +} + +#session-header form { + display: inline; +} + +#session-title { + display: inline-block; +} + +#buttonLeaveSession { + float: right; + margin-top: 20px; +} + +#video-container { + width: 100%; + max-height: 45%; + display: inline-block; + overflow: hidden; +} + +#video-container video.two{ + width: 50%; +} + +#video-container video.three{ + width: 33.33%; +} + +#video-container video.four{ + width: 25%; +} + +#video-container div { + position: absolute; + display: inline-flex; + margin-left: calc(-50% + 15px); +} + +#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; + max-height: 100%; + object-fit: cover; +} + +#session { + height: 100%; + padding-bottom: 80px; +} + +#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; +} + +#recording-btns { + display: flow-root; + padding-left: 15px; + padding-top: 20px; + width: 100%; + height: 40%; +} + +#recording-btns input { + margin-top: 5px; +} + +#recording-btns #btns { + margin-top: 5px; +} + +#recording-btns #text-area { + display: inline-block; + width: 100%; + height: 80%; + margin-top: 20px; +} + +/* 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-recording-java/src/test/java/io/openvidu/js/java/test/AppTest.java b/openvidu-recording-java/src/test/java/io/openvidu/js/java/test/AppTest.java new file mode 100644 index 00000000..0ba99ec8 --- /dev/null +++ b/openvidu-recording-java/src/test/java/io/openvidu/js/java/test/AppTest.java @@ -0,0 +1,38 @@ +package io.openvidu.js.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-recording-node/.gitignore b/openvidu-recording-node/.gitignore new file mode 100644 index 00000000..dbe3e1ad --- /dev/null +++ b/openvidu-recording-node/.gitignore @@ -0,0 +1,60 @@ +# 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-recording-node/LICENSE b/openvidu-recording-node/LICENSE new file mode 100644 index 00000000..8dada3ed --- /dev/null +++ b/openvidu-recording-node/LICENSE @@ -0,0 +1,201 @@ + 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-recording-node/README.md b/openvidu-recording-node/README.md new file mode 100644 index 00000000..09a0b313 --- /dev/null +++ b/openvidu-recording-node/README.md @@ -0,0 +1,13 @@ +[![License badge](https://img.shields.io/badge/license-Apache2-orange.svg)](http://www.apache.org/licenses/LICENSE-2.0) +[![Documentation badge](https://readthedocs.org/projects/fiware-orion/badge/?version=latest)](http://openvidu.io/docs/home/) +[![Docker badge](https://img.shields.io/docker/pulls/fiware/orion.svg)](https://hub.docker.com/r/openvidu/) +[![Support badge](https://img.shields.io/badge/support-sof-yellowgreen.svg)](https://groups.google.com/forum/#!forum/openvidu) + +[![][OpenViduLogo]](http://openvidu.io) + +openvidu-recording-node +=== + +Visit [openvidu.io/docs/tutorials/openvidu-js-node/](http://openvidu.io/docs/tutorials/openvidu-js-node/) + +[OpenViduLogo]: https://secure.gravatar.com/avatar/5daba1d43042f2e4e85849733c8e5702?s=120 diff --git a/openvidu-recording-node/openviducert.pem b/openvidu-recording-node/openviducert.pem new file mode 100644 index 00000000..545ccee2 --- /dev/null +++ b/openvidu-recording-node/openviducert.pem @@ -0,0 +1,21 @@ +-----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-recording-node/openvidukey.pem b/openvidu-recording-node/openvidukey.pem new file mode 100644 index 00000000..9b47696d --- /dev/null +++ b/openvidu-recording-node/openvidukey.pem @@ -0,0 +1,27 @@ +-----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-recording-node/package.json b/openvidu-recording-node/package.json new file mode 100644 index 00000000..b4298e2b --- /dev/null +++ b/openvidu-recording-node/package.json @@ -0,0 +1,25 @@ +{ + "name": "openvidu-js-node", + "version": "1.0.0", + "description": "", + "main": "server.js", + "scripts": { + "test": "ng test" + }, + "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.17.2", + "express": "^4.15.3", + "express-session": "^1.15.3", + "openvidu-node-client": "1.7.0" + } +} diff --git a/openvidu-recording-node/public/app.js b/openvidu-recording-node/public/app.js new file mode 100644 index 00000000..04b97519 --- /dev/null +++ b/openvidu-recording-node/public/app.js @@ -0,0 +1,242 @@ +var OV; +var session; + +var sessionId; +var token; +var sessionName; +var numVideos = 0; + + +/* OPENVIDU METHODS */ + +function joinSession() { + getSessionIdAndToken(function () { + + // --- 1) Get an OpenVidu object and init a session with the retrieved sessionId --- + + OV = new OpenVidu(); + session = OV.initSession(sessionId); + + + // --- 2) Specify the actions when events take place --- + + // On every new Stream received... + session.on('streamCreated', function (event) { + + // Subscribe to the Stream to receive it + // HTML video will be appended to element with 'video-container' id + var subscriber = session.subscribe(event.stream, 'video-container'); + + // When the HTML video has been appended to DOM... + subscriber.on('videoElementCreated', function (event) { + // Add a new HTML element for the user's name and nickname over its video + updateNumVideos(1); + }); + + // When the HTML video has been appended to DOM... + subscriber.on('videoElementDestroyed', function (event) { + // Add a new HTML element for the user's name and nickname over its video + updateNumVideos(-1); + }); + }); + + // --- 3) Connect to the session passing the retrieved token --- + + session.connect(token, null, function (error) { + + // If the connection is successful, initialize a publisher and publish to the session + if (!error) { + + // --- 4) Get your own camera stream --- + + var publisher = OV.initPublisher('video-container', { + audio: true, // Whether you want to transmit audio or not + video: true, // Whether you want to transmit video or not + audioActive: true, // Whether you want to start the publishing with your audio unmuted or muted + videoActive: true, // Whether you want to start the publishing with your video enabled or disabled + quality: 'MEDIUM', // The quality of your video ('LOW', 'MEDIUM', 'HIGH') + screen: false // true to get your screen as video source instead of your camera + }); + + // When our HTML video has been added to DOM... + publisher.on('videoElementCreated', function (event) { + updateNumVideos(1); + $(event.element).prop('muted', true); // Mute local video + }); + + // When the HTML video has been appended to DOM... + publisher.on('videoElementDestroyed', function (event) { + // Add a new HTML element for the user's name and nickname over its video + updateNumVideos(-1); + }); + + + // --- 5) Publish your stream --- + + session.publish(publisher); + + } else { + console.warn('There was an error connecting to the session:', error.code, error.message); + } + }); + + $('#session-title').text(sessionName); + $('#join').hide(); + $('#session').show(); + + return false; + }); +} + +function leaveSession() { + + // 6) Leave the session by calling 'disconnect' method over the Session object + + session.disconnect(); + session = null; + numVideos = 0; + + $('#join').show(); + $('#session').hide(); +} + +/* OPENVIDU METHODS */ + + + +/* APPLICATION REST METHODS */ + +function getSessionIdAndToken(callback) { + sessionName = $("#sessionName").val(); // Video-call chosen by the user + + var jsonBody = JSON.stringify({ // Body of POST request + 'session': sessionName + }); + + // Send POST request + httpRequest('POST', 'api/get-sessionid-token', jsonBody, 'Request of SESSIONID and TOKEN gone WRONG:', function successCallback(response) { + sessionId = response[0]; // Get sessionId from response + token = response[1]; // Get token from response + console.warn('Request of SESSIONID and TOKEN gone WELL (SESSIONID:' + sessionId + ", TOKEN:" + token + ")"); + callback(); // Continue the join operation + }); +} + +function removeUser() { + // Body of POST request with the name of the session and the token of the leaving user + var jsonBody = JSON.stringify({ + 'sessionName': sessionName, + 'token': token + }); + + // Send POST request + httpRequest('POST', 'api/remove-user', jsonBody, 'User couldn\'t be removed from session', function successCallback(response) { + console.warn("User correctly removed from session"); + }); +} + +function httpRequest(method, url, body, errorMsg, callback) { + $('#text-area').text(''); + var http = new XMLHttpRequest(); + http.open(method, url, true); + http.setRequestHeader('Content-type', 'application/json'); + http.addEventListener('readystatechange', processRequest, false); + http.send(body); + + function processRequest() { + if (http.readyState == 4) { + if (http.status == 200) { + try { + callback(JSON.parse(http.responseText)); + } catch (e) { + callback(); + } + } else { + console.warn(errorMsg + ' (' + http.status + ')'); + console.warn(http.responseText); + $('#text-area').text(errorMsg + ": HTTP " + http.status + " (" + http.responseText + ")"); + } + } + } +} + +var recordingId; + +function startRecording() { + var jsonBody = JSON.stringify({ + 'session': session.sessionId + }); + httpRequest('POST', 'api/recording/start', jsonBody, 'Start recording WRONG', function successCallback(response) { + console.log(response); + recordingId = response.id; + $('#text-area').text(JSON.stringify(response, null, "\t")); + }); +} + +function stopRecording() { + var jsonBody = JSON.stringify({ + 'recording': recordingId + }); + httpRequest('POST', 'api/recording/stop', jsonBody, 'Stop recording WRONG', function successCallback(response) { + console.log(response); + $('#text-area').text(JSON.stringify(response, null, "\t")); + }); +} + +function deleteRecording() { + var jsonBody = JSON.stringify({ + 'recording': recordingId + }); + httpRequest('DELETE', 'api/recording/delete', jsonBody, 'Delete recording WRONG', function successCallback() { + console.log("DELETE ok"); + $('#text-area').text("DELETE ok"); + }); +} + +function getRecording() { + httpRequest('GET', 'api/recording/get/' + recordingId, '', 'Get recording WRONG', function successCallback(response) { + console.log(response); + $('#text-area').text(JSON.stringify(response, null, "\t")); + }); +} + +function listRecordings() { + httpRequest('GET', 'api/recording/list', '', 'List recordings WRONG', function successCallback(response) { + console.log(response); + $('#text-area').text(JSON.stringify(response, null, "\t")); + }); +} + +/* APPLICATION REST METHODS */ + + + +/* APPLICATION BROWSER METHODS */ + +window.onbeforeunload = function () { // Gracefully leave session + if (session) { + removeUser(); + leaveSession(); + } +} + +function updateNumVideos(i) { + numVideos += i; + $('video').removeClass(); + switch (numVideos) { + case 1: + $('video').addClass('two'); + break; + case 2: + $('video').addClass('two'); + break; + case 3: + $('video').addClass('three'); + break; + case 4: + $('video').addClass('four'); + break; + } +} + +/* APPLICATION BROWSER METHODS */ \ No newline at end of file diff --git a/openvidu-recording-node/public/images/favicon.ico b/openvidu-recording-node/public/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..0e2249ada68ec5cab2034721dc193285c27175b5 GIT binary patch literal 5430 zcmc&&eN2^Q6o2ox;0z74F{f9TU#+!9X2#sY&6#cG+%jk7$GvdHRGeG+hii#qr9`BK zC}qeHvGgi7)2x{@AZJeQ2i$vM6vot;IU_|SM7+HB^gGY{zHsji5d!CRKhN_%yyy9y z=RD^*=iDnvI!P}LA1>iDPFi7n3LB+bNp^oNLalA8=H z`-6iYNhVd-0{wN8JM*q}0bsYHpWyM3&HpH+LU-f&>6Fv>650J0N)zjuDZSc6C3#&o z_*8vxN9x<4|6}uZ>X2_!&8_cgL&Ni8P1fJjXZ?H%g+e5UI_YNcD%N;b@b^{!L~|as zb>5(}El$d8mIy_@DizA(Ef{Umop0o%=3L z^zNk@HLHP)NK~()6z}r(9R;IG5d)tho~Gi=Phk!9{FF1`IJgHmKAUu|POBE<&`n0{ z`~Z38{s^(X>5?n*o?(vf0mpJ*5OLQf2{sP^oM*-XGXX8nWQp8_iLj5h--j)QuU!4l zcm1^+@nJ!H#Q|OZ7U$!lB*+;+9Dv+6c(yQ?ig?KRuwfJA2(}$O93#xR6=(vGv*`&y z~xQi3P znSt>+$PP%p-|K*(fL5#6->6em58#f9dwT`8?80~sWW3~-#d&2N8zSU^9Ld0NMuE9` zU0^h@05}9(1DKb=<5>W|Bh~^3^C#l|mcS33GlBq1_=8XjLYX?ZoD}Q18pHgh+Z66- ze$}R7*k=mX&IQf`8gEb?pMo3@gvTHA^LejSIn_MHHi(?nVsPI+KE`|0k$G@(@{ufk za@hw`GHPh@;V|Gi<mXv<+e z?JUxZx*lZ%pG7N>0j{Tk)4)w2h#25=kKmu+-A8Zu9~bq?9x%)HTCzBv z<}(v)1WdH7#zYzCO!UcqJ;5j8e$dXO7+miGTFj}u8oyGnCVO|&BL7&yuk%i zsKG{Z1cr3|jsG4FTb-HKRv4)`Ul+lTz4KX=g1b=NZ`i&g`KPG-4s~s=+cv*}R@5fY z^4bx!s75b1H9NxVI(!8m80m{I2Zui`V8NdClu`E>xo&(z{#z#~@8WCVA4-dTdicT8 z z^&i{7;OFL!i&WH<-o?MF$|U?hxcu7wWwjTU;e#OEk^iAfw|%th58DIf&uq~6m3`ll z+vv~sU(ws|L~J~V80GI655oUS{H_4L!-1#x4w~zmNelgx=yl(OK4W2E0;N`2gZaB-FQW#Z2Y(}YtARXVOz-?$ zhq`ST!m( zi)i-rQ~rkcXLa|*I`Mr#?Y$f-H}m%b?o0kRPC_@yT2a&0b85DL6Me7fyL#Eb=7)Yt z<+qnctna`%57RiqCFc1ItiTf3xEV5c5b-Y7nuT@a!Z~{y<30WkGz^lziwzJVMc>6e TedKQfJ#jzGxv-xC9?I}vocwV} literal 0 HcmV?d00001 diff --git a/openvidu-recording-node/public/images/openvidu_globe_bg_transp_cropped.png b/openvidu-recording-node/public/images/openvidu_globe_bg_transp_cropped.png new file mode 100644 index 0000000000000000000000000000000000000000..e0309e62181608cf3543664ced79b6355779533b GIT binary patch literal 11746 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 KVuQR*wOeuWT3;&BESMc5c{Qzs4Eae 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
6<-acu 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 NQp-@YMBO3!e*nzNs#O30 literal 0 HcmV?d00001 diff --git a/openvidu-recording-node/public/images/subscriber-msg.jpg b/openvidu-recording-node/public/images/subscriber-msg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1666fb4099a9236147861e734e61869e37267767 GIT binary patch literal 82734 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 pgR(+GNPdoX zf@|!8C7yRdNd;jCc+?B>7qAB|4qj&gT-bW*{;}$xSu%6FxpDqKuIR`ULIP%qBe8_( z21WTi@lUX+|M|E}o8rH|{%Z~XYYz~!FvT>PN++)g#B_?a&=zBQRQj$?GUepDBZP!~$1uIZi{6e|qj;>e{{V7@a6paQLCwRIWlohtUga@LCYjO7nHG#>QZU8^p ze6Fqtk)Nc#l!3@0Z103anW`&AAAwiRcWh{K&+iTXl}I+h0!u|9j5IY&hrue;l|kji zRTR9ip*8MJ!))X3ZLiXC3uCHsmXn^wVY7YouW+vwy4L?CwH;nAJ0f~K%TGh&Ov+g~ zJ$8`5XoX8xoOuiWE>L5k|p$=pYDuGK7*QVwj~0!t@upo$nYH>8H9J&2%_DroG#b1Lk)t ze!={uMqr{WZb>%{&}D6N13v;8-n%LM9K(#>eAnWDg2#IV#r z;_6M=#xFYx8JN=EQ?Ul4WfT~PXrIE6HpbXohS;FFM@jipdVD1P^|)5 zHEyCvIRbvd-}m;ijG6)4S1yHTHg}yW`&S^n2h&zNYVDL&; zvz7O@ux5)=?eQo_|g^74C69x#<2iE*b=0SiMhvys@FTEF&{?3}PYx<~NvZMTnd zs(WCUEFlggKJIV3F6#visS(;~MVQGvlJtt~Oi$(VK>nxFl^vy;J(itn+Fm})O(#o0 zZd}MkfEe_Vb|QrKaD``WO~p45oji&Q1IhL;w0`}aT_ZlCr?H!C=^tax4Co^+1Fcf^ z3AmX40f9ZakNdYF#e~W0@ME4}J^DRJk=o2D7%0+|<8Y)cQW7 zEh{L@W&72l)6wPnl`7K<-PPoN{?Z6TvIvlUcz+M5TY;hYkY2P(7x10 zR`{GFC74ssbuXk1&^N-5C~hx<&Y34NeaIIWoeno#YO!Yak4!-Bb0=oiqXW8gv*=GD zeD31mP#r++*o#Bt7~vpS100Gvpbc^E6X?c`D$H(-mYV=G61Fply~fD~6PI$d{{GY} z&qH7f#03vm2OuNhy!0$pqsKaf!UpSl`uDg0>@w3odUn=mzkKYP?mOs1pxtjpGl~C6 z`+DWqI^!>I$SZAkB>;9kK&at5#KV7c6PJmq|4e}+Ems9aJ3F5GK}w8nDMBZwViyVE zNrcvMz3b~XBidNDTT{87RzzN2o003*h~b}`|66-+8r4+Vt&3V^FDeQGicLxsQE5_^ z0+uwXQV|gmJBWagvOzjArGj)JOF=+Dq-+3@(kKWhjgdA=lSr>1A|ON(AP_*>kc1{I z$jYiaseR79XMc6Z*mvAB_Mbbx9}a&2D=Tj^n`b`rnXcZdyKJvy#!kK(8ZL&pNgctV za!Wb{{PPgk)YpaRD?cg)`|x%7GaDF9sD&%TKR7Sk-#^5J)lF_7V zc?PK$|2W7}txdx1uHmcCF{1~5`=451|3{$FtE6(qat!HtGn(`cU&zINiMKHS!gEP9 z6WlGn)`1@{1d2U#%I2!!3|#GbC#A;W`OAnx;c$`caavMzjB1^RpVe|jX26sm%gp0h z%J|hP(o*_n|1F(s#hNs8slg5J%Q^{5c~9<}B_Hg#mU%F0O=cXE%Ru!SqG&srn1)1~ z9V#@_JsM9`&5vE5-FqdM*ycL@I(q^e9@G4fI`H2XYU}?Ha{2H2AHM<0>x{8;f~BNk z!3iMHJ#IlrhKjjJ*-lb#4SO}hWv2sO*d)W>j~>P9!|W-r zX2T3VLH3(OAlfI1I4OziNG+jn%8MK=F?;b-Oe;5vqcsXc>8Mi<2(KP7ktHNJ27e^C z`YA7~Dv92F`~cs4)0WzdN)?`IwR7DenL3A7H>iZPJV~gP)>Dv zBycr-G3EI!SLrJk`1pe#DRf;?dej{x}LKJoAAV3Ei~h9@52H8Wdu^G7};U;s+L-p`q_GXxC; z2c*o2(>q?!Apd@lGNT2r+ZD?g^BV+?H9Hl$<18E)5_|Eqspu;Hu854^%7$5F{n+Cf z;3&OB296zFIK&dANcUBNSL0kDt)tmU)F!Su;t^C2{XfTk$gj(?x&8EEsD z-D;jF?pT2Pgm_=77QBD*KJT}Kjp?=0JK13!lypRmzQ$jtC$=Knse39Wf51>*^>o3G z_~}#Cr)c*p1?7VknM;7dFmp^1$7D|0wk32MJ!=CwaoBQ!u=D5KXnpka4Z^3X zDkNeiy__29vITX^wkn#c&@8A<(0i;-*=}!l7X)g*i;%aB5+sKO)8@o5AV^4GB7?7n zKo#Q5vInHXsmh7hbL->>9>JW8z``WYCZwltkkpmP8KY5@fOgsg)#7I7mO1oRdMjtl zQ?QydvUiqa-p~B@iSxXH$Hi@&dNdTbTz-JxqfKIMO)F+6`eshWb21L$_FS<(a`M5~ zHtZ97-l<)lOuR;oBmbHABlA5o8XN;TmZw|wM5~CT z#J7=L3eom03>~@be7b~E-ekRYzoBC4!YYiY^8=hVqJKw7udzmOwEEi=!g z8r}UsX6I46_1K!+?gFkUQJ6IEZC>%M1sk<(Bpts9$}6@HwP2sQBeo;UrlkXJq z*tRZ8v_L(}2U+31EWl0XmE`nto#XVVg!Vzz;QKvHN_Wcd?N~0_BVjnBYe2tkc8;xO zLWx8q=S>%1%aZ;EvmWv)-vhH(Zu}pbyqo?XP2O>3bQ`Nm86p|Py_mECTPw9=-P*+$ zFLSVX;as*Vhsi%1@1rZPvj1z&$=77CnSYNSrvZL<7E%isJ^l*;ifN~S^J5BO@ELs_ z;QVZ2mendCoS&UI^uV8qmpj_x@s^ZOkQ$-DbISCQ-f4Ut@)n9;gUMs;<4hQ45D(`L z&^A(gD>Bg-uopU1={(Mu2T21NvHb$&vVG+7NJ^tXlnI=p`%*u=QUR7_zag^w!A<(7 z|9C4t4TAG?r8W2;4y_58+FDsQgyK7_B`|6n)Em8bF;OcrS@RFZk&yn6a?)2UDep1R;bmN7L`%r4PgbMe7(>)tObMJgvWB4jlRvFrQ5?2IkICnbpot zxY9iumMisr6^`zD;MZ6&P6UQ34pv7_BOnJA}pFoEiH%S9bo=dV=BUUEn3y_q`^)S>U@ z+Mctf%Y90O>lecqOv(%9=h)d;Tf72WgB}wyqY@}AP--*le@gwyUGR zQ1EIQJqS#qOSVJ_w0)RzEC1L2j~or8$E2&2U~MkSZ0O_R(OIeT5E=gsd?dxGx$xKuAKh+$yXtt})e? z-mffVrP9e?yuJIQ{p2rRK>Bb4mUnuwMX;LuC|*g@B)LYv7&Uc1vplmqGm%#8jMy&y zY;tb&ed*atCB}e=?wR$P!5`!h1(j{bchW94dehu`vX2nI_oqwktxt`Lcuw+%4bnxq z?Bj9{X#{kyXvP-wigauxsjL5MVVyLnn&MUMr)ST$7f;bjgluO;8iYl0oYm%w2FP?H z$%dB%kZe4kt!a{$6g}!lAZPR{Uazi1SOy<%D_5si>|u#wy@dRjokH#Ou!fs` zIb;pZtIokGq7BH@d7ENdEJpt$Hh$~u48DsTRA-ba|H0pQuk=o;)Tpi!q6+V{tQ8*K zUVVgZ&pX~e_ZIl6jcG#?+$hLN81Z|7f2D7h5+ZhS);al~!OYI74O^K-pN^cW%e$n; z^$sM8!0gWZ+6u|Oa+sCW@;GS!3wJ+n$)3n@Tkt^kacSlzYI_q08&i0Ey=JbL90jfP zj*9DSL;9D?I=6ft>X-c7z4^hW;i7v+ACQtCZe86*L6?kA0XIJ+N`W*YU6C9mm8uh! zl-0BohMnzs4o>{44dN;1Q`|?hE+gbef9AfX{ucI9nx#$PDUB-bnT)f!?Q}?7xe*Dv&LPWy#?***;b+>tF+QM(A@1n)q>>9%oVvy zQ2ddNPXZ?N4enW~R2N^Ao>G%sPbw!y2S$7Tkv5QB@+(!^ymrZy zpL3_{v`#cc8qrr%mO1lz`Bw*HeEX+gd|cZXXQZf|qc{Qw%m=0ZQlf}vuRh%|5J+n_ z3+tTTTzKHxUvq5V;Cke55Udnd*VrnUME(5X-TKd9wfzpCS+`^R)@e$v0uW!I?U-Da zldxqHX1P-7HM6snW&HZN6w6D$sfwRCTz#GA{ns1^#n7~$4E#rkyO*HAvO1E!9r7ae zEK`%EMc&yFU%xeN=*v?VCta!KbV38wjP4hbhjIvukXKU;;>&A`rSlxy+3UT|drgGC zcfk0k(&b4>)R_)W5b9MoxahxIHBonF0lfJIQw3nS(Mlq z2oB2)9~>G(ba3lO;Q-@)=f|v+^{;2I$@(;-dV097_Z&hqA_vI zWubf*y$qSlaUE`>S#+;e>Nr<K(~v%2nV`6x&OfH+8|fKxY^BI36O>v-S)KOUZGPu#NMPeH4kU^7Kytj!#MwC*Kfv9F!4Rhp!AYBnPlYob*&7uE^l>IuP?^Vgk;Z_DKRTSBb zX1?fjbkI|eHxiqU3Gt3wCv6k&w3wOcg3n$v)gw@>R3;$ZJA(i`&73hrbEGEal=(Qp zi=b+H^{OE|;+f?t*1dfi4~Ljq)x~7a$6*S5mx?ydxrUk5v#kdq_d$diRH!0Gx?u^& z&}k{B+DQG$X32r{>Gc ze>4iy8M74GNN)>!2l6#csH`w=CP)C|^+mtC%)DJe~Kq(#dz^Sp*;s z%Vu^u;xD)5g4t zt)G!^i6w|58M2?fkQpca0MQ)eNT-fOe1mO7+g&Od%_@AAV2l zYFtfdqt$fRU8AU?JL%s(i=R{5k$~*JVT~cq2zSV~%og1iF;XlI*9~%N&_K%9XWNV! zF<#+=#(*AP#xtq%!^a;slm%PbvYTG@H5XVf9vOY=om*z=z3whceyC$RtQct($&Cbx zAh$lpVcuQd3n{Fk2nFF-;r{Uu0N-_Qu^}4z&J$xQ@{q2F8}w1tv`)+#-RI{kL>4-Z z#*cm4zYIyU1hT{fx=fo;HI=}oPr^{3cP)QYXaTmle^;8Ihy+7182p$XL>{pHd&rLE z|2kcaQ;Z6i!B{87xtB zHg%zYw9K0$)qc#X5U-@|dCPS|+ESW`SUmzVXgp*}kC6KF5 zk`yaiFd=!uPwok4`8nnc2{P#fbs;%{XeUZ&T% zH>FRtxZ1TBWJ~tp)|S^vBknK;K4TBK!X+{CeYCBLXY5TV^c>s5u!78GI{V_AhHN(q z$NB==La<>4Z~9zU1Qs7V2l?6vv*Azre5Wwxj`4-W>D2|484OU+~l>gFI9 zynth8zTImk;wHY@zoKf7l|^Zz&-#7G3iOH->Z3Y(PsdI@Aa@Z)z+CFYf*-10&6!xh z>=Xbfy%*nvd`-=SJGd?%2HHn5R7hQrnB{YU-021Sy5tw`HYsRS{RmZky}?#NEw!{D zvu}2)!&S00;?@LnF&fx7T43fmwpM93IV-Pr=oVwDdC7Yaoa%bWR?U-AMX6nzzif2y z&W|k|`g9w)qvYTSA;9&zK4WYF08wq?wpdx9Bx0md5^ITib-y^flV6!PG}V2rR58AF z`~uROg4)@0e&%?JQC(ss6Fs#j{U+iTlx=cIg5SNW&5)JEXI?dbT3h9KQZV+M($V8f zzfI?w?<_`xbR!yAvE5)8WhP;{r7dpe{|KP~6YH6@KlnPKkH-45(A#b^Mt6sU1+%nDM$!mP z2facmhuK9}F|zW-7$Qz80;!W?aMb-KZ<=O`?86GS+Oq>$ypDjW#`ZeaC9y@+yBIri>@AO6_j}v+x)PG~u zPYpiW#f6Kuw8$d6F8EoCT9VI;`l)k{k|o;~;g9e|{z>*yMp^84{tcC?Sw(5Z-7&-y z?7PQ~xd?+!^~Du3YdI#y-*bq_MGCq#R%9nZWDli+3K-|x45P7qOujzN3vpI&bvxXn5#5T zxFB0+(XTFz!qU6~WU*iWwKfh?defh0lAP@!)dV;XcZ zLA>kbxWiz>xYIjMM|+Yh;>X7f(U)C_GC|#+UxBL&SaPqE1+UvlgIO62xglcPYGm}t zIfniC%#wZH9w7YhRi3;(40>Z5nCMm=Y*o-{1*7CNeJQpk9GabZ@9qz4rhf6-^L1Ay zd-pwJQPaikqGI`=n4>oy~1MAN87aQrvIAL zSx((3iiXhMpI2Fhp?~vPID_clzNKB^=47IJDS~)Ofl4YMXpb;&6)e-#>PV?1AL2|KQnn#w z7qM*~XQb5b{ur&>i+!2O?OzX7pzJ#HN!Xu^IpbnfJ7T0P4f8>3f_flf_IT;n&4?&p zd*6Hef;-})34U#joRZ9(KI+s7dCN?K{2aack@CnhNg%SJ(_`?(5Gz3`ZQzkdaP;MC zwI7ZBRwk$HB>cvy)CJ7HE0(QR2m#gkG;VUteteTuThV(@xui}b;d>^&mnt7(d%-v0 z`{xez3*9PW=LRrk-X?pCT1s-JXm!!Cx_*6Lhu!`lVQTkf71R}oH!&*TE^piqxqzH= znqEtKTMPj^sxE4oDU+|qn*$e$oF!NIHHCq+K>ABJ6OW>Aj|hQ$=ZwttZ+oi;hH8Ur zfi=MFKg6z7Tt_agpDQzut!|}nkvvIfwxJBU`Ke9$Zx3RT-k73(oG4vP#?j{+p)PZh z)FwEDs>=5vp8odl9nq^b_AyzGPSwTd3X7KIe$xh~&9x6C(JS3SD!Q=-3&DRvxYZDd zJQa}Z5x4}Rw_Oc2h%J5nj_bAg`Kj}mGU@ek*-3H^I~{GJu%&X@0I$lwY0 zL3?i^%=vz2PnkK|GLep{6LA|&0bVU4K~18aTaQTglcu*ZRFRSS@VL}vltV}vL|eU$ z*}!wU)C_*#rhX26AKpM%dJb)rR+JHxwBwRl(hWIOH(xD9FRP>I0!3Dm8i+?tdNnM- zl+a^H25&IOgS}c}5N7zfpui?`S!&kOzLl2A+6dH}^E4{?q)<-2@^!ZMkVVymV=g( z>v?LPf5ed+y#@D3-Q!4qbdWJ~X$z#-i|9t!Vd&a(M$@~gQ97RstcQ(XKk?uDST-`y zhlpQ%!B>4Z1Hs??hp5t1&Q0uR`Mv?!v0pR!f>)tg`JNggqp=iI6^{I1V=e+LG_SF< zrRhS3C``Ve<}S&4vIxk^D&wab)1K(26~t+H#F_Wd3xr=DK0Ib&L!FnfQ#*fgk(I+S zatmZUP&)~+!E1Ts>vXj;DX0_8oTmyIn)~Zh6Hk20ZDL_b2=Bowg`j;b^91y(z&kDc z!nyF+k=yN7p5(Qbqv`CJEmCv{Vd&Le(oAX_c7@eB&9-wc^&|5-mq@B2LTKxs`R}y0 zaME9BQ_v)WQ5{G3=RC#kaUL`H%GG{sbHz*Zt>}{(xBEyWC?qH$%SubK=P7}bP4c00 zW>eh_m>Ns=T+$Hv^b5^5W6(vf(K@!kW6VRsHz7&`u2g1#LX^0GUhcoIlA%m;7l%T3 z*hseiBxA8Z|4^rlyC{pfD#QMi>j~@-|8B&E6O@lF^d_WiHRcxdivG!5OA<3uujTJm zr5c>zhvl)}glq%UN+9@|)8zvs`U^P3!Fi&Zk!I;I1@%(3F}VBSOTJa_umQt>#tzE; zspK$Hx{~>d({&3OJC5rhUzgMXa-a$7G5Y;CMOr1OUC$dWCEv@-GoPP6NQzuhrnhhW z9wHxlD@L^l*aJ?aK=wV?G43NN-#Es{^<1yBzkyR4K~xp&nK^TK5(IbE?%RflW%^PeI=vn7wb|}p z`mkd&GP5-17eeU7Y{iDoM9P+vdRI!LakdXpv0#R?)oU^cUjzx`53#o?ljF~j0pl;< zaY5LJ)O*W+E?zww7yRrso+tZVk!SuBy>8Eix2ZJ!lID$}lqb5;oPstzP*guuTkPip z{swBd^CA1Yx3NoEt_fM#!9EamJx59rd=(2BQFKFkJ$n&II+Iz!UM>Z1;-y{DwYPJf ztu;k1g6;Y=XE}lk1Yj-Qh&&Y}9I{BNkAJ@ZM6_;|#-6|<_{CxttsWNzTY?1zZq|Km z6w3N88psUgG9{59A#4VL-x>lPWfBeW#%$RM3(wzdGTn~8b zof0u#G)$PeR>XW)q-cV(dH~I6s3hgI-cR{;dw%Dd)=4uX-_fiwC?`nyclXYt!Nr;X z5cVgxi8FF&)>mbWu~#q~1*pDTh~ZjdjQIjIviD8%B(iM%rjJTvisaUB4zQE!ifrZI zIJ;l`R{l>=kUU;TX(GS?j%aZNDNmzwH+8u8Ft8Z;7xK>_636`|On+RgRE!ki;Dv2wQL3SX1ad_tNKheCuYgkJ-K)-s8 zVi+I$MJxZBqb(P@DegE5@c25HAQy0^$Ok$K_u^bU*qBsM08htMl)L-OIFZ0VDe+B3 z``^5$gmK))13{B($bp^izwXWnE&n!-K zk^fSf_&oP5ML3PzD8lMyg{u~s>-dvZSMb_*_=j5F@OKId3je*4DBrg0supzcWV-aj6Cr&1Um-XLcmUV=6sJZ! z&!H-|psIU*0MhQ&CPM~@cATy#%GeciIJ-Goh=Q2+R2h6y7G=zJ1DJ)^@%LeA?{d5P z=u$YQ|0LP0{_&sG8Ok=8RUomZOq(MSgi$ZjjC%J$@qB$}huvQy0rz@EQ zVp$8ks1;faNIyLtaC%M7pNIBBCN%p_-s~OlPMtmA1@wkLa=P9k!)ztwt&pUsAp?#v z%L4je_%^eubXTCXKm!QkY9%7SleTk=J=@7We)cnn@ep)$%HQ=_ywmiw3db+QsH}egIOx7%oUc zS?R$oXc#33DO+RkjityitUD!Ge7P&B?+>In;DVs(X4%dGWmHe_E_>5)2_b^yzD%op zSL?3mzD7fjO}3AMw%I+>L1y~5iwKkL++G{{46Mp=Q8Gie4vp9xniSv@prH_ptic|& zWlFaH2lv%%N(Sfeehq317iTGDW-eJwt!bFvh^*v{9EaVQxZ{YaDniUDd_uRmcxE-2 zm(QA1lGcd1 zOe3}O0{aVQNGrTd#0uUXd~`4YpEr~u1=`;qA)FM-*9hE3wR?kjM(rXp;f(w&wa~7N zUV5-$Q=yuj-%dm1Fkz0V>Q!i8rB(>$3~kFDujpLU>@%DSY};GecOf0BsesxA1I!qN z@b|l)3Cssi%P_B>I@?6r-WO)<@eoDG>-$C$8g3(xd$35etwSuWn&?$nSoJM3myeIbP zC}{4anPro-MEON}1&fkX#k#qLjo$SZdYC#+)kdxlbqY}O{9&3c2c*KKU~(b0Vw@ah zwy$UT&6=s^s%I_-I3t@}z^o2@0Y--y5R-pR?_1=vu}|9P{$jR`cgN>4M(Y2Y44=k_?c8rqP{Fsnbs@dZdJEY~IP*E=9LShEtdGnX z0<@Ve->#EZ=nf0oRN?qa$uie)LD@{DP8ECMfoY%O$ZK^MNP|2|H(`VjUvff5Q#>gN zmRqCK>~*x=_pP0s^<2Lo!gE(XTlDR(%^u&*0^U<#Y|ZQlI+2pxl=d?l#&lP7zuaYJ z?!J*BCmjpuvyZonp&y7rBIB=Gd`6z7XorV-M6!R{C;rJ2=X>s&U8i)e_4FMT zY%aC!INKiF=n^EiK*|j0b7kABVb9Joe=OM-`iwU!qvH| zj)z(5xgXZO@YA~sYQzd~43I=~J4tA2#xUtS`WDZ;;hpY0TNyj@Mf;8bXbI5@cM2e& zf6ZyFd>_nEJeq@jM#o`Rmhnh`51%oIX4!-{_-RfTvUXsfUCOYZDg~9CI<;>taw=?B zC`wI6Q)FkOg-Z)_mN}ITC$zLfSBdS3(PM@;E*cVP_3K;IDmtHfr5{>9xf6du|uC3_Y z-PGaOP`SrB?d5lrQCpSwvr2`gfK8EU-E8)C?H()<^o2)IPy0zZPwy$Oiqv;hiSZu(K~ z&=j_!2mh6@nls!Fmi;rRP``p-;~^hbNERw$V9%dl;r2YHSO064EB%zTmh==}eajS< zNGuo3NZ?F1$)hkZG$9Zaeh|7KUyC7l86Z;91QMH1$XVMk05BM91q$L@=0^^yE5M$t z?^i@Wa>GNl=g_QY)gNX_?f;$s$p1TrOXl=6v%nl^z-7nH_3;MAVpEbNw1S{aBfRin zZ*U3=|AsmTj0NOMvV182{C6Bu%jLX7~CvSNdYkw#X{>Q!+Fh5o6Q^2 zrrF01Cbl_E-L5a53NH!#d&c1PCGxAY;ggdGB~MT(|7*@%fB7-FP6$Tr+njLZs}1R> zZTuR(BHaEwg3d*j(JU?IAXbEY+YyCiT$X`48DFPSA_^a-jwWU}ss&seHNx&!b|}{h z4%jnmXX({tP&f7nCOAIfmhb5gGZg)3{?(wbD9FJX;YFYGo(J5tW^5uG5FDT3LtwFrbgvPJKplvkTdIO-L6j-pYMJsbsm(>oI4iqgS*FA|R@2 zCdVkZS>ubZe6J3HiLyg_J*sWXHw*{=GG3R1WxDdJn) zA^i?Tg^Sfne2iHefzKTAFF|?%uc4S=Ne5+oEW^_VWTl zB+W7tt*8u4k2d|)AG-1j0t^+sqN&t3afuyJQ%*CKLA8DyKcXOwkiT#ywq|zEOhN>i zAd8WbK;&Z=?Wp8VSgPmD_2&L&cEgKlw*7}|qtv@`EE*8uW%w7)!bw6bh=5=Yl4#48 zr_GnJealKNJKL&H+^)L1iu2RdUvtP&7@YcuEi?!36~-K- zxBss>gcO``Mk>Z5ZLgEYt^#lP^TJ@sFuv$%D^FC~Uq!gRvU709j~-e1F=ol}XA}a% zjzY+B)n@edx#a>-&_Azx)i)g_mpxH=eem4)>di;Xqr+SRE`Y82{({*D=7&-*T**v+ zz|$z3n&!W$O!H*c?|EhOD{pgd=H}vYW3km@o?j0lQlc5)+t5+@$#5OPvM7A0337w8 z^QSe&o-S*EekqtGmQLT}g{Y*2bv52SVe?sZ{?mY-R!5#+ib-)TNE~?0+Kvlw`Tr9E zW=s)Cd`G;^6OT+vy?#YG-H(kbj(>qckISguL7evq^&tn>UaPj3=N8OCERZ!cWnU?= zTltRp`cp0z9#@6T2$wK@HBAp?1%Lp65`aD1(+|+@F$~o@9K)P?f9cgrh*i#8ylQ82BL|gODqKsz) zyzm0!YGviR^E45gG5D2|iI3QN5vZ2#r&o7$Zi>iEC3=nQdQlSM}$pJi1)#4NJ1#{I2b zB6l^c_*FwM=TdvZlG4sC{fbs!e7hueo&T%x8goM~=7ms~YPkIHWwgL5IYM#zimh&K zZ4xKK;PPq39ORI>iNvy;$gAsW=PggU>?#D3Y;v1UL1|us$*JHELZtid+L_Gd$s7Y5 z0^YK<=DP<1^XnyfRgMd9O@y>vA5tkuZHgVuy?LHGm0K{@KLTO+Y1&mq67ey64O;8J zt1Zd5`tDV^eA_fM$=OahDN-xQe7XwkJ%89<_TtGNbfa7FmCSLg)S>K)aNEDT>+p+<;TM~fcH7Uu}e)Bd* zQWI*rHZAL*t9Q_|d_`g1(RqXdZcQDBXWP?o3*Yw8 zHPq&DQ{BPB`{5zw8w<5z>ch8dU_p88WcXg&kPq+CI=m7>iV5~7j#(xjaV7CmstLK2 zJCn8qe`3WWqr8BOLE>}k1!>x2O z+x`WJx6F4gs?EDP4h04DzHP4JKFMC1sU;HV6785V(5}kPhKD%9%^JscL)PyAQJ_U1 zE!8DXZbrMvCAm?e19hs2O9%H{d->9xHpdy|84O+jygc4p5ZF9oT+r^>4mh{oVadk3}eKLAX6y^mz694t}eewUnt~Rf+ ztbu6GQUDrRB}ziu4HTN=X9H1*@pBi?@n6^9&KOHAS*E)k>!2SdL##HB)SEwx?8m_E zK9s_IO$&xiLr|`C?z>Jc$%a%(Lz#N(lg&++@)N&>ik_T5c6xuKiNPRU#$`s*)Py>c zh}-!@^{PvGg^@3LLwi-ej+?%;|Aljhx0m!H3U{JefJ(7?Ce%g~2s3NRgA~ks7^=$? z`@y8GwxT2k#`I7q9WJ@v^21C6!RV;>my2uFyhfqXvO0x&M($jYRipgEpM1P9x}&0u zh=;0@E8+$i-0nmAk> z6+P#~#h-FL{wijqwvzmtmRL{_@3CQ#-{{z9R&6mS+P!Md@mbFJ1htJ@ zQ^-(ao6*eC&=+s5*UzoIrop;R>hI8@7z3Q$L20s2J(udASHW_0t&4ta?3nAnK82R` z`cTr5wTe_~D<^(No+LXD@0^aEK$W|lh!HqZqTs}okW!P&&Nd(U?BcXPr8m;Gch3u$ zmAC72V@eML-MmmVzdMt$V#v`llBSDvE4HtVu5$`6jx$J)+I7KhtRx#C2IACkclJW3 z7SkQCJUTZw8gw=vYkGCIH17$ibX}uS@0kf#wHdD-BB~!V`Yf%^t4nahzLlj?{ocvG zMe`d`{%x~uKPAED3s&qtcV?I3KH@=LjDMjl-qo;SfVHA3vqHsjnCHl;KNp;T$+?tP zD1R@2*y9GdTu^{uDz;VZAJ7{wQL)Ug#m9X@V=B>=oeR;(RGPKosiBRQ(Cqs@>cw5o<_8|Ty*<#OdgN2) zSSH2~=m?tvdcLLNL5woo{iLDd(N*JmGd@uz*Ds35297ImBDyKy zY|FebCj{yx5WG&re$Kxj4ks@J3c(Si1+Vxw;tGJK95KM2{ucM5&_ ze~mP`)Jx>}61g<9d+G-5=dSg}-HZ@}i|0qiwou2StnQxFFYdg)Mk0TiqOcV_}E(cSIj1xu>{Smq%V@rPl%#vXLk&07A9?P z@CxwIwa`0al1T)4ciA}^gq*ZGH4Z0ppzjc>rQ#J8>zNgVtaXkOzN#~rOeb-p6 zG=U%Ojqmo@?x0A$gY`eH-$@H^=tb*;JsBJ@Nul zIRbhCRk2G4?|Lv+VGC2yH|522zPIt$OV2?ETCCF>*AB|(O4phke)6~N+QBO2hXwC* z92a(sMyeR&W{2Gd7*Vuik_MRM15Q`pWs_AT!wnA84#YENrz{X{yxh&ybcv=c@)w=WDS303?WCK3 zL2gz-7^RKIjL13R94C@zY+FS+Qh=1}G9q|zy}o`MKXI(FVD}d*nMr~D;w_}eHEZG$ zhr_RP5QLv+@+<&=KO+_~` zMF-egduWc#(C5vx_Gmzr4snVaI>)fAQ5YP-Im&S*wxySoa!KX;B}Vt@EY_7;UOXrB zPzWi%-Fq!V@$fF$llipa8Z!zCFagh_^+@lO8VWB~_i`rhgWk1nPJSboiJVbhEJnHD~@>4Fd+{I>d(zy^TXO~WU zD5m8kU&7VmhI^xazmom-NHa(lXM#q~3Q506Rf1F!7MogbWEHk*QSv&fi=Q+N87r^K z#D_EbTl|QD*i$INHSo^+hvf^XWT>e11%o|1Nyiy$61j$+Onu7sC13F}~l^mFe#@7ruL}>|%4GrcpuXO2GmOaJ4Qj>r1F!BR;gqM=;wyZ<)3$R9RBQQQ}MIBPE>h@2#5MiK*Y0cC zXYCoI7>MnRW_3K@^aX>kWL}KoMTxO+@rbF;@p%ughM&MIL}&J zv;W=C-%8rTy=;EBP!~@*ZZYg9s3TpuoHeF)X$@(#A0-#=c1eE{$uBZx#SoHpbc`WA z52}M=p};P?F2V0h8V)O-^YGo zRzkuWuY@OCq(}1nGCg@Wv&~vM+Os$3zQwm(7YSB6Hdo1#PuX5f_dRi+7%xv9y3gz2A8M>y8V&u6 zKFm_~a=2G#0dp`p9ASYny1k978{Z|_%LDRCsTW+Q*D6FwFK(thd3ngYL>|Y~kb~;?Dxa^YV9epQvYCLQ3we=zUpKajbE{3&den=n>nD`_Q#;RX`pFrVnvle)o&+dYzdJ_=NdGH{u_ zbNWZaF|(y>X1;^N4A$v>ij=IlWz3nm+&nz`_b{VG9T;XLKM08jsyn7EJE?eK>MYlx z{qlvr5!J2W9morM>E1MOZ{N#l_VLQ`vTd$oiB8uBG+@GqivpskSxUG%$%7E4$tW5 zi(+LDei}R*Jc^&NEGTJP?L9r*S9|fI0vM(thcJs~+Bx~ALHf$@ZpZ-3G#`&9`flic zqsLPARfP|&`sjpuCF0s(6+LV7h zC4*HjZ$177Up2+71E`B7dx9p(4bYEhMR#jjlEGe!7lW+*rPOegAz1{(T1ieFpx02L69=2EO~N G?f(Kus+KSS literal 0 HcmV?d00001 diff --git a/openvidu-recording-node/public/index.html b/openvidu-recording-node/public/index.html new file mode 100644 index 00000000..244e6c2e --- /dev/null +++ b/openvidu-recording-node/public/index.html @@ -0,0 +1,99 @@ + + + + openvidu-recording-node + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+

Join a video session

+
+

+ + +

+

+ +

+
+
+
+
+ + +
+ +
+
+
OpenVidu © 2017
+ + + +
+
+ + + + \ No newline at end of file diff --git a/openvidu-recording-node/public/openvidu-browser-1.8.0.js b/openvidu-recording-node/public/openvidu-browser-1.8.0.js new file mode 100644 index 00000000..16abfc5a --- /dev/null +++ b/openvidu-recording-node/public/openvidu-browser-1.8.0.js @@ -0,0 +1,15134 @@ +(function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + if (typeof console.trace === 'function') { + // not supported in IE 10 + console.trace(); + } + } + } + + return this; +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.once = function(type, listener) { + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + var fired = false; + + function g() { + this.removeListener(type, g); + + if (!fired) { + fired = true; + listener.apply(this, arguments); + } + } + + g.listener = listener; + this.on(type, g); + + return this; +}; + +// emits a 'removeListener' event iff the listener was removed +EventEmitter.prototype.removeListener = function(type, listener) { + var list, position, length, i; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events || !this._events[type]) + return this; + + list = this._events[type]; + length = list.length; + position = -1; + + if (list === listener || + (isFunction(list.listener) && list.listener === listener)) { + delete this._events[type]; + if (this._events.removeListener) + this.emit('removeListener', type, listener); + + } else if (isObject(list)) { + for (i = length; i-- > 0;) { + if (list[i] === listener || + (list[i].listener && list[i].listener === listener)) { + position = i; + break; + } + } + + if (position < 0) + return this; + + if (list.length === 1) { + list.length = 0; + delete this._events[type]; + } else { + list.splice(position, 1); + } + + if (this._events.removeListener) + this.emit('removeListener', type, listener); + } + + return this; +}; + +EventEmitter.prototype.removeAllListeners = function(type) { + var key, listeners; + + if (!this._events) + return this; + + // not listening for removeListener, no need to emit + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {}; + else if (this._events[type]) + delete this._events[type]; + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + for (key in this._events) { + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = {}; + return this; + } + + listeners = this._events[type]; + + if (isFunction(listeners)) { + this.removeListener(type, listeners); + } else if (listeners) { + // LIFO order + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]); + } + delete this._events[type]; + + return this; +}; + +EventEmitter.prototype.listeners = function(type) { + var ret; + if (!this._events || !this._events[type]) + ret = []; + else if (isFunction(this._events[type])) + ret = [this._events[type]]; + else + ret = this._events[type].slice(); + return ret; +}; + +EventEmitter.prototype.listenerCount = function(type) { + if (this._events) { + var evlistener = this._events[type]; + + if (isFunction(evlistener)) + return 1; + else if (evlistener) + return evlistener.length; + } + return 0; +}; + +EventEmitter.listenerCount = function(emitter, type) { + return emitter.listenerCount(type); +}; + +function isFunction(arg) { + return typeof arg === 'function'; +} + +function isNumber(arg) { + return typeof arg === 'number'; +} + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} + +function isUndefined(arg) { + return arg === void 0; +} + +},{}],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 = module.exports = 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; +}; + +},{"./stun.json":3,"./turn.json":4,"normalice":8}],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", + "stun.services.mozilla.com" +] + +},{}],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; + + //Setup Audio Context + if (!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.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) { + 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) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],7:[function(require,module,exports){ +/*! + * @name JavaScript/NodeJS Merge v1.2.0 + * @author yeikos + * @repository https://github.com/yeikos/js.merge + + * Copyright 2014 yeikos - MIT license + * https://raw.github.com/yeikos/js.merge/master/LICENSE + */ + +;(function(isNode) { + + /** + * Merge one or more objects + * @param bool? clone + * @param mixed,... arguments + * @return object + */ + + var Public = function(clone) { + + return merge(clone === true, false, arguments); + + }, publicName = 'merge'; + + /** + * Merge two or more objects recursively + * @param bool? clone + * @param mixed,... arguments + * @return object + */ + + Public.recursive = function(clone) { + + return merge(clone === true, true, arguments); + + }; + + /** + * Clone the input removing any reference + * @param mixed input + * @return mixed + */ + + Public.clone = function(input) { + + var output = input, + type = typeOf(input), + index, size; + + if (type === 'array') { + + output = []; + size = input.length; + + for (index=0;index 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; +}; + +},{}],9:[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; }; + +},{}],10:[function(require,module,exports){ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ +'use strict'; + +var SDPUtils = require('sdp'); + +function writeMediaSection(transceiver, caps, type, stream, dtlsRole) { + var sdp = SDPUtils.writeRtpDescription(transceiver.kind, caps); + + // Map ICE parameters (ufrag, pwd) to SDP. + sdp += SDPUtils.writeIceParameters( + transceiver.iceGatherer.getLocalParameters()); + + // Map DTLS parameters to SDP. + sdp += SDPUtils.writeDtlsParameters( + transceiver.dtlsTransport.getLocalParameters(), + type === 'offer' ? 'actpass' : dtlsRole || 'active'); + + sdp += 'a=mid:' + transceiver.mid + '\r\n'; + + if (transceiver.rtpSender && transceiver.rtpReceiver) { + sdp += 'a=sendrecv\r\n'; + } else if (transceiver.rtpSender) { + sdp += 'a=sendonly\r\n'; + } else if (transceiver.rtpReceiver) { + sdp += 'a=recvonly\r\n'; + } else { + sdp += 'a=inactive\r\n'; + } + + if (transceiver.rtpSender) { + var trackId = transceiver.rtpSender._initialTrackId || + transceiver.rtpSender.track.id; + transceiver.rtpSender._initialTrackId = trackId; + // spec. + var msid = 'msid:' + (stream ? stream.id : '-') + ' ' + + trackId + '\r\n'; + sdp += 'a=' + msid; + // for Chrome. Legacy should no longer be required. + sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc + + ' ' + msid; + + // RTX + if (transceiver.sendEncodingParameters[0].rtx) { + sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc + + ' ' + msid; + sdp += 'a=ssrc-group:FID ' + + transceiver.sendEncodingParameters[0].ssrc + ' ' + + transceiver.sendEncodingParameters[0].rtx.ssrc + + '\r\n'; + } + } + // FIXME: this should be written by writeRtpDescription. + sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc + + ' cname:' + SDPUtils.localCName + '\r\n'; + if (transceiver.rtpSender && transceiver.sendEncodingParameters[0].rtx) { + sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc + + ' cname:' + SDPUtils.localCName + '\r\n'; + } + return sdp; +} + +// Edge does not like +// 1) stun: filtered after 14393 unless ?transport=udp is present +// 2) turn: that does not have all of turn:host:port?transport=udp +// 3) turn: with ipv6 addresses +// 4) turn: occurring muliple times +function filterIceServers(iceServers, edgeVersion) { + var hasTurn = false; + iceServers = JSON.parse(JSON.stringify(iceServers)); + return iceServers.filter(function(server) { + if (server && (server.urls || server.url)) { + var urls = server.urls || server.url; + if (server.url && !server.urls) { + console.warn('RTCIceServer.url is deprecated! Use urls instead.'); + } + var isString = typeof urls === 'string'; + if (isString) { + urls = [urls]; + } + urls = urls.filter(function(url) { + var validTurn = url.indexOf('turn:') === 0 && + url.indexOf('transport=udp') !== -1 && + url.indexOf('turn:[') === -1 && + !hasTurn; + + if (validTurn) { + hasTurn = true; + return true; + } + return url.indexOf('stun:') === 0 && edgeVersion >= 14393 && + url.indexOf('?transport=udp') === -1; + }); + + delete server.url; + server.urls = isString ? urls[0] : urls; + return !!urls.length; + } + }); +} + +// Determines the intersection of local and remote capabilities. +function getCommonCapabilities(localCapabilities, remoteCapabilities) { + var commonCapabilities = { + codecs: [], + headerExtensions: [], + fecMechanisms: [] + }; + + var findCodecByPayloadType = function(pt, codecs) { + pt = parseInt(pt, 10); + for (var i = 0; i < codecs.length; i++) { + if (codecs[i].payloadType === pt || + codecs[i].preferredPayloadType === pt) { + return codecs[i]; + } + } + }; + + var rtxCapabilityMatches = function(lRtx, rRtx, lCodecs, rCodecs) { + var lCodec = findCodecByPayloadType(lRtx.parameters.apt, lCodecs); + var rCodec = findCodecByPayloadType(rRtx.parameters.apt, rCodecs); + return lCodec && rCodec && + lCodec.name.toLowerCase() === rCodec.name.toLowerCase(); + }; + + localCapabilities.codecs.forEach(function(lCodec) { + for (var i = 0; i < remoteCapabilities.codecs.length; i++) { + var rCodec = remoteCapabilities.codecs[i]; + if (lCodec.name.toLowerCase() === rCodec.name.toLowerCase() && + lCodec.clockRate === rCodec.clockRate) { + if (lCodec.name.toLowerCase() === 'rtx' && + lCodec.parameters && rCodec.parameters.apt) { + // for RTX we need to find the local rtx that has a apt + // which points to the same local codec as the remote one. + if (!rtxCapabilityMatches(lCodec, rCodec, + localCapabilities.codecs, remoteCapabilities.codecs)) { + continue; + } + } + rCodec = JSON.parse(JSON.stringify(rCodec)); // deepcopy + // number of channels is the highest common number of channels + rCodec.numChannels = Math.min(lCodec.numChannels, + rCodec.numChannels); + // push rCodec so we reply with offerer payload type + commonCapabilities.codecs.push(rCodec); + + // determine common feedback mechanisms + rCodec.rtcpFeedback = rCodec.rtcpFeedback.filter(function(fb) { + for (var j = 0; j < lCodec.rtcpFeedback.length; j++) { + if (lCodec.rtcpFeedback[j].type === fb.type && + lCodec.rtcpFeedback[j].parameter === fb.parameter) { + return true; + } + } + return false; + }); + // FIXME: also need to determine .parameters + // see https://github.com/openpeer/ortc/issues/569 + break; + } + } + }); + + localCapabilities.headerExtensions.forEach(function(lHeaderExtension) { + for (var i = 0; i < remoteCapabilities.headerExtensions.length; + i++) { + var rHeaderExtension = remoteCapabilities.headerExtensions[i]; + if (lHeaderExtension.uri === rHeaderExtension.uri) { + commonCapabilities.headerExtensions.push(rHeaderExtension); + break; + } + } + }); + + // FIXME: fecMechanisms + return commonCapabilities; +} + +// is action=setLocalDescription with type allowed in signalingState +function isActionAllowedInSignalingState(action, type, signalingState) { + return { + offer: { + setLocalDescription: ['stable', 'have-local-offer'], + setRemoteDescription: ['stable', 'have-remote-offer'] + }, + answer: { + setLocalDescription: ['have-remote-offer', 'have-local-pranswer'], + setRemoteDescription: ['have-local-offer', 'have-remote-pranswer'] + } + }[type][action].indexOf(signalingState) !== -1; +} + +function maybeAddCandidate(iceTransport, candidate) { + // Edge's internal representation adds some fields therefore + // not all fieldѕ are taken into account. + var alreadyAdded = iceTransport.getRemoteCandidates() + .find(function(remoteCandidate) { + return candidate.foundation === remoteCandidate.foundation && + candidate.ip === remoteCandidate.ip && + candidate.port === remoteCandidate.port && + candidate.priority === remoteCandidate.priority && + candidate.protocol === remoteCandidate.protocol && + candidate.type === remoteCandidate.type; + }); + if (!alreadyAdded) { + iceTransport.addRemoteCandidate(candidate); + } + return !alreadyAdded; +} + + +function makeError(name, description) { + var e = new Error(description); + e.name = name; + // legacy error codes from https://heycam.github.io/webidl/#idl-DOMException-error-names + e.code = { + NotSupportedError: 9, + InvalidStateError: 11, + InvalidAccessError: 15, + TypeError: undefined, + OperationError: undefined + }[name]; + return e; +} + +module.exports = function(window, edgeVersion) { + // https://w3c.github.io/mediacapture-main/#mediastream + // Helper function to add the track to the stream and + // dispatch the event ourselves. + function addTrackToStreamAndFireEvent(track, stream) { + stream.addTrack(track); + stream.dispatchEvent(new window.MediaStreamTrackEvent('addtrack', + {track: track})); + } + + function removeTrackFromStreamAndFireEvent(track, stream) { + stream.removeTrack(track); + stream.dispatchEvent(new window.MediaStreamTrackEvent('removetrack', + {track: track})); + } + + function fireAddTrack(pc, track, receiver, streams) { + var trackEvent = new Event('track'); + trackEvent.track = track; + trackEvent.receiver = receiver; + trackEvent.transceiver = {receiver: receiver}; + trackEvent.streams = streams; + window.setTimeout(function() { + pc._dispatchEvent('track', trackEvent); + }); + } + + var RTCPeerConnection = function(config) { + var pc = this; + + var _eventTarget = document.createDocumentFragment(); + ['addEventListener', 'removeEventListener', 'dispatchEvent'] + .forEach(function(method) { + pc[method] = _eventTarget[method].bind(_eventTarget); + }); + + this.canTrickleIceCandidates = null; + + this.needNegotiation = false; + + this.localStreams = []; + this.remoteStreams = []; + + this.localDescription = null; + this.remoteDescription = null; + + this.signalingState = 'stable'; + this.iceConnectionState = 'new'; + this.connectionState = 'new'; + this.iceGatheringState = 'new'; + + config = JSON.parse(JSON.stringify(config || {})); + + this.usingBundle = config.bundlePolicy === 'max-bundle'; + if (config.rtcpMuxPolicy === 'negotiate') { + throw(makeError('NotSupportedError', + 'rtcpMuxPolicy \'negotiate\' is not supported')); + } else if (!config.rtcpMuxPolicy) { + config.rtcpMuxPolicy = 'require'; + } + + switch (config.iceTransportPolicy) { + case 'all': + case 'relay': + break; + default: + config.iceTransportPolicy = 'all'; + break; + } + + switch (config.bundlePolicy) { + case 'balanced': + case 'max-compat': + case 'max-bundle': + break; + default: + config.bundlePolicy = 'balanced'; + break; + } + + config.iceServers = filterIceServers(config.iceServers || [], edgeVersion); + + this._iceGatherers = []; + if (config.iceCandidatePoolSize) { + for (var i = config.iceCandidatePoolSize; i > 0; i--) { + this._iceGatherers.push(new window.RTCIceGatherer({ + iceServers: config.iceServers, + gatherPolicy: config.iceTransportPolicy + })); + } + } else { + config.iceCandidatePoolSize = 0; + } + + this._config = config; + + // per-track iceGathers, iceTransports, dtlsTransports, rtpSenders, ... + // everything that is needed to describe a SDP m-line. + this.transceivers = []; + + this._sdpSessionId = SDPUtils.generateSessionId(); + this._sdpSessionVersion = 0; + + this._dtlsRole = undefined; // role for a=setup to use in answers. + + this._isClosed = false; + }; + + // set up event handlers on prototype + RTCPeerConnection.prototype.onicecandidate = null; + RTCPeerConnection.prototype.onaddstream = null; + RTCPeerConnection.prototype.ontrack = null; + RTCPeerConnection.prototype.onremovestream = null; + RTCPeerConnection.prototype.onsignalingstatechange = null; + RTCPeerConnection.prototype.oniceconnectionstatechange = null; + RTCPeerConnection.prototype.onconnectionstatechange = null; + RTCPeerConnection.prototype.onicegatheringstatechange = null; + RTCPeerConnection.prototype.onnegotiationneeded = null; + RTCPeerConnection.prototype.ondatachannel = null; + + RTCPeerConnection.prototype._dispatchEvent = function(name, event) { + if (this._isClosed) { + return; + } + this.dispatchEvent(event); + if (typeof this['on' + name] === 'function') { + this['on' + name](event); + } + }; + + RTCPeerConnection.prototype._emitGatheringStateChange = function() { + var event = new Event('icegatheringstatechange'); + this._dispatchEvent('icegatheringstatechange', event); + }; + + RTCPeerConnection.prototype.getConfiguration = function() { + return this._config; + }; + + RTCPeerConnection.prototype.getLocalStreams = function() { + return this.localStreams; + }; + + RTCPeerConnection.prototype.getRemoteStreams = function() { + return this.remoteStreams; + }; + + // internal helper to create a transceiver object. + // (which is not yet the same as the WebRTC 1.0 transceiver) + RTCPeerConnection.prototype._createTransceiver = function(kind, doNotAdd) { + var hasBundleTransport = this.transceivers.length > 0; + var transceiver = { + track: null, + iceGatherer: null, + iceTransport: null, + dtlsTransport: null, + localCapabilities: null, + remoteCapabilities: null, + rtpSender: null, + rtpReceiver: null, + kind: kind, + mid: null, + sendEncodingParameters: null, + recvEncodingParameters: null, + stream: null, + associatedRemoteMediaStreams: [], + wantReceive: true + }; + if (this.usingBundle && hasBundleTransport) { + transceiver.iceTransport = this.transceivers[0].iceTransport; + transceiver.dtlsTransport = this.transceivers[0].dtlsTransport; + } else { + var transports = this._createIceAndDtlsTransports(); + transceiver.iceTransport = transports.iceTransport; + transceiver.dtlsTransport = transports.dtlsTransport; + } + if (!doNotAdd) { + this.transceivers.push(transceiver); + } + return transceiver; + }; + + RTCPeerConnection.prototype.addTrack = function(track, stream) { + if (this._isClosed) { + throw makeError('InvalidStateError', + 'Attempted to call addTrack on a closed peerconnection.'); + } + + var alreadyExists = this.transceivers.find(function(s) { + return s.track === track; + }); + + if (alreadyExists) { + throw makeError('InvalidAccessError', 'Track already exists.'); + } + + var transceiver; + for (var i = 0; i < this.transceivers.length; i++) { + if (!this.transceivers[i].track && + this.transceivers[i].kind === track.kind) { + transceiver = this.transceivers[i]; + } + } + if (!transceiver) { + transceiver = this._createTransceiver(track.kind); + } + + this._maybeFireNegotiationNeeded(); + + if (this.localStreams.indexOf(stream) === -1) { + this.localStreams.push(stream); + } + + transceiver.track = track; + transceiver.stream = stream; + transceiver.rtpSender = new window.RTCRtpSender(track, + transceiver.dtlsTransport); + return transceiver.rtpSender; + }; + + RTCPeerConnection.prototype.addStream = function(stream) { + var pc = this; + if (edgeVersion >= 15025) { + stream.getTracks().forEach(function(track) { + pc.addTrack(track, stream); + }); + } else { + // Clone is necessary for local demos mostly, attaching directly + // to two different senders does not work (build 10547). + // Fixed in 15025 (or earlier) + var clonedStream = stream.clone(); + stream.getTracks().forEach(function(track, idx) { + var clonedTrack = clonedStream.getTracks()[idx]; + track.addEventListener('enabled', function(event) { + clonedTrack.enabled = event.enabled; + }); + }); + clonedStream.getTracks().forEach(function(track) { + pc.addTrack(track, clonedStream); + }); + } + }; + + RTCPeerConnection.prototype.removeTrack = function(sender) { + if (this._isClosed) { + throw makeError('InvalidStateError', + 'Attempted to call removeTrack on a closed peerconnection.'); + } + + if (!(sender instanceof window.RTCRtpSender)) { + throw new TypeError('Argument 1 of RTCPeerConnection.removeTrack ' + + 'does not implement interface RTCRtpSender.'); + } + + var transceiver = this.transceivers.find(function(t) { + return t.rtpSender === sender; + }); + + if (!transceiver) { + throw makeError('InvalidAccessError', + 'Sender was not created by this connection.'); + } + var stream = transceiver.stream; + + transceiver.rtpSender.stop(); + transceiver.rtpSender = null; + transceiver.track = null; + transceiver.stream = null; + + // remove the stream from the set of local streams + var localStreams = this.transceivers.map(function(t) { + return t.stream; + }); + if (localStreams.indexOf(stream) === -1 && + this.localStreams.indexOf(stream) > -1) { + this.localStreams.splice(this.localStreams.indexOf(stream), 1); + } + + this._maybeFireNegotiationNeeded(); + }; + + RTCPeerConnection.prototype.removeStream = function(stream) { + var pc = this; + stream.getTracks().forEach(function(track) { + var sender = pc.getSenders().find(function(s) { + return s.track === track; + }); + if (sender) { + pc.removeTrack(sender); + } + }); + }; + + RTCPeerConnection.prototype.getSenders = function() { + return this.transceivers.filter(function(transceiver) { + return !!transceiver.rtpSender; + }) + .map(function(transceiver) { + return transceiver.rtpSender; + }); + }; + + RTCPeerConnection.prototype.getReceivers = function() { + return this.transceivers.filter(function(transceiver) { + return !!transceiver.rtpReceiver; + }) + .map(function(transceiver) { + return transceiver.rtpReceiver; + }); + }; + + + RTCPeerConnection.prototype._createIceGatherer = function(sdpMLineIndex, + usingBundle) { + var pc = this; + if (usingBundle && sdpMLineIndex > 0) { + return this.transceivers[0].iceGatherer; + } else if (this._iceGatherers.length) { + return this._iceGatherers.shift(); + } + var iceGatherer = new window.RTCIceGatherer({ + iceServers: this._config.iceServers, + gatherPolicy: this._config.iceTransportPolicy + }); + Object.defineProperty(iceGatherer, 'state', + {value: 'new', writable: true} + ); + + this.transceivers[sdpMLineIndex].bufferedCandidateEvents = []; + this.transceivers[sdpMLineIndex].bufferCandidates = function(event) { + var end = !event.candidate || Object.keys(event.candidate).length === 0; + // polyfill since RTCIceGatherer.state is not implemented in + // Edge 10547 yet. + iceGatherer.state = end ? 'completed' : 'gathering'; + if (pc.transceivers[sdpMLineIndex].bufferedCandidateEvents !== null) { + pc.transceivers[sdpMLineIndex].bufferedCandidateEvents.push(event); + } + }; + iceGatherer.addEventListener('localcandidate', + this.transceivers[sdpMLineIndex].bufferCandidates); + return iceGatherer; + }; + + // start gathering from an RTCIceGatherer. + RTCPeerConnection.prototype._gather = function(mid, sdpMLineIndex) { + var pc = this; + var iceGatherer = this.transceivers[sdpMLineIndex].iceGatherer; + if (iceGatherer.onlocalcandidate) { + return; + } + var bufferedCandidateEvents = + this.transceivers[sdpMLineIndex].bufferedCandidateEvents; + this.transceivers[sdpMLineIndex].bufferedCandidateEvents = null; + iceGatherer.removeEventListener('localcandidate', + this.transceivers[sdpMLineIndex].bufferCandidates); + iceGatherer.onlocalcandidate = function(evt) { + if (pc.usingBundle && sdpMLineIndex > 0) { + // if we know that we use bundle we can drop candidates with + // ѕdpMLineIndex > 0. If we don't do this then our state gets + // confused since we dispose the extra ice gatherer. + return; + } + var event = new Event('icecandidate'); + event.candidate = {sdpMid: mid, sdpMLineIndex: sdpMLineIndex}; + + var cand = evt.candidate; + // Edge emits an empty object for RTCIceCandidateComplete‥ + var end = !cand || Object.keys(cand).length === 0; + if (end) { + // polyfill since RTCIceGatherer.state is not implemented in + // Edge 10547 yet. + if (iceGatherer.state === 'new' || iceGatherer.state === 'gathering') { + iceGatherer.state = 'completed'; + } + } else { + if (iceGatherer.state === 'new') { + iceGatherer.state = 'gathering'; + } + // RTCIceCandidate doesn't have a component, needs to be added + cand.component = 1; + var serializedCandidate = SDPUtils.writeCandidate(cand); + event.candidate = Object.assign(event.candidate, + SDPUtils.parseCandidate(serializedCandidate)); + event.candidate.candidate = serializedCandidate; + } + + // update local description. + var sections = SDPUtils.getMediaSections(pc.localDescription.sdp); + if (!end) { + sections[event.candidate.sdpMLineIndex] += + 'a=' + event.candidate.candidate + '\r\n'; + } else { + sections[event.candidate.sdpMLineIndex] += + 'a=end-of-candidates\r\n'; + } + pc.localDescription.sdp = + SDPUtils.getDescription(pc.localDescription.sdp) + + sections.join(''); + var complete = pc.transceivers.every(function(transceiver) { + return transceiver.iceGatherer && + transceiver.iceGatherer.state === 'completed'; + }); + + if (pc.iceGatheringState !== 'gathering') { + pc.iceGatheringState = 'gathering'; + pc._emitGatheringStateChange(); + } + + // Emit candidate. Also emit null candidate when all gatherers are + // complete. + if (!end) { + pc._dispatchEvent('icecandidate', event); + } + if (complete) { + pc._dispatchEvent('icecandidate', new Event('icecandidate')); + pc.iceGatheringState = 'complete'; + pc._emitGatheringStateChange(); + } + }; + + // emit already gathered candidates. + window.setTimeout(function() { + bufferedCandidateEvents.forEach(function(e) { + iceGatherer.onlocalcandidate(e); + }); + }, 0); + }; + + // Create ICE transport and DTLS transport. + RTCPeerConnection.prototype._createIceAndDtlsTransports = function() { + var pc = this; + var iceTransport = new window.RTCIceTransport(null); + iceTransport.onicestatechange = function() { + pc._updateIceConnectionState(); + pc._updateConnectionState(); + }; + + var dtlsTransport = new window.RTCDtlsTransport(iceTransport); + dtlsTransport.ondtlsstatechange = function() { + pc._updateConnectionState(); + }; + dtlsTransport.onerror = function() { + // onerror does not set state to failed by itself. + Object.defineProperty(dtlsTransport, 'state', + {value: 'failed', writable: true}); + pc._updateConnectionState(); + }; + + return { + iceTransport: iceTransport, + dtlsTransport: dtlsTransport + }; + }; + + // Destroy ICE gatherer, ICE transport and DTLS transport. + // Without triggering the callbacks. + RTCPeerConnection.prototype._disposeIceAndDtlsTransports = function( + sdpMLineIndex) { + var iceGatherer = this.transceivers[sdpMLineIndex].iceGatherer; + if (iceGatherer) { + delete iceGatherer.onlocalcandidate; + delete this.transceivers[sdpMLineIndex].iceGatherer; + } + var iceTransport = this.transceivers[sdpMLineIndex].iceTransport; + if (iceTransport) { + delete iceTransport.onicestatechange; + delete this.transceivers[sdpMLineIndex].iceTransport; + } + var dtlsTransport = this.transceivers[sdpMLineIndex].dtlsTransport; + if (dtlsTransport) { + delete dtlsTransport.ondtlsstatechange; + delete dtlsTransport.onerror; + delete this.transceivers[sdpMLineIndex].dtlsTransport; + } + }; + + // Start the RTP Sender and Receiver for a transceiver. + RTCPeerConnection.prototype._transceive = function(transceiver, + send, recv) { + var params = getCommonCapabilities(transceiver.localCapabilities, + transceiver.remoteCapabilities); + if (send && transceiver.rtpSender) { + params.encodings = transceiver.sendEncodingParameters; + params.rtcp = { + cname: SDPUtils.localCName, + compound: transceiver.rtcpParameters.compound + }; + if (transceiver.recvEncodingParameters.length) { + params.rtcp.ssrc = transceiver.recvEncodingParameters[0].ssrc; + } + transceiver.rtpSender.send(params); + } + if (recv && transceiver.rtpReceiver && params.codecs.length > 0) { + // remove RTX field in Edge 14942 + if (transceiver.kind === 'video' + && transceiver.recvEncodingParameters + && edgeVersion < 15019) { + transceiver.recvEncodingParameters.forEach(function(p) { + delete p.rtx; + }); + } + if (transceiver.recvEncodingParameters.length) { + params.encodings = transceiver.recvEncodingParameters; + } else { + params.encodings = [{}]; + } + params.rtcp = { + compound: transceiver.rtcpParameters.compound + }; + if (transceiver.rtcpParameters.cname) { + params.rtcp.cname = transceiver.rtcpParameters.cname; + } + if (transceiver.sendEncodingParameters.length) { + params.rtcp.ssrc = transceiver.sendEncodingParameters[0].ssrc; + } + transceiver.rtpReceiver.receive(params); + } + }; + + RTCPeerConnection.prototype.setLocalDescription = function(description) { + var pc = this; + + // Note: pranswer is not supported. + if (['offer', 'answer'].indexOf(description.type) === -1) { + return Promise.reject(makeError('TypeError', + 'Unsupported type "' + description.type + '"')); + } + + if (!isActionAllowedInSignalingState('setLocalDescription', + description.type, pc.signalingState) || pc._isClosed) { + return Promise.reject(makeError('InvalidStateError', + 'Can not set local ' + description.type + + ' in state ' + pc.signalingState)); + } + + var sections; + var sessionpart; + if (description.type === 'offer') { + // VERY limited support for SDP munging. Limited to: + // * changing the order of codecs + sections = SDPUtils.splitSections(description.sdp); + sessionpart = sections.shift(); + sections.forEach(function(mediaSection, sdpMLineIndex) { + var caps = SDPUtils.parseRtpParameters(mediaSection); + pc.transceivers[sdpMLineIndex].localCapabilities = caps; + }); + + pc.transceivers.forEach(function(transceiver, sdpMLineIndex) { + pc._gather(transceiver.mid, sdpMLineIndex); + }); + } else if (description.type === 'answer') { + sections = SDPUtils.splitSections(pc.remoteDescription.sdp); + sessionpart = sections.shift(); + var isIceLite = SDPUtils.matchPrefix(sessionpart, + 'a=ice-lite').length > 0; + sections.forEach(function(mediaSection, sdpMLineIndex) { + var transceiver = pc.transceivers[sdpMLineIndex]; + var iceGatherer = transceiver.iceGatherer; + var iceTransport = transceiver.iceTransport; + var dtlsTransport = transceiver.dtlsTransport; + var localCapabilities = transceiver.localCapabilities; + var remoteCapabilities = transceiver.remoteCapabilities; + + // treat bundle-only as not-rejected. + var rejected = SDPUtils.isRejected(mediaSection) && + SDPUtils.matchPrefix(mediaSection, 'a=bundle-only').length === 0; + + if (!rejected && !transceiver.rejected) { + var remoteIceParameters = SDPUtils.getIceParameters( + mediaSection, sessionpart); + var remoteDtlsParameters = SDPUtils.getDtlsParameters( + mediaSection, sessionpart); + if (isIceLite) { + remoteDtlsParameters.role = 'server'; + } + + if (!pc.usingBundle || sdpMLineIndex === 0) { + pc._gather(transceiver.mid, sdpMLineIndex); + if (iceTransport.state === 'new') { + iceTransport.start(iceGatherer, remoteIceParameters, + isIceLite ? 'controlling' : 'controlled'); + } + if (dtlsTransport.state === 'new') { + dtlsTransport.start(remoteDtlsParameters); + } + } + + // Calculate intersection of capabilities. + var params = getCommonCapabilities(localCapabilities, + remoteCapabilities); + + // Start the RTCRtpSender. The RTCRtpReceiver for this + // transceiver has already been started in setRemoteDescription. + pc._transceive(transceiver, + params.codecs.length > 0, + false); + } + }); + } + + pc.localDescription = { + type: description.type, + sdp: description.sdp + }; + if (description.type === 'offer') { + pc._updateSignalingState('have-local-offer'); + } else { + pc._updateSignalingState('stable'); + } + + return Promise.resolve(); + }; + + RTCPeerConnection.prototype.setRemoteDescription = function(description) { + var pc = this; + + // Note: pranswer is not supported. + if (['offer', 'answer'].indexOf(description.type) === -1) { + return Promise.reject(makeError('TypeError', + 'Unsupported type "' + description.type + '"')); + } + + if (!isActionAllowedInSignalingState('setRemoteDescription', + description.type, pc.signalingState) || pc._isClosed) { + return Promise.reject(makeError('InvalidStateError', + 'Can not set remote ' + description.type + + ' in state ' + pc.signalingState)); + } + + var streams = {}; + pc.remoteStreams.forEach(function(stream) { + streams[stream.id] = stream; + }); + var receiverList = []; + var sections = SDPUtils.splitSections(description.sdp); + var sessionpart = sections.shift(); + var isIceLite = SDPUtils.matchPrefix(sessionpart, + 'a=ice-lite').length > 0; + var usingBundle = SDPUtils.matchPrefix(sessionpart, + 'a=group:BUNDLE ').length > 0; + pc.usingBundle = usingBundle; + var iceOptions = SDPUtils.matchPrefix(sessionpart, + 'a=ice-options:')[0]; + if (iceOptions) { + pc.canTrickleIceCandidates = iceOptions.substr(14).split(' ') + .indexOf('trickle') >= 0; + } else { + pc.canTrickleIceCandidates = false; + } + + sections.forEach(function(mediaSection, sdpMLineIndex) { + var lines = SDPUtils.splitLines(mediaSection); + var kind = SDPUtils.getKind(mediaSection); + // treat bundle-only as not-rejected. + var rejected = SDPUtils.isRejected(mediaSection) && + SDPUtils.matchPrefix(mediaSection, 'a=bundle-only').length === 0; + var protocol = lines[0].substr(2).split(' ')[2]; + + var direction = SDPUtils.getDirection(mediaSection, sessionpart); + var remoteMsid = SDPUtils.parseMsid(mediaSection); + + var mid = SDPUtils.getMid(mediaSection) || SDPUtils.generateIdentifier(); + + // Reject datachannels which are not implemented yet. + if ((kind === 'application' && protocol === 'DTLS/SCTP') || rejected) { + // TODO: this is dangerous in the case where a non-rejected m-line + // becomes rejected. + pc.transceivers[sdpMLineIndex] = { + mid: mid, + kind: kind, + rejected: true + }; + return; + } + + if (!rejected && pc.transceivers[sdpMLineIndex] && + pc.transceivers[sdpMLineIndex].rejected) { + // recycle a rejected transceiver. + pc.transceivers[sdpMLineIndex] = pc._createTransceiver(kind, true); + } + + var transceiver; + var iceGatherer; + var iceTransport; + var dtlsTransport; + var rtpReceiver; + var sendEncodingParameters; + var recvEncodingParameters; + var localCapabilities; + + var track; + // FIXME: ensure the mediaSection has rtcp-mux set. + var remoteCapabilities = SDPUtils.parseRtpParameters(mediaSection); + var remoteIceParameters; + var remoteDtlsParameters; + if (!rejected) { + remoteIceParameters = SDPUtils.getIceParameters(mediaSection, + sessionpart); + remoteDtlsParameters = SDPUtils.getDtlsParameters(mediaSection, + sessionpart); + remoteDtlsParameters.role = 'client'; + } + recvEncodingParameters = + SDPUtils.parseRtpEncodingParameters(mediaSection); + + var rtcpParameters = SDPUtils.parseRtcpParameters(mediaSection); + + var isComplete = SDPUtils.matchPrefix(mediaSection, + 'a=end-of-candidates', sessionpart).length > 0; + var cands = SDPUtils.matchPrefix(mediaSection, 'a=candidate:') + .map(function(cand) { + return SDPUtils.parseCandidate(cand); + }) + .filter(function(cand) { + return cand.component === 1; + }); + + // Check if we can use BUNDLE and dispose transports. + if ((description.type === 'offer' || description.type === 'answer') && + !rejected && usingBundle && sdpMLineIndex > 0 && + pc.transceivers[sdpMLineIndex]) { + pc._disposeIceAndDtlsTransports(sdpMLineIndex); + pc.transceivers[sdpMLineIndex].iceGatherer = + pc.transceivers[0].iceGatherer; + pc.transceivers[sdpMLineIndex].iceTransport = + pc.transceivers[0].iceTransport; + pc.transceivers[sdpMLineIndex].dtlsTransport = + pc.transceivers[0].dtlsTransport; + if (pc.transceivers[sdpMLineIndex].rtpSender) { + pc.transceivers[sdpMLineIndex].rtpSender.setTransport( + pc.transceivers[0].dtlsTransport); + } + if (pc.transceivers[sdpMLineIndex].rtpReceiver) { + pc.transceivers[sdpMLineIndex].rtpReceiver.setTransport( + pc.transceivers[0].dtlsTransport); + } + } + if (description.type === 'offer' && !rejected) { + transceiver = pc.transceivers[sdpMLineIndex] || + pc._createTransceiver(kind); + transceiver.mid = mid; + + if (!transceiver.iceGatherer) { + transceiver.iceGatherer = pc._createIceGatherer(sdpMLineIndex, + usingBundle); + } + + if (cands.length && transceiver.iceTransport.state === 'new') { + if (isComplete && (!usingBundle || sdpMLineIndex === 0)) { + transceiver.iceTransport.setRemoteCandidates(cands); + } else { + cands.forEach(function(candidate) { + maybeAddCandidate(transceiver.iceTransport, candidate); + }); + } + } + + localCapabilities = window.RTCRtpReceiver.getCapabilities(kind); + + // filter RTX until additional stuff needed for RTX is implemented + // in adapter.js + if (edgeVersion < 15019) { + localCapabilities.codecs = localCapabilities.codecs.filter( + function(codec) { + return codec.name !== 'rtx'; + }); + } + + sendEncodingParameters = transceiver.sendEncodingParameters || [{ + ssrc: (2 * sdpMLineIndex + 2) * 1001 + }]; + + // TODO: rewrite to use http://w3c.github.io/webrtc-pc/#set-associated-remote-streams + var isNewTrack = false; + if (direction === 'sendrecv' || direction === 'sendonly') { + isNewTrack = !transceiver.rtpReceiver; + rtpReceiver = transceiver.rtpReceiver || + new window.RTCRtpReceiver(transceiver.dtlsTransport, kind); + + if (isNewTrack) { + var stream; + track = rtpReceiver.track; + // FIXME: does not work with Plan B. + if (remoteMsid && remoteMsid.stream === '-') { + // no-op. a stream id of '-' means: no associated stream. + } else if (remoteMsid) { + if (!streams[remoteMsid.stream]) { + streams[remoteMsid.stream] = new window.MediaStream(); + Object.defineProperty(streams[remoteMsid.stream], 'id', { + get: function() { + return remoteMsid.stream; + } + }); + } + Object.defineProperty(track, 'id', { + get: function() { + return remoteMsid.track; + } + }); + stream = streams[remoteMsid.stream]; + } else { + if (!streams.default) { + streams.default = new window.MediaStream(); + } + stream = streams.default; + } + if (stream) { + addTrackToStreamAndFireEvent(track, stream); + transceiver.associatedRemoteMediaStreams.push(stream); + } + receiverList.push([track, rtpReceiver, stream]); + } + } else if (transceiver.rtpReceiver && transceiver.rtpReceiver.track) { + transceiver.associatedRemoteMediaStreams.forEach(function(s) { + var nativeTrack = s.getTracks().find(function(t) { + return t.id === transceiver.rtpReceiver.track.id; + }); + if (nativeTrack) { + removeTrackFromStreamAndFireEvent(nativeTrack, s); + } + }); + transceiver.associatedRemoteMediaStreams = []; + } + + transceiver.localCapabilities = localCapabilities; + transceiver.remoteCapabilities = remoteCapabilities; + transceiver.rtpReceiver = rtpReceiver; + transceiver.rtcpParameters = rtcpParameters; + transceiver.sendEncodingParameters = sendEncodingParameters; + transceiver.recvEncodingParameters = recvEncodingParameters; + + // Start the RTCRtpReceiver now. The RTPSender is started in + // setLocalDescription. + pc._transceive(pc.transceivers[sdpMLineIndex], + false, + isNewTrack); + } else if (description.type === 'answer' && !rejected) { + transceiver = pc.transceivers[sdpMLineIndex]; + iceGatherer = transceiver.iceGatherer; + iceTransport = transceiver.iceTransport; + dtlsTransport = transceiver.dtlsTransport; + rtpReceiver = transceiver.rtpReceiver; + sendEncodingParameters = transceiver.sendEncodingParameters; + localCapabilities = transceiver.localCapabilities; + + pc.transceivers[sdpMLineIndex].recvEncodingParameters = + recvEncodingParameters; + pc.transceivers[sdpMLineIndex].remoteCapabilities = + remoteCapabilities; + pc.transceivers[sdpMLineIndex].rtcpParameters = rtcpParameters; + + if (cands.length && iceTransport.state === 'new') { + if ((isIceLite || isComplete) && + (!usingBundle || sdpMLineIndex === 0)) { + iceTransport.setRemoteCandidates(cands); + } else { + cands.forEach(function(candidate) { + maybeAddCandidate(transceiver.iceTransport, candidate); + }); + } + } + + if (!usingBundle || sdpMLineIndex === 0) { + if (iceTransport.state === 'new') { + iceTransport.start(iceGatherer, remoteIceParameters, + 'controlling'); + } + if (dtlsTransport.state === 'new') { + dtlsTransport.start(remoteDtlsParameters); + } + } + + pc._transceive(transceiver, + direction === 'sendrecv' || direction === 'recvonly', + direction === 'sendrecv' || direction === 'sendonly'); + + // TODO: rewrite to use http://w3c.github.io/webrtc-pc/#set-associated-remote-streams + if (rtpReceiver && + (direction === 'sendrecv' || direction === 'sendonly')) { + track = rtpReceiver.track; + if (remoteMsid) { + if (!streams[remoteMsid.stream]) { + streams[remoteMsid.stream] = new window.MediaStream(); + } + addTrackToStreamAndFireEvent(track, streams[remoteMsid.stream]); + receiverList.push([track, rtpReceiver, streams[remoteMsid.stream]]); + } else { + if (!streams.default) { + streams.default = new window.MediaStream(); + } + addTrackToStreamAndFireEvent(track, streams.default); + receiverList.push([track, rtpReceiver, streams.default]); + } + } else { + // FIXME: actually the receiver should be created later. + delete transceiver.rtpReceiver; + } + } + }); + + if (pc._dtlsRole === undefined) { + pc._dtlsRole = description.type === 'offer' ? 'active' : 'passive'; + } + + pc.remoteDescription = { + type: description.type, + sdp: description.sdp + }; + if (description.type === 'offer') { + pc._updateSignalingState('have-remote-offer'); + } else { + pc._updateSignalingState('stable'); + } + Object.keys(streams).forEach(function(sid) { + var stream = streams[sid]; + if (stream.getTracks().length) { + if (pc.remoteStreams.indexOf(stream) === -1) { + pc.remoteStreams.push(stream); + var event = new Event('addstream'); + event.stream = stream; + window.setTimeout(function() { + pc._dispatchEvent('addstream', event); + }); + } + + receiverList.forEach(function(item) { + var track = item[0]; + var receiver = item[1]; + if (stream.id !== item[2].id) { + return; + } + fireAddTrack(pc, track, receiver, [stream]); + }); + } + }); + receiverList.forEach(function(item) { + if (item[2]) { + return; + } + fireAddTrack(pc, item[0], item[1], []); + }); + + // check whether addIceCandidate({}) was called within four seconds after + // setRemoteDescription. + window.setTimeout(function() { + if (!(pc && pc.transceivers)) { + return; + } + pc.transceivers.forEach(function(transceiver) { + if (transceiver.iceTransport && + transceiver.iceTransport.state === 'new' && + transceiver.iceTransport.getRemoteCandidates().length > 0) { + console.warn('Timeout for addRemoteCandidate. Consider sending ' + + 'an end-of-candidates notification'); + transceiver.iceTransport.addRemoteCandidate({}); + } + }); + }, 4000); + + return Promise.resolve(); + }; + + RTCPeerConnection.prototype.close = function() { + this.transceivers.forEach(function(transceiver) { + /* not yet + if (transceiver.iceGatherer) { + transceiver.iceGatherer.close(); + } + */ + if (transceiver.iceTransport) { + transceiver.iceTransport.stop(); + } + if (transceiver.dtlsTransport) { + transceiver.dtlsTransport.stop(); + } + if (transceiver.rtpSender) { + transceiver.rtpSender.stop(); + } + if (transceiver.rtpReceiver) { + transceiver.rtpReceiver.stop(); + } + }); + // FIXME: clean up tracks, local streams, remote streams, etc + this._isClosed = true; + this._updateSignalingState('closed'); + }; + + // Update the signaling state. + RTCPeerConnection.prototype._updateSignalingState = function(newState) { + this.signalingState = newState; + var event = new Event('signalingstatechange'); + this._dispatchEvent('signalingstatechange', event); + }; + + // Determine whether to fire the negotiationneeded event. + RTCPeerConnection.prototype._maybeFireNegotiationNeeded = function() { + var pc = this; + if (this.signalingState !== 'stable' || this.needNegotiation === true) { + return; + } + this.needNegotiation = true; + window.setTimeout(function() { + if (pc.needNegotiation) { + pc.needNegotiation = false; + var event = new Event('negotiationneeded'); + pc._dispatchEvent('negotiationneeded', event); + } + }, 0); + }; + + // Update the ice connection state. + RTCPeerConnection.prototype._updateIceConnectionState = function() { + var newState; + var states = { + 'new': 0, + closed: 0, + checking: 0, + connected: 0, + completed: 0, + disconnected: 0, + failed: 0 + }; + this.transceivers.forEach(function(transceiver) { + states[transceiver.iceTransport.state]++; + }); + + newState = 'new'; + if (states.failed > 0) { + newState = 'failed'; + } else if (states.checking > 0) { + newState = 'checking'; + } else if (states.disconnected > 0) { + newState = 'disconnected'; + } else if (states.new > 0) { + newState = 'new'; + } else if (states.connected > 0) { + newState = 'connected'; + } else if (states.completed > 0) { + newState = 'completed'; + } + + if (newState !== this.iceConnectionState) { + this.iceConnectionState = newState; + var event = new Event('iceconnectionstatechange'); + this._dispatchEvent('iceconnectionstatechange', event); + } + }; + + // Update the connection state. + RTCPeerConnection.prototype._updateConnectionState = function() { + var newState; + var states = { + 'new': 0, + closed: 0, + connecting: 0, + connected: 0, + completed: 0, + disconnected: 0, + failed: 0 + }; + this.transceivers.forEach(function(transceiver) { + states[transceiver.iceTransport.state]++; + states[transceiver.dtlsTransport.state]++; + }); + // ICETransport.completed and connected are the same for this purpose. + states.connected += states.completed; + + newState = 'new'; + if (states.failed > 0) { + newState = 'failed'; + } else if (states.connecting > 0) { + newState = 'connecting'; + } else if (states.disconnected > 0) { + newState = 'disconnected'; + } else if (states.new > 0) { + newState = 'new'; + } else if (states.connected > 0) { + newState = 'connected'; + } + + if (newState !== this.connectionState) { + this.connectionState = newState; + var event = new Event('connectionstatechange'); + this._dispatchEvent('connectionstatechange', event); + } + }; + + RTCPeerConnection.prototype.createOffer = function() { + var pc = this; + + if (pc._isClosed) { + return Promise.reject(makeError('InvalidStateError', + 'Can not call createOffer after close')); + } + + var numAudioTracks = pc.transceivers.filter(function(t) { + return t.kind === 'audio'; + }).length; + var numVideoTracks = pc.transceivers.filter(function(t) { + return t.kind === 'video'; + }).length; + + // Determine number of audio and video tracks we need to send/recv. + var offerOptions = arguments[0]; + if (offerOptions) { + // Reject Chrome legacy constraints. + if (offerOptions.mandatory || offerOptions.optional) { + throw new TypeError( + 'Legacy mandatory/optional constraints not supported.'); + } + if (offerOptions.offerToReceiveAudio !== undefined) { + if (offerOptions.offerToReceiveAudio === true) { + numAudioTracks = 1; + } else if (offerOptions.offerToReceiveAudio === false) { + numAudioTracks = 0; + } else { + numAudioTracks = offerOptions.offerToReceiveAudio; + } + } + if (offerOptions.offerToReceiveVideo !== undefined) { + if (offerOptions.offerToReceiveVideo === true) { + numVideoTracks = 1; + } else if (offerOptions.offerToReceiveVideo === false) { + numVideoTracks = 0; + } else { + numVideoTracks = offerOptions.offerToReceiveVideo; + } + } + } + + pc.transceivers.forEach(function(transceiver) { + if (transceiver.kind === 'audio') { + numAudioTracks--; + if (numAudioTracks < 0) { + transceiver.wantReceive = false; + } + } else if (transceiver.kind === 'video') { + numVideoTracks--; + if (numVideoTracks < 0) { + transceiver.wantReceive = false; + } + } + }); + + // Create M-lines for recvonly streams. + while (numAudioTracks > 0 || numVideoTracks > 0) { + if (numAudioTracks > 0) { + pc._createTransceiver('audio'); + numAudioTracks--; + } + if (numVideoTracks > 0) { + pc._createTransceiver('video'); + numVideoTracks--; + } + } + + var sdp = SDPUtils.writeSessionBoilerplate(pc._sdpSessionId, + pc._sdpSessionVersion++); + pc.transceivers.forEach(function(transceiver, sdpMLineIndex) { + // For each track, create an ice gatherer, ice transport, + // dtls transport, potentially rtpsender and rtpreceiver. + var track = transceiver.track; + var kind = transceiver.kind; + var mid = transceiver.mid || SDPUtils.generateIdentifier(); + transceiver.mid = mid; + + if (!transceiver.iceGatherer) { + transceiver.iceGatherer = pc._createIceGatherer(sdpMLineIndex, + pc.usingBundle); + } + + var localCapabilities = window.RTCRtpSender.getCapabilities(kind); + // filter RTX until additional stuff needed for RTX is implemented + // in adapter.js + if (edgeVersion < 15019) { + localCapabilities.codecs = localCapabilities.codecs.filter( + function(codec) { + return codec.name !== 'rtx'; + }); + } + localCapabilities.codecs.forEach(function(codec) { + // work around https://bugs.chromium.org/p/webrtc/issues/detail?id=6552 + // by adding level-asymmetry-allowed=1 + if (codec.name === 'H264' && + codec.parameters['level-asymmetry-allowed'] === undefined) { + codec.parameters['level-asymmetry-allowed'] = '1'; + } + + // for subsequent offers, we might have to re-use the payload + // type of the last offer. + if (transceiver.remoteCapabilities && + transceiver.remoteCapabilities.codecs) { + transceiver.remoteCapabilities.codecs.forEach(function(remoteCodec) { + if (codec.name.toLowerCase() === remoteCodec.name.toLowerCase() && + codec.clockRate === remoteCodec.clockRate) { + codec.preferredPayloadType = remoteCodec.payloadType; + } + }); + } + }); + localCapabilities.headerExtensions.forEach(function(hdrExt) { + var remoteExtensions = transceiver.remoteCapabilities && + transceiver.remoteCapabilities.headerExtensions || []; + remoteExtensions.forEach(function(rHdrExt) { + if (hdrExt.uri === rHdrExt.uri) { + hdrExt.id = rHdrExt.id; + } + }); + }); + + // generate an ssrc now, to be used later in rtpSender.send + var sendEncodingParameters = transceiver.sendEncodingParameters || [{ + ssrc: (2 * sdpMLineIndex + 1) * 1001 + }]; + if (track) { + // add RTX + if (edgeVersion >= 15019 && kind === 'video' && + !sendEncodingParameters[0].rtx) { + sendEncodingParameters[0].rtx = { + ssrc: sendEncodingParameters[0].ssrc + 1 + }; + } + } + + if (transceiver.wantReceive) { + transceiver.rtpReceiver = new window.RTCRtpReceiver( + transceiver.dtlsTransport, kind); + } + + transceiver.localCapabilities = localCapabilities; + transceiver.sendEncodingParameters = sendEncodingParameters; + }); + + // always offer BUNDLE and dispose on return if not supported. + if (pc._config.bundlePolicy !== 'max-compat') { + sdp += 'a=group:BUNDLE ' + pc.transceivers.map(function(t) { + return t.mid; + }).join(' ') + '\r\n'; + } + sdp += 'a=ice-options:trickle\r\n'; + + pc.transceivers.forEach(function(transceiver, sdpMLineIndex) { + sdp += writeMediaSection(transceiver, transceiver.localCapabilities, + 'offer', transceiver.stream, pc._dtlsRole); + sdp += 'a=rtcp-rsize\r\n'; + + if (transceiver.iceGatherer && pc.iceGatheringState !== 'new' && + (sdpMLineIndex === 0 || !pc.usingBundle)) { + transceiver.iceGatherer.getLocalCandidates().forEach(function(cand) { + cand.component = 1; + sdp += 'a=' + SDPUtils.writeCandidate(cand) + '\r\n'; + }); + + if (transceiver.iceGatherer.state === 'completed') { + sdp += 'a=end-of-candidates\r\n'; + } + } + }); + + var desc = new window.RTCSessionDescription({ + type: 'offer', + sdp: sdp + }); + return Promise.resolve(desc); + }; + + RTCPeerConnection.prototype.createAnswer = function() { + var pc = this; + + if (pc._isClosed) { + return Promise.reject(makeError('InvalidStateError', + 'Can not call createAnswer after close')); + } + + if (!(pc.signalingState === 'have-remote-offer' || + pc.signalingState === 'have-local-pranswer')) { + return Promise.reject(makeError('InvalidStateError', + 'Can not call createAnswer in signalingState ' + pc.signalingState)); + } + + var sdp = SDPUtils.writeSessionBoilerplate(pc._sdpSessionId, + pc._sdpSessionVersion++); + if (pc.usingBundle) { + sdp += 'a=group:BUNDLE ' + pc.transceivers.map(function(t) { + return t.mid; + }).join(' ') + '\r\n'; + } + var mediaSectionsInOffer = SDPUtils.getMediaSections( + pc.remoteDescription.sdp).length; + pc.transceivers.forEach(function(transceiver, sdpMLineIndex) { + if (sdpMLineIndex + 1 > mediaSectionsInOffer) { + return; + } + if (transceiver.rejected) { + if (transceiver.kind === 'application') { + sdp += 'm=application 0 DTLS/SCTP 5000\r\n'; + } else if (transceiver.kind === 'audio') { + sdp += 'm=audio 0 UDP/TLS/RTP/SAVPF 0\r\n' + + 'a=rtpmap:0 PCMU/8000\r\n'; + } else if (transceiver.kind === 'video') { + sdp += 'm=video 0 UDP/TLS/RTP/SAVPF 120\r\n' + + 'a=rtpmap:120 VP8/90000\r\n'; + } + sdp += 'c=IN IP4 0.0.0.0\r\n' + + 'a=inactive\r\n' + + 'a=mid:' + transceiver.mid + '\r\n'; + return; + } + + // FIXME: look at direction. + if (transceiver.stream) { + var localTrack; + if (transceiver.kind === 'audio') { + localTrack = transceiver.stream.getAudioTracks()[0]; + } else if (transceiver.kind === 'video') { + localTrack = transceiver.stream.getVideoTracks()[0]; + } + if (localTrack) { + // add RTX + if (edgeVersion >= 15019 && transceiver.kind === 'video' && + !transceiver.sendEncodingParameters[0].rtx) { + transceiver.sendEncodingParameters[0].rtx = { + ssrc: transceiver.sendEncodingParameters[0].ssrc + 1 + }; + } + } + } + + // Calculate intersection of capabilities. + var commonCapabilities = getCommonCapabilities( + transceiver.localCapabilities, + transceiver.remoteCapabilities); + + var hasRtx = commonCapabilities.codecs.filter(function(c) { + return c.name.toLowerCase() === 'rtx'; + }).length; + if (!hasRtx && transceiver.sendEncodingParameters[0].rtx) { + delete transceiver.sendEncodingParameters[0].rtx; + } + + sdp += writeMediaSection(transceiver, commonCapabilities, + 'answer', transceiver.stream, pc._dtlsRole); + if (transceiver.rtcpParameters && + transceiver.rtcpParameters.reducedSize) { + sdp += 'a=rtcp-rsize\r\n'; + } + }); + + var desc = new window.RTCSessionDescription({ + type: 'answer', + sdp: sdp + }); + return Promise.resolve(desc); + }; + + RTCPeerConnection.prototype.addIceCandidate = function(candidate) { + var pc = this; + var sections; + if (candidate && !(candidate.sdpMLineIndex !== undefined || + candidate.sdpMid)) { + return Promise.reject(new TypeError('sdpMLineIndex or sdpMid required')); + } + + // TODO: needs to go into ops queue. + return new Promise(function(resolve, reject) { + if (!pc.remoteDescription) { + return reject(makeError('InvalidStateError', + 'Can not add ICE candidate without a remote description')); + } else if (!candidate || candidate.candidate === '') { + for (var j = 0; j < pc.transceivers.length; j++) { + if (pc.transceivers[j].rejected) { + continue; + } + pc.transceivers[j].iceTransport.addRemoteCandidate({}); + sections = SDPUtils.getMediaSections(pc.remoteDescription.sdp); + sections[j] += 'a=end-of-candidates\r\n'; + pc.remoteDescription.sdp = + SDPUtils.getDescription(pc.remoteDescription.sdp) + + sections.join(''); + if (pc.usingBundle) { + break; + } + } + } else { + var sdpMLineIndex = candidate.sdpMLineIndex; + if (candidate.sdpMid) { + for (var i = 0; i < pc.transceivers.length; i++) { + if (pc.transceivers[i].mid === candidate.sdpMid) { + sdpMLineIndex = i; + break; + } + } + } + var transceiver = pc.transceivers[sdpMLineIndex]; + if (transceiver) { + if (transceiver.rejected) { + return resolve(); + } + var cand = Object.keys(candidate.candidate).length > 0 ? + SDPUtils.parseCandidate(candidate.candidate) : {}; + // Ignore Chrome's invalid candidates since Edge does not like them. + if (cand.protocol === 'tcp' && (cand.port === 0 || cand.port === 9)) { + return resolve(); + } + // Ignore RTCP candidates, we assume RTCP-MUX. + if (cand.component && cand.component !== 1) { + return resolve(); + } + // when using bundle, avoid adding candidates to the wrong + // ice transport. And avoid adding candidates added in the SDP. + if (sdpMLineIndex === 0 || (sdpMLineIndex > 0 && + transceiver.iceTransport !== pc.transceivers[0].iceTransport)) { + if (!maybeAddCandidate(transceiver.iceTransport, cand)) { + return reject(makeError('OperationError', + 'Can not add ICE candidate')); + } + } + + // update the remoteDescription. + var candidateString = candidate.candidate.trim(); + if (candidateString.indexOf('a=') === 0) { + candidateString = candidateString.substr(2); + } + sections = SDPUtils.getMediaSections(pc.remoteDescription.sdp); + sections[sdpMLineIndex] += 'a=' + + (cand.type ? candidateString : 'end-of-candidates') + + '\r\n'; + pc.remoteDescription.sdp = sections.join(''); + } else { + return reject(makeError('OperationError', + 'Can not add ICE candidate')); + } + } + resolve(); + }); + }; + + RTCPeerConnection.prototype.getStats = function() { + var promises = []; + this.transceivers.forEach(function(transceiver) { + ['rtpSender', 'rtpReceiver', 'iceGatherer', 'iceTransport', + 'dtlsTransport'].forEach(function(method) { + if (transceiver[method]) { + promises.push(transceiver[method].getStats()); + } + }); + }); + var fixStatsType = function(stat) { + return { + inboundrtp: 'inbound-rtp', + outboundrtp: 'outbound-rtp', + candidatepair: 'candidate-pair', + localcandidate: 'local-candidate', + remotecandidate: 'remote-candidate' + }[stat.type] || stat.type; + }; + return new Promise(function(resolve) { + // shim getStats with maplike support + var results = new Map(); + Promise.all(promises).then(function(res) { + res.forEach(function(result) { + Object.keys(result).forEach(function(id) { + result[id].type = fixStatsType(result[id]); + results.set(id, result[id]); + }); + }); + resolve(results); + }); + }); + }; + + // legacy callback shims. Should be moved to adapter.js some days. + var methods = ['createOffer', 'createAnswer']; + methods.forEach(function(method) { + var nativeMethod = RTCPeerConnection.prototype[method]; + RTCPeerConnection.prototype[method] = function() { + var args = arguments; + if (typeof args[0] === 'function' || + typeof args[1] === 'function') { // legacy + return nativeMethod.apply(this, [arguments[2]]) + .then(function(description) { + if (typeof args[0] === 'function') { + args[0].apply(null, [description]); + } + }, function(error) { + if (typeof args[1] === 'function') { + args[1].apply(null, [error]); + } + }); + } + return nativeMethod.apply(this, arguments); + }; + }); + + methods = ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']; + methods.forEach(function(method) { + var nativeMethod = RTCPeerConnection.prototype[method]; + RTCPeerConnection.prototype[method] = function() { + var args = arguments; + if (typeof args[1] === 'function' || + typeof args[2] === 'function') { // legacy + return nativeMethod.apply(this, arguments) + .then(function() { + if (typeof args[1] === 'function') { + args[1].apply(null); + } + }, function(error) { + if (typeof args[2] === 'function') { + args[2].apply(null, [error]); + } + }); + } + return nativeMethod.apply(this, arguments); + }; + }); + + // getStats is special. It doesn't have a spec legacy method yet we support + // getStats(something, cb) without error callbacks. + ['getStats'].forEach(function(method) { + var nativeMethod = RTCPeerConnection.prototype[method]; + RTCPeerConnection.prototype[method] = function() { + var args = arguments; + if (typeof args[1] === 'function') { + return nativeMethod.apply(this, arguments) + .then(function() { + if (typeof args[1] === 'function') { + args[1].apply(null); + } + }); + } + return nativeMethod.apply(this, arguments); + }; + }); + + return RTCPeerConnection; +}; + +},{"sdp":19}],11:[function(require,module,exports){ +var grammar = module.exports = { + v: [{ + name: 'version', + reg: /^(\d*)$/ + }], + o: [{ //o=- 20518 0 IN IP4 203.0.113.1 + // NB: sessionId will be a String in most cases because it is huge + name: 'origin', + reg: /^(\S*) (\d*) (\d*) (\S*) IP(\d) (\S*)/, + names: ['username', 'sessionId', 'sessionVersion', 'netType', 'ipVer', 'address'], + format: "%s %s %d %s IP%d %s" + }], + // default parsing of these only (though some of these feel outdated) + s: [{ name: 'name' }], + i: [{ name: 'description' }], + u: [{ name: 'uri' }], + e: [{ name: 'email' }], + p: [{ name: 'phone' }], + z: [{ name: 'timezones' }], // TODO: this one can actually be parsed properly.. + r: [{ name: 'repeats' }], // TODO: this one can also be parsed properly + //k: [{}], // outdated thing ignored + t: [{ //t=0 0 + name: 'timing', + reg: /^(\d*) (\d*)/, + names: ['start', 'stop'], + format: "%d %d" + }], + c: [{ //c=IN IP4 10.47.197.26 + name: 'connection', + reg: /^IN IP(\d) (\S*)/, + names: ['version', 'ip'], + format: "IN IP%d %s" + }], + b: [{ //b=AS:4000 + push: 'bandwidth', + reg: /^(TIAS|AS|CT|RR|RS):(\d*)/, + names: ['type', 'limit'], + format: "%s:%s" + }], + m: [{ //m=video 51744 RTP/AVP 126 97 98 34 31 + // NB: special - pushes to session + // TODO: rtp/fmtp should be filtered by the payloads found here? + reg: /^(\w*) (\d*) ([\w\/]*)(?: (.*))?/, + names: ['type', 'port', 'protocol', 'payloads'], + format: "%s %d %s %s" + }], + a: [ + { //a=rtpmap:110 opus/48000/2 + push: 'rtp', + reg: /^rtpmap:(\d*) ([\w\-]*)(?:\s*\/(\d*)(?:\s*\/(\S*))?)?/, + names: ['payload', 'codec', 'rate', 'encoding'], + format: function (o) { + return (o.encoding) ? + "rtpmap:%d %s/%s/%s": + o.rate ? + "rtpmap:%d %s/%s": + "rtpmap:%d %s"; + } + }, + { + //a=fmtp:108 profile-level-id=24;object=23;bitrate=64000 + //a=fmtp:111 minptime=10; useinbandfec=1 + push: 'fmtp', + reg: /^fmtp:(\d*) ([\S| ]*)/, + names: ['payload', 'config'], + format: "fmtp:%d %s" + }, + { //a=control:streamid=0 + name: 'control', + reg: /^control:(.*)/, + format: "control:%s" + }, + { //a=rtcp:65179 IN IP4 193.84.77.194 + name: 'rtcp', + reg: /^rtcp:(\d*)(?: (\S*) IP(\d) (\S*))?/, + names: ['port', 'netType', 'ipVer', 'address'], + format: function (o) { + return (o.address != null) ? + "rtcp:%d %s IP%d %s": + "rtcp:%d"; + } + }, + { //a=rtcp-fb:98 trr-int 100 + push: 'rtcpFbTrrInt', + reg: /^rtcp-fb:(\*|\d*) trr-int (\d*)/, + names: ['payload', 'value'], + format: "rtcp-fb:%d trr-int %d" + }, + { //a=rtcp-fb:98 nack rpsi + push: 'rtcpFb', + reg: /^rtcp-fb:(\*|\d*) ([\w-_]*)(?: ([\w-_]*))?/, + names: ['payload', 'type', 'subtype'], + format: function (o) { + return (o.subtype != null) ? + "rtcp-fb:%s %s %s": + "rtcp-fb:%s %s"; + } + }, + { //a=extmap:2 urn:ietf:params:rtp-hdrext:toffset + //a=extmap:1/recvonly URI-gps-string + push: 'ext', + reg: /^extmap:([\w_\/]*) (\S*)(?: (\S*))?/, + names: ['value', 'uri', 'config'], // value may include "/direction" suffix + format: function (o) { + return (o.config != null) ? + "extmap:%s %s %s": + "extmap:%s %s"; + } + }, + { + //a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR|2^20|1:32 + push: 'crypto', + reg: /^crypto:(\d*) ([\w_]*) (\S*)(?: (\S*))?/, + names: ['id', 'suite', 'config', 'sessionConfig'], + format: function (o) { + return (o.sessionConfig != null) ? + "crypto:%d %s %s %s": + "crypto:%d %s %s"; + } + }, + { //a=setup:actpass + name: 'setup', + reg: /^setup:(\w*)/, + format: "setup:%s" + }, + { //a=mid:1 + name: 'mid', + reg: /^mid:([^\s]*)/, + format: "mid:%s" + }, + { //a=msid:0c8b064d-d807-43b4-b434-f92a889d8587 98178685-d409-46e0-8e16-7ef0db0db64a + name: 'msid', + reg: /^msid:(.*)/, + format: "msid:%s" + }, + { //a=ptime:20 + name: 'ptime', + reg: /^ptime:(\d*)/, + format: "ptime:%d" + }, + { //a=maxptime:60 + name: 'maxptime', + reg: /^maxptime:(\d*)/, + format: "maxptime:%d" + }, + { //a=sendrecv + name: 'direction', + reg: /^(sendrecv|recvonly|sendonly|inactive)/ + }, + { //a=ice-lite + name: 'icelite', + reg: /^(ice-lite)/ + }, + { //a=ice-ufrag:F7gI + name: 'iceUfrag', + reg: /^ice-ufrag:(\S*)/, + format: "ice-ufrag:%s" + }, + { //a=ice-pwd:x9cml/YzichV2+XlhiMu8g + name: 'icePwd', + reg: /^ice-pwd:(\S*)/, + format: "ice-pwd:%s" + }, + { //a=fingerprint:SHA-1 00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33 + name: 'fingerprint', + reg: /^fingerprint:(\S*) (\S*)/, + names: ['type', 'hash'], + format: "fingerprint:%s %s" + }, + { + //a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host + //a=candidate:1162875081 1 udp 2113937151 192.168.34.75 60017 typ host generation 0 + //a=candidate:3289912957 2 udp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 generation 0 + //a=candidate:229815620 1 tcp 1518280447 192.168.150.19 60017 typ host tcptype active generation 0 + //a=candidate:3289912957 2 tcp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 tcptype passive generation 0 + push:'candidates', + reg: /^candidate:(\S*) (\d*) (\S*) (\d*) (\S*) (\d*) typ (\S*)(?: raddr (\S*) rport (\d*))?(?: tcptype (\S*))?(?: generation (\d*))?/, + names: ['foundation', 'component', 'transport', 'priority', 'ip', 'port', 'type', 'raddr', 'rport', 'tcptype', 'generation'], + format: function (o) { + var str = "candidate:%s %d %s %d %s %d typ %s"; + + str += (o.raddr != null) ? " raddr %s rport %d" : "%v%v"; + + // NB: candidate has three optional chunks, so %void middles one if it's missing + str += (o.tcptype != null) ? " tcptype %s" : "%v"; + + if (o.generation != null) { + str += " generation %d"; + } + return str; + } + }, + { //a=end-of-candidates (keep after the candidates line for readability) + name: 'endOfCandidates', + reg: /^(end-of-candidates)/ + }, + { //a=remote-candidates:1 203.0.113.1 54400 2 203.0.113.1 54401 ... + name: 'remoteCandidates', + reg: /^remote-candidates:(.*)/, + format: "remote-candidates:%s" + }, + { //a=ice-options:google-ice + name: 'iceOptions', + reg: /^ice-options:(\S*)/, + format: "ice-options:%s" + }, + { //a=ssrc:2566107569 cname:t9YU8M1UxTF8Y1A1 + push: "ssrcs", + reg: /^ssrc:(\d*) ([\w_]*):(.*)/, + names: ['id', 'attribute', 'value'], + format: "ssrc:%d %s:%s" + }, + { //a=ssrc-group:FEC 1 2 + push: "ssrcGroups", + reg: /^ssrc-group:(\w*) (.*)/, + names: ['semantics', 'ssrcs'], + format: "ssrc-group:%s %s" + }, + { //a=msid-semantic: WMS Jvlam5X3SX1OP6pn20zWogvaKJz5Hjf9OnlV + name: "msidSemantic", + reg: /^msid-semantic:\s?(\w*) (\S*)/, + names: ['semantic', 'token'], + format: "msid-semantic: %s %s" // space after ":" is not accidental + }, + { //a=group:BUNDLE audio video + push: 'groups', + reg: /^group:(\w*) (.*)/, + names: ['type', 'mids'], + format: "group:%s %s" + }, + { //a=rtcp-mux + name: 'rtcpMux', + reg: /^(rtcp-mux)/ + }, + { //a=rtcp-rsize + name: 'rtcpRsize', + reg: /^(rtcp-rsize)/ + }, + { // any a= that we don't understand is kepts verbatim on media.invalid + push: 'invalid', + names: ["value"] + } + ] +}; + +// set sensible defaults to avoid polluting the grammar with boring details +Object.keys(grammar).forEach(function (key) { + var objs = grammar[key]; + objs.forEach(function (obj) { + if (!obj.reg) { + obj.reg = /(.*)/; + } + if (!obj.format) { + obj.format = "%s"; + } + }); +}); + +},{}],12:[function(require,module,exports){ +var parser = require('./parser'); +var writer = require('./writer'); + +exports.write = writer; +exports.parse = parser.parse; +exports.parseFmtpConfig = parser.parseFmtpConfig; +exports.parsePayloads = parser.parsePayloads; +exports.parseRemoteCandidates = parser.parseRemoteCandidates; + +},{"./parser":13,"./writer":14}],13:[function(require,module,exports){ +var toIntIfInt = function (v) { + return String(Number(v)) === v ? Number(v) : v; +}; + +var attachProperties = function (match, location, names, rawName) { + if (rawName && !names) { + location[rawName] = toIntIfInt(match[1]); + } + else { + for (var i = 0; i < names.length; i += 1) { + if (match[i+1] != null) { + location[names[i]] = toIntIfInt(match[i+1]); + } + } + } +}; + +var parseReg = function (obj, location, content) { + var needsBlank = obj.name && obj.names; + if (obj.push && !location[obj.push]) { + location[obj.push] = []; + } + else if (needsBlank && !location[obj.name]) { + location[obj.name] = {}; + } + var keyLocation = obj.push ? + {} : // blank object that will be pushed + needsBlank ? location[obj.name] : location; // otherwise, named location or root + + attachProperties(content.match(obj.reg), keyLocation, obj.names, obj.name); + + if (obj.push) { + location[obj.push].push(keyLocation); + } +}; + +var grammar = require('./grammar'); +var validLine = RegExp.prototype.test.bind(/^([a-z])=(.*)/); + +exports.parse = function (sdp) { + var session = {} + , media = [] + , location = session; // points at where properties go under (one of the above) + + // parse lines we understand + sdp.split(/(\r\n|\r|\n)/).filter(validLine).forEach(function (l) { + var type = l[0]; + var content = l.slice(2); + if (type === 'm') { + media.push({rtp: [], fmtp: []}); + location = media[media.length-1]; // point at latest media line + } + + for (var j = 0; j < (grammar[type] || []).length; j += 1) { + var obj = grammar[type][j]; + if (obj.reg.test(content)) { + return parseReg(obj, location, content); + } + } + }); + + session.media = media; // link it up + return session; +}; + +var fmtpReducer = function (acc, expr) { + var s = expr.split('='); + if (s.length === 2) { + acc[s[0]] = toIntIfInt(s[1]); + } + return acc; +}; + +exports.parseFmtpConfig = function (str) { + return str.split(/\;\s?/).reduce(fmtpReducer, {}); +}; + +exports.parsePayloads = function (str) { + return str.split(' ').map(Number); +}; + +exports.parseRemoteCandidates = function (str) { + var candidates = []; + var parts = str.split(' ').map(toIntIfInt); + for (var i = 0; i < parts.length; i += 3) { + candidates.push({ + component: parts[i], + ip: parts[i + 1], + port: parts[i + 2] + }); + } + return candidates; +}; + +},{"./grammar":11}],14:[function(require,module,exports){ +var grammar = require('./grammar'); + +// customized util.format - discards excess arguments and can void middle ones +var formatRegExp = /%[sdv%]/g; +var format = function (formatStr) { + var i = 1; + var args = arguments; + var len = args.length; + return formatStr.replace(formatRegExp, function (x) { + if (i >= len) { + return x; // missing argument + } + var arg = args[i]; + i += 1; + switch (x) { + case '%%': + return '%'; + case '%s': + return String(arg); + case '%d': + return Number(arg); + case '%v': + return ''; + } + }); + // NB: we discard excess arguments - they are typically undefined from makeLine +}; + +var makeLine = function (type, obj, location) { + var str = obj.format instanceof Function ? + (obj.format(obj.push ? location : location[obj.name])) : + obj.format; + + var args = [type + '=' + str]; + if (obj.names) { + for (var i = 0; i < obj.names.length; i += 1) { + var n = obj.names[i]; + if (obj.name) { + args.push(location[obj.name][n]); + } + else { // for mLine and push attributes + args.push(location[obj.names[i]]); + } + } + } + else { + args.push(location[obj.name]); + } + return format.apply(null, args); +}; + +// RFC specified order +// TODO: extend this with all the rest +var defaultOuterOrder = [ + 'v', 'o', 's', 'i', + 'u', 'e', 'p', 'c', + 'b', 't', 'r', 'z', 'a' +]; +var defaultInnerOrder = ['i', 'c', 'b', 'a']; + + +module.exports = function (session, opts) { + opts = opts || {}; + // ensure certain properties exist + if (session.version == null) { + session.version = 0; // "v=0" must be there (only defined version atm) + } + if (session.name == null) { + session.name = " "; // "s= " must be there if no meaningful name set + } + session.media.forEach(function (mLine) { + if (mLine.payloads == null) { + mLine.payloads = ""; + } + }); + + var outerOrder = opts.outerOrder || defaultOuterOrder; + var innerOrder = opts.innerOrder || defaultInnerOrder; + var sdp = []; + + // loop through outerOrder for matching properties on session + outerOrder.forEach(function (type) { + grammar[type].forEach(function (obj) { + if (obj.name in session && session[obj.name] != null) { + sdp.push(makeLine(type, obj, session)); + } + else if (obj.push in session && session[obj.push] != null) { + session[obj.push].forEach(function (el) { + sdp.push(makeLine(type, obj, el)); + }); + } + }); + }); + + // then for each media line, follow the innerOrder + session.media.forEach(function (mLine) { + sdp.push(makeLine('m', grammar.m[0], mLine)); + + innerOrder.forEach(function (type) { + grammar[type].forEach(function (obj) { + if (obj.name in mLine && mLine[obj.name] != null) { + sdp.push(makeLine(type, obj, mLine)); + } + else if (obj.push in mLine && mLine[obj.push] != null) { + mLine[obj.push].forEach(function (el) { + sdp.push(makeLine(type, obj, el)); + }); + } + }); + }); + }); + + return sdp.join('\r\n') + '\r\n'; +}; + +},{"./grammar":11}],15:[function(require,module,exports){ +/* Copyright @ 2015 Atlassian Pty Ltd + * + * 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. + */ + +module.exports = function arrayEquals(array) { + // if the other array is a falsy value, return + if (!array) + return false; + + // compare lengths - can save a lot of time + if (this.length != array.length) + return false; + + for (var i = 0, l = this.length; i < l; i++) { + // Check if we have nested arrays + if (this[i] instanceof Array && array[i] instanceof Array) { + // recurse into the nested arrays + if (!arrayEquals.apply(this[i], [array[i]])) + return false; + } else if (this[i] != array[i]) { + // Warning - two different object instances will never be equal: + // {x:20} != {x:20} + return false; + } + } + return true; +}; + + +},{}],16:[function(require,module,exports){ +/* Copyright @ 2015 Atlassian Pty Ltd + * + * 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. + */ + +exports.Interop = require('./interop'); + +},{"./interop":17}],17:[function(require,module,exports){ +/* Copyright @ 2015 Atlassian Pty Ltd + * + * 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. + */ + +/* global RTCSessionDescription */ +/* global RTCIceCandidate */ +/* jshint -W097 */ +"use strict"; + +var transform = require('./transform'); +var arrayEquals = require('./array-equals'); + +function Interop() { + + /** + * This map holds the most recent Unified Plan offer/answer SDP that was + * converted to Plan B, with the SDP type ('offer' or 'answer') as keys and + * the SDP string as values. + * + * @type {{}} + */ + this.cache = { + mlB2UMap : {}, + mlU2BMap : {} + }; +} + +module.exports = Interop; + +/** + * Changes the candidate args to match with the related Unified Plan + */ +Interop.prototype.candidateToUnifiedPlan = function(candidate) { + var cand = new RTCIceCandidate(candidate); + + cand.sdpMLineIndex = this.cache.mlB2UMap[cand.sdpMLineIndex]; + /* TODO: change sdpMid to (audio|video)-SSRC */ + + return cand; +}; + +/** + * Changes the candidate args to match with the related Plan B + */ +Interop.prototype.candidateToPlanB = function(candidate) { + var cand = new RTCIceCandidate(candidate); + + if (cand.sdpMid.indexOf('audio') === 0) { + cand.sdpMid = 'audio'; + } else if (cand.sdpMid.indexOf('video') === 0) { + cand.sdpMid = 'video'; + } else { + throw new Error('candidate with ' + cand.sdpMid + ' not allowed'); + } + + cand.sdpMLineIndex = this.cache.mlU2BMap[cand.sdpMLineIndex]; + + return cand; +}; + +/** + * Returns the index of the first m-line with the given media type and with a + * direction which allows sending, in the last Unified Plan description with + * type "answer" converted to Plan B. Returns {null} if there is no saved + * answer, or if none of its m-lines with the given type allow sending. + * @param type the media type ("audio" or "video"). + * @returns {*} + */ +Interop.prototype.getFirstSendingIndexFromAnswer = function(type) { + if (!this.cache.answer) { + return null; + } + + var session = transform.parse(this.cache.answer); + if (session && session.media && Array.isArray(session.media)){ + for (var i = 0; i < session.media.length; i++) { + if (session.media[i].type == type && + (!session.media[i].direction /* default to sendrecv */ || + session.media[i].direction === 'sendrecv' || + session.media[i].direction === 'sendonly')){ + return i; + } + } + } + + return null; +}; + +/** + * This method transforms a Unified Plan SDP to an equivalent Plan B SDP. A + * PeerConnection wrapper transforms the SDP to Plan B before passing it to the + * application. + * + * @param desc + * @returns {*} + */ +Interop.prototype.toPlanB = function(desc) { + var self = this; + //#region Preliminary input validation. + + if (typeof desc !== 'object' || desc === null || + typeof desc.sdp !== 'string') { + console.warn('An empty description was passed as an argument.'); + return desc; + } + + // Objectify the SDP for easier manipulation. + var session = transform.parse(desc.sdp); + + // If the SDP contains no media, there's nothing to transform. + if (typeof session.media === 'undefined' || + !Array.isArray(session.media) || session.media.length === 0) { + console.warn('The description has no media.'); + return desc; + } + + // Try some heuristics to "make sure" this is a Unified Plan SDP. Plan B + // SDP has a video, an audio and a data "channel" at most. + if (session.media.length <= 3 && session.media.every(function(m) { + return ['video', 'audio', 'data'].indexOf(m.mid) !== -1; + })) { + console.warn('This description does not look like Unified Plan.'); + return desc; + } + + //#endregion + + // HACK https://bugzilla.mozilla.org/show_bug.cgi?id=1113443 + var sdp = desc.sdp; + var rewrite = false; + for (var i = 0; i < session.media.length; i++) { + var uLine = session.media[i]; + uLine.rtp.forEach(function(rtp) { + if (rtp.codec === 'NULL') + { + rewrite = true; + var offer = transform.parse(self.cache.offer); + rtp.codec = offer.media[i].rtp[0].codec; + } + }); + } + if (rewrite) { + sdp = transform.write(session); + } + + // Unified Plan SDP is our "precious". Cache it for later use in the Plan B + // -> Unified Plan transformation. + this.cache[desc.type] = sdp; + + //#region Convert from Unified Plan to Plan B. + + // We rebuild the session.media array. + var media = session.media; + session.media = []; + + // Associative array that maps channel types to channel objects for fast + // access to channel objects by their type, e.g. type2bl['audio']->channel + // obj. + var type2bl = {}; + + // Used to build the group:BUNDLE value after the channels construction + // loop. + var types = []; + + media.forEach(function(uLine) { + // rtcp-mux is required in the Plan B SDP. + if ((typeof uLine.rtcpMux !== 'string' || + uLine.rtcpMux !== 'rtcp-mux') && + uLine.direction !== 'inactive') { + throw new Error('Cannot convert to Plan B because m-lines ' + + 'without the rtcp-mux attribute were found.'); + } + + // If we don't have a channel for this uLine.type OR the selected is + // inactive, then select this uLine as the channel basis. + if (typeof type2bl[uLine.type] === 'undefined' || + type2bl[uLine.type].direction === 'inactive') { + type2bl[uLine.type] = uLine; + } + + if (uLine.protocol != type2bl[uLine.type].protocol) { + throw new Error('Cannot convert to Plan B because m-lines ' + + 'have different protocols and this library does not have ' + + 'support for that'); + } + + if (uLine.payloads != type2bl[uLine.type].payloads) { + throw new Error('Cannot convert to Plan B because m-lines ' + + 'have different payloads and this library does not have ' + + 'support for that'); + } + + }); + + // Implode the Unified Plan m-lines/tracks into Plan B channels. + media.forEach(function(uLine) { + if (uLine.type === 'application') { + session.media.push(uLine); + types.push(uLine.mid); + return; + } + + // Add sources to the channel and handle a=msid. + if (typeof uLine.sources === 'object') { + Object.keys(uLine.sources).forEach(function(ssrc) { + if (typeof type2bl[uLine.type].sources !== 'object') + type2bl[uLine.type].sources = {}; + + // Assign the sources to the channel. + type2bl[uLine.type].sources[ssrc] = + uLine.sources[ssrc]; + + if (typeof uLine.msid !== 'undefined') { + // In Plan B the msid is an SSRC attribute. Also, we don't + // care about the obsolete label and mslabel attributes. + // + // Note that it is not guaranteed that the uLine will + // have an msid. recvonly channels in particular don't have + // one. + type2bl[uLine.type].sources[ssrc].msid = + uLine.msid; + } + // NOTE ssrcs in ssrc groups will share msids, as + // draft-uberti-rtcweb-plan-00 mandates. + }); + } + + // Add ssrc groups to the channel. + if (typeof uLine.ssrcGroups !== 'undefined' && + Array.isArray(uLine.ssrcGroups)) { + + // Create the ssrcGroups array, if it's not defined. + if (typeof type2bl[uLine.type].ssrcGroups === 'undefined' || + !Array.isArray(type2bl[uLine.type].ssrcGroups)) { + type2bl[uLine.type].ssrcGroups = []; + } + + type2bl[uLine.type].ssrcGroups = + type2bl[uLine.type].ssrcGroups.concat( + uLine.ssrcGroups); + } + + if (type2bl[uLine.type] === uLine) { + // Plan B mids are in ['audio', 'video', 'data'] + uLine.mid = uLine.type; + + // Plan B doesn't support/need the bundle-only attribute. + delete uLine.bundleOnly; + + // In Plan B the msid is an SSRC attribute. + delete uLine.msid; + + if (uLine.type == media[0].type) { + types.unshift(uLine.type); + // Add the channel to the new media array. + session.media.unshift(uLine); + } else { + types.push(uLine.type); + // Add the channel to the new media array. + session.media.push(uLine); + } + } + }); + + if (typeof session.groups !== 'undefined') { + // We regenerate the BUNDLE group with the new mids. + session.groups.some(function(group) { + if (group.type === 'BUNDLE') { + group.mids = types.join(' '); + return true; + } + }); + } + + // msid semantic + session.msidSemantic = { + semantic: 'WMS', + token: '*' + }; + + var resStr = transform.write(session); + + return new RTCSessionDescription({ + type: desc.type, + sdp: resStr + }); + + //#endregion +}; + +/* follow rules defined in RFC4145 */ +function addSetupAttr(uLine) { + if (typeof uLine.setup === 'undefined') { + return; + } + + if (uLine.setup === "active") { + uLine.setup = "passive"; + } else if (uLine.setup === "passive") { + uLine.setup = "active"; + } +} + +/** + * This method transforms a Plan B SDP to an equivalent Unified Plan SDP. A + * PeerConnection wrapper transforms the SDP to Unified Plan before passing it + * to FF. + * + * @param desc + * @returns {*} + */ +Interop.prototype.toUnifiedPlan = function(desc) { + var self = this; + //#region Preliminary input validation. + + if (typeof desc !== 'object' || desc === null || + typeof desc.sdp !== 'string') { + console.warn('An empty description was passed as an argument.'); + return desc; + } + + var session = transform.parse(desc.sdp); + + // If the SDP contains no media, there's nothing to transform. + if (typeof session.media === 'undefined' || + !Array.isArray(session.media) || session.media.length === 0) { + console.warn('The description has no media.'); + return desc; + } + + // Try some heuristics to "make sure" this is a Plan B SDP. Plan B SDP has + // a video, an audio and a data "channel" at most. + if (session.media.length > 3 || !session.media.every(function(m) { + return ['video', 'audio', 'data'].indexOf(m.mid) !== -1; + })) { + console.warn('This description does not look like Plan B.'); + return desc; + } + + // Make sure this Plan B SDP can be converted to a Unified Plan SDP. + var mids = []; + session.media.forEach(function(m) { + mids.push(m.mid); + }); + + var hasBundle = false; + if (typeof session.groups !== 'undefined' && + Array.isArray(session.groups)) { + hasBundle = session.groups.every(function(g) { + return g.type !== 'BUNDLE' || + arrayEquals.apply(g.mids.sort(), [mids.sort()]); + }); + } + + if (!hasBundle) { + var mustBeBundle = false; + + session.media.forEach(function(m) { + if (m.direction !== 'inactive') { + mustBeBundle = true; + } + }); + + if (mustBeBundle) { + throw new Error("Cannot convert to Unified Plan because m-lines that" + + " are not bundled were found."); + } + } + + //#endregion + + + //#region Convert from Plan B to Unified Plan. + + // Unfortunately, a Plan B offer/answer doesn't have enough information to + // rebuild an equivalent Unified Plan offer/answer. + // + // For example, if this is a local answer (in Unified Plan style) that we + // convert to Plan B prior to handing it over to the application (the + // PeerConnection wrapper called us, for instance, after a successful + // createAnswer), we want to remember the m-line at which we've seen the + // (local) SSRC. That's because when the application wants to do call the + // SLD method, forcing us to do the inverse transformation (from Plan B to + // Unified Plan), we need to know to which m-line to assign the (local) + // SSRC. We also need to know all the other m-lines that the original + // answer had and include them in the transformed answer as well. + // + // Another example is if this is a remote offer that we convert to Plan B + // prior to giving it to the application, we want to remember the mid at + // which we've seen the (remote) SSRC. + // + // In the iteration that follows, we use the cached Unified Plan (if it + // exists) to assign mids to ssrcs. + + var type; + if (desc.type === 'answer') { + type = 'offer'; + } else if (desc.type === 'offer') { + type = 'answer'; + } else { + throw new Error("Type '" + desc.type + "' not supported."); + } + + var cached; + if (typeof this.cache[type] !== 'undefined') { + cached = transform.parse(this.cache[type]); + } + + var recvonlySsrcs = { + audio: {}, + video: {} + }; + + // A helper map that sends mids to m-line objects. We use it later to + // rebuild the Unified Plan style session.media array. + var mid2ul = {}; + var bIdx = 0; + var uIdx = 0; + + var sources2ul = {}; + + var candidates; + var iceUfrag; + var icePwd; + var fingerprint; + var payloads = {}; + var rtcpFb = {}; + var rtp = {}; + + session.media.forEach(function(bLine) { + if ((typeof bLine.rtcpMux !== 'string' || + bLine.rtcpMux !== 'rtcp-mux') && + bLine.direction !== 'inactive') { + throw new Error("Cannot convert to Unified Plan because m-lines " + + "without the rtcp-mux attribute were found."); + } + + if (bLine.type === 'application') { + mid2ul[bLine.mid] = bLine; + return; + } + + // With rtcp-mux and bundle all the channels should have the same ICE + // stuff. + var sources = bLine.sources; + var ssrcGroups = bLine.ssrcGroups; + var port = bLine.port; + + /* Chrome adds different candidates even using bundle, so we concat the candidates list */ + if (typeof bLine.candidates != 'undefined') { + if (typeof candidates != 'undefined') { + candidates = candidates.concat(bLine.candidates); + } else { + candidates = bLine.candidates; + } + } + + if ((typeof iceUfrag != 'undefined') && (typeof bLine.iceUfrag != 'undefined') && (iceUfrag != bLine.iceUfrag)) { + throw new Error("Only BUNDLE supported, iceUfrag must be the same for all m-lines.\n" + + "\tLast iceUfrag: " + iceUfrag + "\n" + + "\tNew iceUfrag: " + bLine.iceUfrag + ); + } + + if (typeof bLine.iceUfrag != 'undefined') { + iceUfrag = bLine.iceUfrag; + } + + if ((typeof icePwd != 'undefined') && (typeof bLine.icePwd != 'undefined') && (icePwd != bLine.icePwd)) { + throw new Error("Only BUNDLE supported, icePwd must be the same for all m-lines.\n" + + "\tLast icePwd: " + icePwd + "\n" + + "\tNew icePwd: " + bLine.icePwd + ); + } + + if (typeof bLine.icePwd != 'undefined') { + icePwd = bLine.icePwd; + } + + if ((typeof fingerprint != 'undefined') && (typeof bLine.fingerprint != 'undefined') && + (fingerprint.type != bLine.fingerprint.type || fingerprint.hash != bLine.fingerprint.hash)) { + throw new Error("Only BUNDLE supported, fingerprint must be the same for all m-lines.\n" + + "\tLast fingerprint: " + JSON.stringify(fingerprint) + "\n" + + "\tNew fingerprint: " + JSON.stringify(bLine.fingerprint) + ); + } + + if (typeof bLine.fingerprint != 'undefined') { + fingerprint = bLine.fingerprint; + } + + payloads[bLine.type] = bLine.payloads; + rtcpFb[bLine.type] = bLine.rtcpFb; + rtp[bLine.type] = bLine.rtp; + + // inverted ssrc group map + var ssrc2group = {}; + if (typeof ssrcGroups !== 'undefined' && Array.isArray(ssrcGroups)) { + ssrcGroups.forEach(function (ssrcGroup) { + // XXX This might brake if an SSRC is in more than one group + // for some reason. + if (typeof ssrcGroup.ssrcs !== 'undefined' && + Array.isArray(ssrcGroup.ssrcs)) { + ssrcGroup.ssrcs.forEach(function (ssrc) { + if (typeof ssrc2group[ssrc] === 'undefined') { + ssrc2group[ssrc] = []; + } + + ssrc2group[ssrc].push(ssrcGroup); + }); + } + }); + } + + // ssrc to m-line index. + var ssrc2ml = {}; + + if (typeof sources === 'object') { + + // We'll use the "bLine" object as a prototype for each new "mLine" + // that we create, but first we need to clean it up a bit. + delete bLine.sources; + delete bLine.ssrcGroups; + delete bLine.candidates; + delete bLine.iceUfrag; + delete bLine.icePwd; + delete bLine.fingerprint; + delete bLine.port; + delete bLine.mid; + + // Explode the Plan B channel sources with one m-line per source. + Object.keys(sources).forEach(function(ssrc) { + + // The (unified) m-line for this SSRC. We either create it from + // scratch or, if it's a grouped SSRC, we re-use a related + // mline. In other words, if the source is grouped with another + // source, put the two together in the same m-line. + var uLine; + + // We assume here that we are the answerer in the O/A, so any + // offers which we translate come from the remote side, while + // answers are local. So the check below is to make that we + // handle receive-only SSRCs in a special way only if they come + // from the remote side. + if (desc.type==='offer') { + // We want to detect SSRCs which are used by a remote peer + // in an m-line with direction=recvonly (i.e. they are + // being used for RTCP only). + // This information would have gotten lost if the remote + // peer used Unified Plan and their local description was + // translated to Plan B. So we use the lack of an MSID + // attribute to deduce a "receive only" SSRC. + if (!sources[ssrc].msid) { + recvonlySsrcs[bLine.type][ssrc] = sources[ssrc]; + // Receive-only SSRCs must not create new m-lines. We + // will assign them to an existing m-line later. + return; + } + } + + if (typeof ssrc2group[ssrc] !== 'undefined' && + Array.isArray(ssrc2group[ssrc])) { + ssrc2group[ssrc].some(function (ssrcGroup) { + // ssrcGroup.ssrcs *is* an Array, no need to check + // again here. + return ssrcGroup.ssrcs.some(function (related) { + if (typeof ssrc2ml[related] === 'object') { + uLine = ssrc2ml[related]; + return true; + } + }); + }); + } + + if (typeof uLine === 'object') { + // the m-line already exists. Just add the source. + uLine.sources[ssrc] = sources[ssrc]; + delete sources[ssrc].msid; + } else { + // Use the "bLine" as a prototype for the "uLine". + uLine = Object.create(bLine); + ssrc2ml[ssrc] = uLine; + + if (typeof sources[ssrc].msid !== 'undefined') { + // Assign the msid of the source to the m-line. Note + // that it is not guaranteed that the source will have + // msid. In particular "recvonly" sources don't have an + // msid. Note that "recvonly" is a term only defined + // for m-lines. + uLine.msid = sources[ssrc].msid; + delete sources[ssrc].msid; + } + + // We assign one SSRC per media line. + uLine.sources = {}; + uLine.sources[ssrc] = sources[ssrc]; + uLine.ssrcGroups = ssrc2group[ssrc]; + + // Use the cached Unified Plan SDP (if it exists) to assign + // SSRCs to mids. + if (typeof cached !== 'undefined' && + typeof cached.media !== 'undefined' && + Array.isArray(cached.media)) { + + cached.media.forEach(function (m) { + if (typeof m.sources === 'object') { + Object.keys(m.sources).forEach(function (s) { + if (s === ssrc) { + uLine.mid = m.mid; + } + }); + } + }); + } + + if (typeof uLine.mid === 'undefined') { + + // If this is an SSRC that we see for the first time + // assign it a new mid. This is typically the case when + // this method is called to transform a remote + // description for the first time or when there is a + // new SSRC in the remote description because a new + // peer has joined the conference. Local SSRCs should + // have already been added to the map in the toPlanB + // method. + // + // Because FF generates answers in Unified Plan style, + // we MUST already have a cached answer with all the + // local SSRCs mapped to some m-line/mid. + + uLine.mid = [bLine.type, '-', ssrc].join(''); + } + + // Include the candidates in the 1st media line. + uLine.candidates = candidates; + uLine.iceUfrag = iceUfrag; + uLine.icePwd = icePwd; + uLine.fingerprint = fingerprint; + uLine.port = port; + + mid2ul[uLine.mid] = uLine; + sources2ul[uIdx] = uLine.sources; + + self.cache.mlU2BMap[uIdx] = bIdx; + if (typeof self.cache.mlB2UMap[bIdx] === 'undefined') { + self.cache.mlB2UMap[bIdx] = uIdx; + } + uIdx++; + } + }); + } else { + var uLine = bLine; + + uLine.candidates = candidates; + uLine.iceUfrag = iceUfrag; + uLine.icePwd = icePwd; + uLine.fingerprint = fingerprint; + uLine.port = port; + + mid2ul[uLine.mid] = uLine; + + self.cache.mlU2BMap[uIdx] = bIdx; + if (typeof self.cache.mlB2UMap[bIdx] === 'undefined') { + self.cache.mlB2UMap[bIdx] = uIdx; + } + } + + bIdx++; + }); + + // Rebuild the media array in the right order and add the missing mLines + // (missing from the Plan B SDP). + session.media = []; + mids = []; // reuse + + if (desc.type === 'answer') { + + // The media lines in the answer must match the media lines in the + // offer. The order is important too. Here we assume that Firefox is + // the answerer, so we merely have to use the reconstructed (unified) + // answer to update the cached (unified) answer accordingly. + // + // In the general case, one would have to use the cached (unified) + // offer to find the m-lines that are missing from the reconstructed + // answer, potentially grabbing them from the cached (unified) answer. + // One has to be careful with this approach because inactive m-lines do + // not always have an mid, making it tricky (impossible?) to find where + // exactly and which m-lines are missing from the reconstructed answer. + + for (var i = 0; i < cached.media.length; i++) { + var uLine = cached.media[i]; + + delete uLine.msid; + delete uLine.sources; + delete uLine.ssrcGroups; + + if (typeof sources2ul[i] === 'undefined') { + if (!uLine.direction + || uLine.direction === 'sendrecv') + uLine.direction = 'recvonly'; + else if (uLine.direction === 'sendonly') + uLine.direction = 'inactive'; + } else { + if (!uLine.direction + || uLine.direction === 'sendrecv') + uLine.direction = 'sendrecv'; + else if (uLine.direction === 'recvonly') + uLine.direction = 'sendonly'; + } + + uLine.sources = sources2ul[i]; + uLine.candidates = candidates; + uLine.iceUfrag = iceUfrag; + uLine.icePwd = icePwd; + uLine.fingerprint = fingerprint; + + uLine.rtp = rtp[uLine.type]; + uLine.payloads = payloads[uLine.type]; + uLine.rtcpFb = rtcpFb[uLine.type]; + + session.media.push(uLine); + + if (typeof uLine.mid === 'string') { + // inactive lines don't/may not have an mid. + mids.push(uLine.mid); + } + } + } else { + + // SDP offer/answer (and the JSEP spec) forbids removing an m-section + // under any circumstances. If we are no longer interested in sending a + // track, we just remove the msid and ssrc attributes and set it to + // either a=recvonly (as the reofferer, we must use recvonly if the + // other side was previously sending on the m-section, but we can also + // leave the possibility open if it wasn't previously in use), or + // a=inactive. + + if (typeof cached !== 'undefined' && + typeof cached.media !== 'undefined' && + Array.isArray(cached.media)) { + cached.media.forEach(function(uLine) { + mids.push(uLine.mid); + if (typeof mid2ul[uLine.mid] !== 'undefined') { + session.media.push(mid2ul[uLine.mid]); + } else { + delete uLine.msid; + delete uLine.sources; + delete uLine.ssrcGroups; + + if (!uLine.direction + || uLine.direction === 'sendrecv') { + uLine.direction = 'sendonly'; + } + if (!uLine.direction + || uLine.direction === 'recvonly') { + uLine.direction = 'inactive'; + } + + addSetupAttr (uLine); + session.media.push(uLine); + } + }); + } + + // Add all the remaining (new) m-lines of the transformed SDP. + Object.keys(mid2ul).forEach(function(mid) { + if (mids.indexOf(mid) === -1) { + mids.push(mid); + if (mid2ul[mid].direction === 'recvonly') { + // This is a remote recvonly channel. Add its SSRC to the + // appropriate sendrecv or sendonly channel. + // TODO(gp) what if we don't have sendrecv/sendonly + // channel? + + var done = false; + + session.media.some(function (uLine) { + if ((uLine.direction === 'sendrecv' || + uLine.direction === 'sendonly') && + uLine.type === mid2ul[mid].type) { + // mid2ul[mid] shouldn't have any ssrc-groups + Object.keys(mid2ul[mid].sources).forEach( + function (ssrc) { + uLine.sources[ssrc] = + mid2ul[mid].sources[ssrc]; + }); + + done = true; + return true; + } + }); + + if (!done) { + session.media.push(mid2ul[mid]); + } + } else { + session.media.push(mid2ul[mid]); + } + } + }); + } + + // After we have constructed the Plan Unified m-lines we can figure out + // where (in which m-line) to place the 'recvonly SSRCs'. + // Note: we assume here that we are the answerer in the O/A, so any offers + // which we translate come from the remote side, while answers are local + // (and so our last local description is cached as an 'answer'). + ["audio", "video"].forEach(function (type) { + if (!session || !session.media || !Array.isArray(session.media)) + return; + + var idx = null; + if (Object.keys(recvonlySsrcs[type]).length > 0) { + idx = self.getFirstSendingIndexFromAnswer(type); + if (idx === null){ + // If this is the first offer we receive, we don't have a + // cached answer. Assume that we will be sending media using + // the first m-line for each media type. + + for (var i = 0; i < session.media.length; i++) { + if (session.media[i].type === type) { + idx = i; + break; + } + } + } + } + + if (idx && session.media.length > idx) { + var mLine = session.media[idx]; + Object.keys(recvonlySsrcs[type]).forEach(function(ssrc) { + if (mLine.sources && mLine.sources[ssrc]) { + console.warn("Replacing an existing SSRC."); + } + if (!mLine.sources) { + mLine.sources = {}; + } + + mLine.sources[ssrc] = recvonlySsrcs[type][ssrc]; + }); + } + }); + + if (typeof session.groups !== 'undefined') { + // We regenerate the BUNDLE group (since we regenerated the mids) + session.groups.some(function(group) { + if (group.type === 'BUNDLE') { + group.mids = mids.join(' '); + return true; + } + }); + } + + // msid semantic + session.msidSemantic = { + semantic: 'WMS', + token: '*' + }; + + var resStr = transform.write(session); + + // Cache the transformed SDP (Unified Plan) for later re-use in this + // function. + this.cache[desc.type] = resStr; + + return new RTCSessionDescription({ + type: desc.type, + sdp: resStr + }); + + //#endregion +}; + +},{"./array-equals":15,"./transform":18}],18:[function(require,module,exports){ +/* Copyright @ 2015 Atlassian Pty Ltd + * + * 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. + */ + +var transform = require('sdp-transform'); + +exports.write = function(session, opts) { + + if (typeof session !== 'undefined' && + typeof session.media !== 'undefined' && + Array.isArray(session.media)) { + + session.media.forEach(function (mLine) { + // expand sources to ssrcs + if (typeof mLine.sources !== 'undefined' && + Object.keys(mLine.sources).length !== 0) { + mLine.ssrcs = []; + Object.keys(mLine.sources).forEach(function (ssrc) { + var source = mLine.sources[ssrc]; + Object.keys(source).forEach(function (attribute) { + mLine.ssrcs.push({ + id: ssrc, + attribute: attribute, + value: source[attribute] + }); + }); + }); + delete mLine.sources; + } + + // join ssrcs in ssrc groups + if (typeof mLine.ssrcGroups !== 'undefined' && + Array.isArray(mLine.ssrcGroups)) { + mLine.ssrcGroups.forEach(function (ssrcGroup) { + if (typeof ssrcGroup.ssrcs !== 'undefined' && + Array.isArray(ssrcGroup.ssrcs)) { + ssrcGroup.ssrcs = ssrcGroup.ssrcs.join(' '); + } + }); + } + }); + } + + // join group mids + if (typeof session !== 'undefined' && + typeof session.groups !== 'undefined' && Array.isArray(session.groups)) { + + session.groups.forEach(function (g) { + if (typeof g.mids !== 'undefined' && Array.isArray(g.mids)) { + g.mids = g.mids.join(' '); + } + }); + } + + return transform.write(session, opts); +}; + +exports.parse = function(sdp) { + var session = transform.parse(sdp); + + if (typeof session !== 'undefined' && typeof session.media !== 'undefined' && + Array.isArray(session.media)) { + + session.media.forEach(function (mLine) { + // group sources attributes by ssrc + if (typeof mLine.ssrcs !== 'undefined' && Array.isArray(mLine.ssrcs)) { + mLine.sources = {}; + mLine.ssrcs.forEach(function (ssrc) { + if (!mLine.sources[ssrc.id]) + mLine.sources[ssrc.id] = {}; + mLine.sources[ssrc.id][ssrc.attribute] = ssrc.value; + }); + + delete mLine.ssrcs; + } + + // split ssrcs in ssrc groups + if (typeof mLine.ssrcGroups !== 'undefined' && + Array.isArray(mLine.ssrcGroups)) { + mLine.ssrcGroups.forEach(function (ssrcGroup) { + if (typeof ssrcGroup.ssrcs === 'string') { + ssrcGroup.ssrcs = ssrcGroup.ssrcs.split(' '); + } + }); + } + }); + } + // split group mids + if (typeof session !== 'undefined' && + typeof session.groups !== 'undefined' && Array.isArray(session.groups)) { + + session.groups.forEach(function (g) { + if (typeof g.mids === 'string') { + g.mids = g.mids.split(' '); + } + }); + } + + return session; +}; + + +},{"sdp-transform":12}],19:[function(require,module,exports){ + /* eslint-env node */ +'use strict'; + +// SDP helpers. +var SDPUtils = {}; + +// Generate an alphanumeric identifier for cname or mids. +// TODO: use UUIDs instead? https://gist.github.com/jed/982883 +SDPUtils.generateIdentifier = function() { + return Math.random().toString(36).substr(2, 10); +}; + +// The RTCP CNAME used by all peerconnections from the same JS. +SDPUtils.localCName = SDPUtils.generateIdentifier(); + +// Splits SDP into lines, dealing with both CRLF and LF. +SDPUtils.splitLines = function(blob) { + return blob.trim().split('\n').map(function(line) { + return line.trim(); + }); +}; +// Splits SDP into sessionpart and mediasections. Ensures CRLF. +SDPUtils.splitSections = function(blob) { + var parts = blob.split('\nm='); + return parts.map(function(part, index) { + return (index > 0 ? 'm=' + part : part).trim() + '\r\n'; + }); +}; + +// returns the session description. +SDPUtils.getDescription = function(blob) { + var sections = SDPUtils.splitSections(blob); + return sections && sections[0]; +}; + +// returns the individual media sections. +SDPUtils.getMediaSections = function(blob) { + var sections = SDPUtils.splitSections(blob); + sections.shift(); + return sections; +}; + +// Returns lines that start with a certain prefix. +SDPUtils.matchPrefix = function(blob, prefix) { + return SDPUtils.splitLines(blob).filter(function(line) { + return line.indexOf(prefix) === 0; + }); +}; + +// Parses an ICE candidate line. Sample input: +// candidate:702786350 2 udp 41819902 8.8.8.8 60769 typ relay raddr 8.8.8.8 +// rport 55996" +SDPUtils.parseCandidate = function(line) { + var parts; + // Parse both variants. + if (line.indexOf('a=candidate:') === 0) { + parts = line.substring(12).split(' '); + } else { + parts = line.substring(10).split(' '); + } + + var candidate = { + foundation: parts[0], + component: parseInt(parts[1], 10), + protocol: parts[2].toLowerCase(), + priority: parseInt(parts[3], 10), + ip: parts[4], + port: parseInt(parts[5], 10), + // skip parts[6] == 'typ' + type: parts[7] + }; + + for (var i = 8; i < parts.length; i += 2) { + switch (parts[i]) { + case 'raddr': + candidate.relatedAddress = parts[i + 1]; + break; + case 'rport': + candidate.relatedPort = parseInt(parts[i + 1], 10); + break; + case 'tcptype': + candidate.tcpType = parts[i + 1]; + break; + case 'ufrag': + candidate.ufrag = parts[i + 1]; // for backward compability. + candidate.usernameFragment = parts[i + 1]; + break; + default: // extension handling, in particular ufrag + candidate[parts[i]] = parts[i + 1]; + break; + } + } + return candidate; +}; + +// Translates a candidate object into SDP candidate attribute. +SDPUtils.writeCandidate = function(candidate) { + var sdp = []; + sdp.push(candidate.foundation); + sdp.push(candidate.component); + sdp.push(candidate.protocol.toUpperCase()); + sdp.push(candidate.priority); + sdp.push(candidate.ip); + sdp.push(candidate.port); + + var type = candidate.type; + sdp.push('typ'); + sdp.push(type); + if (type !== 'host' && candidate.relatedAddress && + candidate.relatedPort) { + sdp.push('raddr'); + sdp.push(candidate.relatedAddress); // was: relAddr + sdp.push('rport'); + sdp.push(candidate.relatedPort); // was: relPort + } + if (candidate.tcpType && candidate.protocol.toLowerCase() === 'tcp') { + sdp.push('tcptype'); + sdp.push(candidate.tcpType); + } + if (candidate.usernameFragment || candidate.ufrag) { + sdp.push('ufrag'); + sdp.push(candidate.usernameFragment || candidate.ufrag); + } + return 'candidate:' + sdp.join(' '); +}; + +// Parses an ice-options line, returns an array of option tags. +// a=ice-options:foo bar +SDPUtils.parseIceOptions = function(line) { + return line.substr(14).split(' '); +} + +// Parses an rtpmap line, returns RTCRtpCoddecParameters. Sample input: +// a=rtpmap:111 opus/48000/2 +SDPUtils.parseRtpMap = function(line) { + var parts = line.substr(9).split(' '); + var parsed = { + payloadType: parseInt(parts.shift(), 10) // was: id + }; + + parts = parts[0].split('/'); + + parsed.name = parts[0]; + parsed.clockRate = parseInt(parts[1], 10); // was: clockrate + // was: channels + parsed.numChannels = parts.length === 3 ? parseInt(parts[2], 10) : 1; + return parsed; +}; + +// Generate an a=rtpmap line from RTCRtpCodecCapability or +// RTCRtpCodecParameters. +SDPUtils.writeRtpMap = function(codec) { + var pt = codec.payloadType; + if (codec.preferredPayloadType !== undefined) { + pt = codec.preferredPayloadType; + } + return 'a=rtpmap:' + pt + ' ' + codec.name + '/' + codec.clockRate + + (codec.numChannels !== 1 ? '/' + codec.numChannels : '') + '\r\n'; +}; + +// Parses an a=extmap line (headerextension from RFC 5285). Sample input: +// a=extmap:2 urn:ietf:params:rtp-hdrext:toffset +// a=extmap:2/sendonly urn:ietf:params:rtp-hdrext:toffset +SDPUtils.parseExtmap = function(line) { + var parts = line.substr(9).split(' '); + return { + id: parseInt(parts[0], 10), + direction: parts[0].indexOf('/') > 0 ? parts[0].split('/')[1] : 'sendrecv', + uri: parts[1] + }; +}; + +// Generates a=extmap line from RTCRtpHeaderExtensionParameters or +// RTCRtpHeaderExtension. +SDPUtils.writeExtmap = function(headerExtension) { + return 'a=extmap:' + (headerExtension.id || headerExtension.preferredId) + + (headerExtension.direction && headerExtension.direction !== 'sendrecv' + ? '/' + headerExtension.direction + : '') + + ' ' + headerExtension.uri + '\r\n'; +}; + +// Parses an ftmp line, returns dictionary. Sample input: +// a=fmtp:96 vbr=on;cng=on +// Also deals with vbr=on; cng=on +SDPUtils.parseFmtp = function(line) { + var parsed = {}; + var kv; + var parts = line.substr(line.indexOf(' ') + 1).split(';'); + for (var j = 0; j < parts.length; j++) { + kv = parts[j].trim().split('='); + parsed[kv[0].trim()] = kv[1]; + } + return parsed; +}; + +// Generates an a=ftmp line from RTCRtpCodecCapability or RTCRtpCodecParameters. +SDPUtils.writeFmtp = function(codec) { + var line = ''; + var pt = codec.payloadType; + if (codec.preferredPayloadType !== undefined) { + pt = codec.preferredPayloadType; + } + if (codec.parameters && Object.keys(codec.parameters).length) { + var params = []; + Object.keys(codec.parameters).forEach(function(param) { + params.push(param + '=' + codec.parameters[param]); + }); + line += 'a=fmtp:' + pt + ' ' + params.join(';') + '\r\n'; + } + return line; +}; + +// Parses an rtcp-fb line, returns RTCPRtcpFeedback object. Sample input: +// a=rtcp-fb:98 nack rpsi +SDPUtils.parseRtcpFb = function(line) { + var parts = line.substr(line.indexOf(' ') + 1).split(' '); + return { + type: parts.shift(), + parameter: parts.join(' ') + }; +}; +// Generate a=rtcp-fb lines from RTCRtpCodecCapability or RTCRtpCodecParameters. +SDPUtils.writeRtcpFb = function(codec) { + var lines = ''; + var pt = codec.payloadType; + if (codec.preferredPayloadType !== undefined) { + pt = codec.preferredPayloadType; + } + if (codec.rtcpFeedback && codec.rtcpFeedback.length) { + // FIXME: special handling for trr-int? + codec.rtcpFeedback.forEach(function(fb) { + lines += 'a=rtcp-fb:' + pt + ' ' + fb.type + + (fb.parameter && fb.parameter.length ? ' ' + fb.parameter : '') + + '\r\n'; + }); + } + return lines; +}; + +// Parses an RFC 5576 ssrc media attribute. Sample input: +// a=ssrc:3735928559 cname:something +SDPUtils.parseSsrcMedia = function(line) { + var sp = line.indexOf(' '); + var parts = { + ssrc: parseInt(line.substr(7, sp - 7), 10) + }; + var colon = line.indexOf(':', sp); + if (colon > -1) { + parts.attribute = line.substr(sp + 1, colon - sp - 1); + parts.value = line.substr(colon + 1); + } else { + parts.attribute = line.substr(sp + 1); + } + return parts; +}; + +// Extracts the MID (RFC 5888) from a media section. +// returns the MID or undefined if no mid line was found. +SDPUtils.getMid = function(mediaSection) { + var mid = SDPUtils.matchPrefix(mediaSection, 'a=mid:')[0]; + if (mid) { + return mid.substr(6); + } +} + +SDPUtils.parseFingerprint = function(line) { + var parts = line.substr(14).split(' '); + return { + algorithm: parts[0].toLowerCase(), // algorithm is case-sensitive in Edge. + value: parts[1] + }; +}; + +// Extracts DTLS parameters from SDP media section or sessionpart. +// FIXME: for consistency with other functions this should only +// get the fingerprint line as input. See also getIceParameters. +SDPUtils.getDtlsParameters = function(mediaSection, sessionpart) { + var lines = SDPUtils.matchPrefix(mediaSection + sessionpart, + 'a=fingerprint:'); + // Note: a=setup line is ignored since we use the 'auto' role. + // Note2: 'algorithm' is not case sensitive except in Edge. + return { + role: 'auto', + fingerprints: lines.map(SDPUtils.parseFingerprint) + }; +}; + +// Serializes DTLS parameters to SDP. +SDPUtils.writeDtlsParameters = function(params, setupType) { + var sdp = 'a=setup:' + setupType + '\r\n'; + params.fingerprints.forEach(function(fp) { + sdp += 'a=fingerprint:' + fp.algorithm + ' ' + fp.value + '\r\n'; + }); + return sdp; +}; +// Parses ICE information from SDP media section or sessionpart. +// FIXME: for consistency with other functions this should only +// get the ice-ufrag and ice-pwd lines as input. +SDPUtils.getIceParameters = function(mediaSection, sessionpart) { + var lines = SDPUtils.splitLines(mediaSection); + // Search in session part, too. + lines = lines.concat(SDPUtils.splitLines(sessionpart)); + var iceParameters = { + usernameFragment: lines.filter(function(line) { + return line.indexOf('a=ice-ufrag:') === 0; + })[0].substr(12), + password: lines.filter(function(line) { + return line.indexOf('a=ice-pwd:') === 0; + })[0].substr(10) + }; + return iceParameters; +}; + +// Serializes ICE parameters to SDP. +SDPUtils.writeIceParameters = function(params) { + return 'a=ice-ufrag:' + params.usernameFragment + '\r\n' + + 'a=ice-pwd:' + params.password + '\r\n'; +}; + +// Parses the SDP media section and returns RTCRtpParameters. +SDPUtils.parseRtpParameters = function(mediaSection) { + var description = { + codecs: [], + headerExtensions: [], + fecMechanisms: [], + rtcp: [] + }; + var lines = SDPUtils.splitLines(mediaSection); + var mline = lines[0].split(' '); + for (var i = 3; i < mline.length; i++) { // find all codecs from mline[3..] + var pt = mline[i]; + var rtpmapline = SDPUtils.matchPrefix( + mediaSection, 'a=rtpmap:' + pt + ' ')[0]; + if (rtpmapline) { + var codec = SDPUtils.parseRtpMap(rtpmapline); + var fmtps = SDPUtils.matchPrefix( + mediaSection, 'a=fmtp:' + pt + ' '); + // Only the first a=fmtp: is considered. + codec.parameters = fmtps.length ? SDPUtils.parseFmtp(fmtps[0]) : {}; + codec.rtcpFeedback = SDPUtils.matchPrefix( + mediaSection, 'a=rtcp-fb:' + pt + ' ') + .map(SDPUtils.parseRtcpFb); + description.codecs.push(codec); + // parse FEC mechanisms from rtpmap lines. + switch (codec.name.toUpperCase()) { + case 'RED': + case 'ULPFEC': + description.fecMechanisms.push(codec.name.toUpperCase()); + break; + default: // only RED and ULPFEC are recognized as FEC mechanisms. + break; + } + } + } + SDPUtils.matchPrefix(mediaSection, 'a=extmap:').forEach(function(line) { + description.headerExtensions.push(SDPUtils.parseExtmap(line)); + }); + // FIXME: parse rtcp. + return description; +}; + +// Generates parts of the SDP media section describing the capabilities / +// parameters. +SDPUtils.writeRtpDescription = function(kind, caps) { + var sdp = ''; + + // Build the mline. + sdp += 'm=' + kind + ' '; + sdp += caps.codecs.length > 0 ? '9' : '0'; // reject if no codecs. + sdp += ' UDP/TLS/RTP/SAVPF '; + sdp += caps.codecs.map(function(codec) { + if (codec.preferredPayloadType !== undefined) { + return codec.preferredPayloadType; + } + return codec.payloadType; + }).join(' ') + '\r\n'; + + sdp += 'c=IN IP4 0.0.0.0\r\n'; + sdp += 'a=rtcp:9 IN IP4 0.0.0.0\r\n'; + + // Add a=rtpmap lines for each codec. Also fmtp and rtcp-fb. + caps.codecs.forEach(function(codec) { + sdp += SDPUtils.writeRtpMap(codec); + sdp += SDPUtils.writeFmtp(codec); + sdp += SDPUtils.writeRtcpFb(codec); + }); + var maxptime = 0; + caps.codecs.forEach(function(codec) { + if (codec.maxptime > maxptime) { + maxptime = codec.maxptime; + } + }); + if (maxptime > 0) { + sdp += 'a=maxptime:' + maxptime + '\r\n'; + } + sdp += 'a=rtcp-mux\r\n'; + + caps.headerExtensions.forEach(function(extension) { + sdp += SDPUtils.writeExtmap(extension); + }); + // FIXME: write fecMechanisms. + return sdp; +}; + +// Parses the SDP media section and returns an array of +// RTCRtpEncodingParameters. +SDPUtils.parseRtpEncodingParameters = function(mediaSection) { + var encodingParameters = []; + var description = SDPUtils.parseRtpParameters(mediaSection); + var hasRed = description.fecMechanisms.indexOf('RED') !== -1; + var hasUlpfec = description.fecMechanisms.indexOf('ULPFEC') !== -1; + + // filter a=ssrc:... cname:, ignore PlanB-msid + var ssrcs = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:') + .map(function(line) { + return SDPUtils.parseSsrcMedia(line); + }) + .filter(function(parts) { + return parts.attribute === 'cname'; + }); + var primarySsrc = ssrcs.length > 0 && ssrcs[0].ssrc; + var secondarySsrc; + + var flows = SDPUtils.matchPrefix(mediaSection, 'a=ssrc-group:FID') + .map(function(line) { + var parts = line.split(' '); + parts.shift(); + return parts.map(function(part) { + return parseInt(part, 10); + }); + }); + if (flows.length > 0 && flows[0].length > 1 && flows[0][0] === primarySsrc) { + secondarySsrc = flows[0][1]; + } + + description.codecs.forEach(function(codec) { + if (codec.name.toUpperCase() === 'RTX' && codec.parameters.apt) { + var encParam = { + ssrc: primarySsrc, + codecPayloadType: parseInt(codec.parameters.apt, 10), + rtx: { + ssrc: secondarySsrc + } + }; + encodingParameters.push(encParam); + if (hasRed) { + encParam = JSON.parse(JSON.stringify(encParam)); + encParam.fec = { + ssrc: secondarySsrc, + mechanism: hasUlpfec ? 'red+ulpfec' : 'red' + }; + encodingParameters.push(encParam); + } + } + }); + if (encodingParameters.length === 0 && primarySsrc) { + encodingParameters.push({ + ssrc: primarySsrc + }); + } + + // we support both b=AS and b=TIAS but interpret AS as TIAS. + var bandwidth = SDPUtils.matchPrefix(mediaSection, 'b='); + if (bandwidth.length) { + if (bandwidth[0].indexOf('b=TIAS:') === 0) { + bandwidth = parseInt(bandwidth[0].substr(7), 10); + } else if (bandwidth[0].indexOf('b=AS:') === 0) { + // use formula from JSEP to convert b=AS to TIAS value. + bandwidth = parseInt(bandwidth[0].substr(5), 10) * 1000 * 0.95 + - (50 * 40 * 8); + } else { + bandwidth = undefined; + } + encodingParameters.forEach(function(params) { + params.maxBitrate = bandwidth; + }); + } + return encodingParameters; +}; + +// parses http://draft.ortc.org/#rtcrtcpparameters* +SDPUtils.parseRtcpParameters = function(mediaSection) { + var rtcpParameters = {}; + + var cname; + // Gets the first SSRC. Note that with RTX there might be multiple + // SSRCs. + var remoteSsrc = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:') + .map(function(line) { + return SDPUtils.parseSsrcMedia(line); + }) + .filter(function(obj) { + return obj.attribute === 'cname'; + })[0]; + if (remoteSsrc) { + rtcpParameters.cname = remoteSsrc.value; + rtcpParameters.ssrc = remoteSsrc.ssrc; + } + + // Edge uses the compound attribute instead of reducedSize + // compound is !reducedSize + var rsize = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-rsize'); + rtcpParameters.reducedSize = rsize.length > 0; + rtcpParameters.compound = rsize.length === 0; + + // parses the rtcp-mux attrіbute. + // Note that Edge does not support unmuxed RTCP. + var mux = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-mux'); + rtcpParameters.mux = mux.length > 0; + + return rtcpParameters; +}; + +// parses either a=msid: or a=ssrc:... msid lines and returns +// the id of the MediaStream and MediaStreamTrack. +SDPUtils.parseMsid = function(mediaSection) { + var parts; + var spec = SDPUtils.matchPrefix(mediaSection, 'a=msid:'); + if (spec.length === 1) { + parts = spec[0].substr(7).split(' '); + return {stream: parts[0], track: parts[1]}; + } + var planB = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:') + .map(function(line) { + return SDPUtils.parseSsrcMedia(line); + }) + .filter(function(parts) { + return parts.attribute === 'msid'; + }); + if (planB.length > 0) { + parts = planB[0].value.split(' '); + return {stream: parts[0], track: parts[1]}; + } +}; + +// Generate a session ID for SDP. +// https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-20#section-5.2.1 +// recommends using a cryptographically random +ve 64-bit value +// but right now this should be acceptable and within the right range +SDPUtils.generateSessionId = function() { + return Math.random().toString().substr(2, 21); +}; + +// Write boilder plate for start of SDP +// sessId argument is optional - if not supplied it will +// be generated randomly +// sessVersion is optional and defaults to 2 +SDPUtils.writeSessionBoilerplate = function(sessId, sessVer) { + var sessionId; + var version = sessVer !== undefined ? sessVer : 2; + if (sessId) { + sessionId = sessId; + } else { + sessionId = SDPUtils.generateSessionId(); + } + // FIXME: sess-id should be an NTP timestamp. + return 'v=0\r\n' + + 'o=thisisadapterortc ' + sessionId + ' ' + version + ' IN IP4 127.0.0.1\r\n' + + 's=-\r\n' + + 't=0 0\r\n'; +}; + +SDPUtils.writeMediaSection = function(transceiver, caps, type, stream) { + var sdp = SDPUtils.writeRtpDescription(transceiver.kind, caps); + + // Map ICE parameters (ufrag, pwd) to SDP. + sdp += SDPUtils.writeIceParameters( + transceiver.iceGatherer.getLocalParameters()); + + // Map DTLS parameters to SDP. + sdp += SDPUtils.writeDtlsParameters( + transceiver.dtlsTransport.getLocalParameters(), + type === 'offer' ? 'actpass' : 'active'); + + sdp += 'a=mid:' + transceiver.mid + '\r\n'; + + if (transceiver.direction) { + sdp += 'a=' + transceiver.direction + '\r\n'; + } else if (transceiver.rtpSender && transceiver.rtpReceiver) { + sdp += 'a=sendrecv\r\n'; + } else if (transceiver.rtpSender) { + sdp += 'a=sendonly\r\n'; + } else if (transceiver.rtpReceiver) { + sdp += 'a=recvonly\r\n'; + } else { + sdp += 'a=inactive\r\n'; + } + + if (transceiver.rtpSender) { + // spec. + var msid = 'msid:' + stream.id + ' ' + + transceiver.rtpSender.track.id + '\r\n'; + sdp += 'a=' + msid; + + // for Chrome. + sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc + + ' ' + msid; + if (transceiver.sendEncodingParameters[0].rtx) { + sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc + + ' ' + msid; + sdp += 'a=ssrc-group:FID ' + + transceiver.sendEncodingParameters[0].ssrc + ' ' + + transceiver.sendEncodingParameters[0].rtx.ssrc + + '\r\n'; + } + } + // FIXME: this should be written by writeRtpDescription. + sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc + + ' cname:' + SDPUtils.localCName + '\r\n'; + if (transceiver.rtpSender && transceiver.sendEncodingParameters[0].rtx) { + sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc + + ' cname:' + SDPUtils.localCName + '\r\n'; + } + return sdp; +}; + +// Gets the direction from the mediaSection or the sessionpart. +SDPUtils.getDirection = function(mediaSection, sessionpart) { + // Look for sendrecv, sendonly, recvonly, inactive, default to sendrecv. + var lines = SDPUtils.splitLines(mediaSection); + for (var i = 0; i < lines.length; i++) { + switch (lines[i]) { + case 'a=sendrecv': + case 'a=sendonly': + case 'a=recvonly': + case 'a=inactive': + return lines[i].substr(2); + default: + // FIXME: What should happen here? + } + } + if (sessionpart) { + return SDPUtils.getDirection(sessionpart); + } + return 'sendrecv'; +}; + +SDPUtils.getKind = function(mediaSection) { + var lines = SDPUtils.splitLines(mediaSection); + var mline = lines[0].split(' '); + return mline[0].substr(2); +}; + +SDPUtils.isRejected = function(mediaSection) { + return mediaSection.split(' ', 2)[1] === '0'; +}; + +SDPUtils.parseMLine = function(mediaSection) { + var lines = SDPUtils.splitLines(mediaSection); + var parts = lines[0].substr(2).split(' '); + return { + kind: parts[0], + port: parseInt(parts[1], 10), + protocol: parts[2], + fmt: parts.slice(3).join(' ') + }; +}; + +SDPUtils.parseOLine = function(mediaSection) { + var line = SDPUtils.matchPrefix(mediaSection, 'o=')[0]; + var parts = line.substr(2).split(' '); + return { + username: parts[0], + sessionId: parts[1], + sessionVersion: parseInt(parts[2], 10), + netType: parts[3], + addressType: parts[4], + address: parts[5], + }; +} + +// Expose public methods. +if (typeof module === 'object') { + module.exports = SDPUtils; +} + +},{}],20:[function(require,module,exports){ +/** + * UAParser.js v0.7.17 + * Lightweight JavaScript-based User-Agent string parser + * https://github.com/faisalman/ua-parser-js + * + * Copyright © 2012-2016 Faisal Salman + * Dual licensed under GPLv2 & MIT + */ + +(function (window, undefined) { + + 'use strict'; + + ////////////// + // Constants + ///////////// + + + var LIBVERSION = '0.7.17', + EMPTY = '', + UNKNOWN = '?', + FUNC_TYPE = 'function', + UNDEF_TYPE = 'undefined', + OBJ_TYPE = 'object', + STR_TYPE = 'string', + MAJOR = 'major', // deprecated + MODEL = 'model', + NAME = 'name', + TYPE = 'type', + VENDOR = 'vendor', + VERSION = 'version', + ARCHITECTURE= 'architecture', + CONSOLE = 'console', + MOBILE = 'mobile', + TABLET = 'tablet', + SMARTTV = 'smarttv', + WEARABLE = 'wearable', + EMBEDDED = 'embedded'; + + + /////////// + // Helper + ////////// + + + var util = { + extend : function (regexes, extensions) { + var margedRegexes = {}; + for (var i in regexes) { + if (extensions[i] && extensions[i].length % 2 === 0) { + margedRegexes[i] = extensions[i].concat(regexes[i]); + } else { + margedRegexes[i] = regexes[i]; + } + } + return margedRegexes; + }, + has : function (str1, str2) { + if (typeof str1 === "string") { + return str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1; + } else { + return false; + } + }, + lowerize : function (str) { + return str.toLowerCase(); + }, + major : function (version) { + return typeof(version) === STR_TYPE ? version.replace(/[^\d\.]/g,'').split(".")[0] : undefined; + }, + trim : function (str) { + return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); + } + }; + + + /////////////// + // Map helper + ////////////// + + + var mapper = { + + rgx : function (ua, arrays) { + + //var result = {}, + var i = 0, j, k, p, q, matches, match;//, args = arguments; + + /*// construct object barebones + for (p = 0; p < args[1].length; p++) { + q = args[1][p]; + result[typeof q === OBJ_TYPE ? q[0] : q] = undefined; + }*/ + + // loop through all regexes maps + while (i < arrays.length && !matches) { + + var regex = arrays[i], // even sequence (0,2,4,..) + props = arrays[i + 1]; // odd sequence (1,3,5,..) + j = k = 0; + + // try matching uastring with regexes + while (j < regex.length && !matches) { + + matches = regex[j++].exec(ua); + + if (!!matches) { + for (p = 0; p < props.length; p++) { + match = matches[++k]; + q = props[p]; + // check if given property is actually array + if (typeof q === OBJ_TYPE && q.length > 0) { + if (q.length == 2) { + if (typeof q[1] == FUNC_TYPE) { + // assign modified match + this[q[0]] = q[1].call(this, match); + } else { + // assign given value, ignore regex match + this[q[0]] = q[1]; + } + } else if (q.length == 3) { + // check whether function or regex + if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) { + // call function (usually string mapper) + this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined; + } else { + // sanitize match using given regex + this[q[0]] = match ? match.replace(q[1], q[2]) : undefined; + } + } else if (q.length == 4) { + this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined; + } + } else { + this[q] = match ? match : undefined; + } + } + } + } + i += 2; + } + // console.log(this); + //return this; + }, + + str : function (str, map) { + + for (var i in map) { + // check if array + if (typeof map[i] === OBJ_TYPE && map[i].length > 0) { + for (var j = 0; j < map[i].length; j++) { + if (util.has(map[i][j], str)) { + return (i === UNKNOWN) ? undefined : i; + } + } + } else if (util.has(map[i], str)) { + return (i === UNKNOWN) ? undefined : i; + } + } + return str; + } + }; + + + /////////////// + // String map + ////////////// + + + var maps = { + + browser : { + oldsafari : { + version : { + '1.0' : '/8', + '1.2' : '/1', + '1.3' : '/3', + '2.0' : '/412', + '2.0.2' : '/416', + '2.0.3' : '/417', + '2.0.4' : '/419', + '?' : '/' + } + } + }, + + device : { + amazon : { + model : { + 'Fire Phone' : ['SD', 'KF'] + } + }, + sprint : { + model : { + 'Evo Shift 4G' : '7373KT' + }, + vendor : { + 'HTC' : 'APA', + 'Sprint' : 'Sprint' + } + } + }, + + os : { + windows : { + version : { + 'ME' : '4.90', + 'NT 3.11' : 'NT3.51', + 'NT 4.0' : 'NT4.0', + '2000' : 'NT 5.0', + 'XP' : ['NT 5.1', 'NT 5.2'], + 'Vista' : 'NT 6.0', + '7' : 'NT 6.1', + '8' : 'NT 6.2', + '8.1' : 'NT 6.3', + '10' : ['NT 6.4', 'NT 10.0'], + 'RT' : 'ARM' + } + } + } + }; + + + ////////////// + // Regex map + ///////////// + + + var regexes = { + + browser : [[ + + // Presto based + /(opera\smini)\/([\w\.-]+)/i, // Opera Mini + /(opera\s[mobiletab]+).+version\/([\w\.-]+)/i, // Opera Mobi/Tablet + /(opera).+version\/([\w\.]+)/i, // Opera > 9.80 + /(opera)[\/\s]+([\w\.]+)/i // Opera < 9.80 + ], [NAME, VERSION], [ + + /(opios)[\/\s]+([\w\.]+)/i // Opera mini on iphone >= 8.0 + ], [[NAME, 'Opera Mini'], VERSION], [ + + /\s(opr)\/([\w\.]+)/i // Opera Webkit + ], [[NAME, 'Opera'], VERSION], [ + + // Mixed + /(kindle)\/([\w\.]+)/i, // Kindle + /(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?([\w\.]+)*/i, + // Lunascape/Maxthon/Netfront/Jasmine/Blazer + + // Trident based + /(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?([\w\.]*)/i, + // Avant/IEMobile/SlimBrowser/Baidu + /(?:ms|\()(ie)\s([\w\.]+)/i, // Internet Explorer + + // Webkit/KHTML based + /(rekonq)\/([\w\.]+)*/i, // Rekonq + /(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser)\/([\w\.-]+)/i + // Chromium/Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser + ], [NAME, VERSION], [ + + /(trident).+rv[:\s]([\w\.]+).+like\sgecko/i // IE11 + ], [[NAME, 'IE'], VERSION], [ + + /(edge)\/((\d+)?[\w\.]+)/i // Microsoft Edge + ], [NAME, VERSION], [ + + /(yabrowser)\/([\w\.]+)/i // Yandex + ], [[NAME, 'Yandex'], VERSION], [ + + /(puffin)\/([\w\.]+)/i // Puffin + ], [[NAME, 'Puffin'], VERSION], [ + + /((?:[\s\/])uc?\s?browser|(?:juc.+)ucweb)[\/\s]?([\w\.]+)/i + // UCBrowser + ], [[NAME, 'UCBrowser'], VERSION], [ + + /(comodo_dragon)\/([\w\.]+)/i // Comodo Dragon + ], [[NAME, /_/g, ' '], VERSION], [ + + /(micromessenger)\/([\w\.]+)/i // WeChat + ], [[NAME, 'WeChat'], VERSION], [ + + /(QQ)\/([\d\.]+)/i // QQ, aka ShouQ + ], [NAME, VERSION], [ + + /m?(qqbrowser)[\/\s]?([\w\.]+)/i // QQBrowser + ], [NAME, VERSION], [ + + /xiaomi\/miuibrowser\/([\w\.]+)/i // MIUI Browser + ], [VERSION, [NAME, 'MIUI Browser']], [ + + /;fbav\/([\w\.]+);/i // Facebook App for iOS & Android + ], [VERSION, [NAME, 'Facebook']], [ + + /headlesschrome(?:\/([\w\.]+)|\s)/i // Chrome Headless + ], [VERSION, [NAME, 'Chrome Headless']], [ + + /\swv\).+(chrome)\/([\w\.]+)/i // Chrome WebView + ], [[NAME, /(.+)/, '$1 WebView'], VERSION], [ + + /((?:oculus|samsung)browser)\/([\w\.]+)/i + ], [[NAME, /(.+(?:g|us))(.+)/, '$1 $2'], VERSION], [ // Oculus / Samsung Browser + + /android.+version\/([\w\.]+)\s+(?:mobile\s?safari|safari)*/i // Android Browser + ], [VERSION, [NAME, 'Android Browser']], [ + + /(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?([\w\.]+)/i + // Chrome/OmniWeb/Arora/Tizen/Nokia + ], [NAME, VERSION], [ + + /(dolfin)\/([\w\.]+)/i // Dolphin + ], [[NAME, 'Dolphin'], VERSION], [ + + /((?:android.+)crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS + ], [[NAME, 'Chrome'], VERSION], [ + + /(coast)\/([\w\.]+)/i // Opera Coast + ], [[NAME, 'Opera Coast'], VERSION], [ + + /fxios\/([\w\.-]+)/i // Firefox for iOS + ], [VERSION, [NAME, 'Firefox']], [ + + /version\/([\w\.]+).+?mobile\/\w+\s(safari)/i // Mobile Safari + ], [VERSION, [NAME, 'Mobile Safari']], [ + + /version\/([\w\.]+).+?(mobile\s?safari|safari)/i // Safari & Safari Mobile + ], [VERSION, NAME], [ + + /webkit.+?(gsa)\/([\w\.]+).+?(mobile\s?safari|safari)(\/[\w\.]+)/i // Google Search Appliance on iOS + ], [[NAME, 'GSA'], VERSION], [ + + /webkit.+?(mobile\s?safari|safari)(\/[\w\.]+)/i // Safari < 3.0 + ], [NAME, [VERSION, mapper.str, maps.browser.oldsafari.version]], [ + + /(konqueror)\/([\w\.]+)/i, // Konqueror + /(webkit|khtml)\/([\w\.]+)/i + ], [NAME, VERSION], [ + + // Gecko based + /(navigator|netscape)\/([\w\.-]+)/i // Netscape + ], [[NAME, 'Netscape'], VERSION], [ + /(swiftfox)/i, // Swiftfox + /(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?([\w\.\+]+)/i, + // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror + /(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/([\w\.-]+)/i, + // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix + /(mozilla)\/([\w\.]+).+rv\:.+gecko\/\d+/i, // Mozilla + + // Other + /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir)[\/\s]?([\w\.]+)/i, + // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Sleipnir + /(links)\s\(([\w\.]+)/i, // Links + /(gobrowser)\/?([\w\.]+)*/i, // GoBrowser + /(ice\s?browser)\/v?([\w\._]+)/i, // ICE Browser + /(mosaic)[\/\s]([\w\.]+)/i // Mosaic + ], [NAME, VERSION] + + /* ///////////////////// + // Media players BEGIN + //////////////////////// + + , [ + + /(apple(?:coremedia|))\/((\d+)[\w\._]+)/i, // Generic Apple CoreMedia + /(coremedia) v((\d+)[\w\._]+)/i + ], [NAME, VERSION], [ + + /(aqualung|lyssna|bsplayer)\/((\d+)?[\w\.-]+)/i // Aqualung/Lyssna/BSPlayer + ], [NAME, VERSION], [ + + /(ares|ossproxy)\s((\d+)[\w\.-]+)/i // Ares/OSSProxy + ], [NAME, VERSION], [ + + /(audacious|audimusicstream|amarok|bass|core|dalvik|gnomemplayer|music on console|nsplayer|psp-internetradioplayer|videos)\/((\d+)[\w\.-]+)/i, + // Audacious/AudiMusicStream/Amarok/BASS/OpenCORE/Dalvik/GnomeMplayer/MoC + // NSPlayer/PSP-InternetRadioPlayer/Videos + /(clementine|music player daemon)\s((\d+)[\w\.-]+)/i, // Clementine/MPD + /(lg player|nexplayer)\s((\d+)[\d\.]+)/i, + /player\/(nexplayer|lg player)\s((\d+)[\w\.-]+)/i // NexPlayer/LG Player + ], [NAME, VERSION], [ + /(nexplayer)\s((\d+)[\w\.-]+)/i // Nexplayer + ], [NAME, VERSION], [ + + /(flrp)\/((\d+)[\w\.-]+)/i // Flip Player + ], [[NAME, 'Flip Player'], VERSION], [ + + /(fstream|nativehost|queryseekspider|ia-archiver|facebookexternalhit)/i + // FStream/NativeHost/QuerySeekSpider/IA Archiver/facebookexternalhit + ], [NAME], [ + + /(gstreamer) souphttpsrc (?:\([^\)]+\)){0,1} libsoup\/((\d+)[\w\.-]+)/i + // Gstreamer + ], [NAME, VERSION], [ + + /(htc streaming player)\s[\w_]+\s\/\s((\d+)[\d\.]+)/i, // HTC Streaming Player + /(java|python-urllib|python-requests|wget|libcurl)\/((\d+)[\w\.-_]+)/i, + // Java/urllib/requests/wget/cURL + /(lavf)((\d+)[\d\.]+)/i // Lavf (FFMPEG) + ], [NAME, VERSION], [ + + /(htc_one_s)\/((\d+)[\d\.]+)/i // HTC One S + ], [[NAME, /_/g, ' '], VERSION], [ + + /(mplayer)(?:\s|\/)(?:(?:sherpya-){0,1}svn)(?:-|\s)(r\d+(?:-\d+[\w\.-]+){0,1})/i + // MPlayer SVN + ], [NAME, VERSION], [ + + /(mplayer)(?:\s|\/|[unkow-]+)((\d+)[\w\.-]+)/i // MPlayer + ], [NAME, VERSION], [ + + /(mplayer)/i, // MPlayer (no other info) + /(yourmuze)/i, // YourMuze + /(media player classic|nero showtime)/i // Media Player Classic/Nero ShowTime + ], [NAME], [ + + /(nero (?:home|scout))\/((\d+)[\w\.-]+)/i // Nero Home/Nero Scout + ], [NAME, VERSION], [ + + /(nokia\d+)\/((\d+)[\w\.-]+)/i // Nokia + ], [NAME, VERSION], [ + + /\s(songbird)\/((\d+)[\w\.-]+)/i // Songbird/Philips-Songbird + ], [NAME, VERSION], [ + + /(winamp)3 version ((\d+)[\w\.-]+)/i, // Winamp + /(winamp)\s((\d+)[\w\.-]+)/i, + /(winamp)mpeg\/((\d+)[\w\.-]+)/i + ], [NAME, VERSION], [ + + /(ocms-bot|tapinradio|tunein radio|unknown|winamp|inlight radio)/i // OCMS-bot/tap in radio/tunein/unknown/winamp (no other info) + // inlight radio + ], [NAME], [ + + /(quicktime|rma|radioapp|radioclientapplication|soundtap|totem|stagefright|streamium)\/((\d+)[\w\.-]+)/i + // QuickTime/RealMedia/RadioApp/RadioClientApplication/ + // SoundTap/Totem/Stagefright/Streamium + ], [NAME, VERSION], [ + + /(smp)((\d+)[\d\.]+)/i // SMP + ], [NAME, VERSION], [ + + /(vlc) media player - version ((\d+)[\w\.]+)/i, // VLC Videolan + /(vlc)\/((\d+)[\w\.-]+)/i, + /(xbmc|gvfs|xine|xmms|irapp)\/((\d+)[\w\.-]+)/i, // XBMC/gvfs/Xine/XMMS/irapp + /(foobar2000)\/((\d+)[\d\.]+)/i, // Foobar2000 + /(itunes)\/((\d+)[\d\.]+)/i // iTunes + ], [NAME, VERSION], [ + + /(wmplayer)\/((\d+)[\w\.-]+)/i, // Windows Media Player + /(windows-media-player)\/((\d+)[\w\.-]+)/i + ], [[NAME, /-/g, ' '], VERSION], [ + + /windows\/((\d+)[\w\.-]+) upnp\/[\d\.]+ dlnadoc\/[\d\.]+ (home media server)/i + // Windows Media Server + ], [VERSION, [NAME, 'Windows']], [ + + /(com\.riseupradioalarm)\/((\d+)[\d\.]*)/i // RiseUP Radio Alarm + ], [NAME, VERSION], [ + + /(rad.io)\s((\d+)[\d\.]+)/i, // Rad.io + /(radio.(?:de|at|fr))\s((\d+)[\d\.]+)/i + ], [[NAME, 'rad.io'], VERSION] + + ////////////////////// + // Media players END + ////////////////////*/ + + ], + + cpu : [[ + + /(?:(amd|x(?:(?:86|64)[_-])?|wow|win)64)[;\)]/i // AMD64 + ], [[ARCHITECTURE, 'amd64']], [ + + /(ia32(?=;))/i // IA32 (quicktime) + ], [[ARCHITECTURE, util.lowerize]], [ + + /((?:i[346]|x)86)[;\)]/i // IA32 + ], [[ARCHITECTURE, 'ia32']], [ + + // PocketPC mistakenly identified as PowerPC + /windows\s(ce|mobile);\sppc;/i + ], [[ARCHITECTURE, 'arm']], [ + + /((?:ppc|powerpc)(?:64)?)(?:\smac|;|\))/i // PowerPC + ], [[ARCHITECTURE, /ower/, '', util.lowerize]], [ + + /(sun4\w)[;\)]/i // SPARC + ], [[ARCHITECTURE, 'sparc']], [ + + /((?:avr32|ia64(?=;))|68k(?=\))|arm(?:64|(?=v\d+;))|(?=atmel\s)avr|(?:irix|mips|sparc)(?:64)?(?=;)|pa-risc)/i + // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC + ], [[ARCHITECTURE, util.lowerize]] + ], + + device : [[ + + /\((ipad|playbook);[\w\s\);-]+(rim|apple)/i // iPad/PlayBook + ], [MODEL, VENDOR, [TYPE, TABLET]], [ + + /applecoremedia\/[\w\.]+ \((ipad)/ // iPad + ], [MODEL, [VENDOR, 'Apple'], [TYPE, TABLET]], [ + + /(apple\s{0,1}tv)/i // Apple TV + ], [[MODEL, 'Apple TV'], [VENDOR, 'Apple']], [ + + /(archos)\s(gamepad2?)/i, // Archos + /(hp).+(touchpad)/i, // HP TouchPad + /(hp).+(tablet)/i, // HP Tablet + /(kindle)\/([\w\.]+)/i, // Kindle + /\s(nook)[\w\s]+build\/(\w+)/i, // Nook + /(dell)\s(strea[kpr\s\d]*[\dko])/i // Dell Streak + ], [VENDOR, MODEL, [TYPE, TABLET]], [ + + /(kf[A-z]+)\sbuild\/[\w\.]+.*silk\//i // Kindle Fire HD + ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [ + /(sd|kf)[0349hijorstuw]+\sbuild\/[\w\.]+.*silk\//i // Fire Phone + ], [[MODEL, mapper.str, maps.device.amazon.model], [VENDOR, 'Amazon'], [TYPE, MOBILE]], [ + + /\((ip[honed|\s\w*]+);.+(apple)/i // iPod/iPhone + ], [MODEL, VENDOR, [TYPE, MOBILE]], [ + /\((ip[honed|\s\w*]+);/i // iPod/iPhone + ], [MODEL, [VENDOR, 'Apple'], [TYPE, MOBILE]], [ + + /(blackberry)[\s-]?(\w+)/i, // BlackBerry + /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[\s_-]?([\w-]+)*/i, + // BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron + /(hp)\s([\w\s]+\w)/i, // HP iPAQ + /(asus)-?(\w+)/i // Asus + ], [VENDOR, MODEL, [TYPE, MOBILE]], [ + /\(bb10;\s(\w+)/i // BlackBerry 10 + ], [MODEL, [VENDOR, 'BlackBerry'], [TYPE, MOBILE]], [ + // Asus Tablets + /android.+(transfo[prime\s]{4,10}\s\w+|eeepc|slider\s\w+|nexus 7|padfone)/i + ], [MODEL, [VENDOR, 'Asus'], [TYPE, TABLET]], [ + + /(sony)\s(tablet\s[ps])\sbuild\//i, // Sony + /(sony)?(?:sgp.+)\sbuild\//i + ], [[VENDOR, 'Sony'], [MODEL, 'Xperia Tablet'], [TYPE, TABLET]], [ + /android.+\s([c-g]\d{4}|so[-l]\w+)\sbuild\//i + ], [MODEL, [VENDOR, 'Sony'], [TYPE, MOBILE]], [ + + /\s(ouya)\s/i, // Ouya + /(nintendo)\s([wids3u]+)/i // Nintendo + ], [VENDOR, MODEL, [TYPE, CONSOLE]], [ + + /android.+;\s(shield)\sbuild/i // Nvidia + ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, CONSOLE]], [ + + /(playstation\s[34portablevi]+)/i // Playstation + ], [MODEL, [VENDOR, 'Sony'], [TYPE, CONSOLE]], [ + + /(sprint\s(\w+))/i // Sprint Phones + ], [[VENDOR, mapper.str, maps.device.sprint.vendor], [MODEL, mapper.str, maps.device.sprint.model], [TYPE, MOBILE]], [ + + /(lenovo)\s?(S(?:5000|6000)+(?:[-][\w+]))/i // Lenovo tablets + ], [VENDOR, MODEL, [TYPE, TABLET]], [ + + /(htc)[;_\s-]+([\w\s]+(?=\))|\w+)*/i, // HTC + /(zte)-(\w+)*/i, // ZTE + /(alcatel|geeksphone|lenovo|nexian|panasonic|(?=;\s)sony)[_\s-]?([\w-]+)*/i + // Alcatel/GeeksPhone/Lenovo/Nexian/Panasonic/Sony + ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [ + + /(nexus\s9)/i // HTC Nexus 9 + ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [ + + /d\/huawei([\w\s-]+)[;\)]/i, + /(nexus\s6p)/i // Huawei + ], [MODEL, [VENDOR, 'Huawei'], [TYPE, MOBILE]], [ + + /(microsoft);\s(lumia[\s\w]+)/i // Microsoft Lumia + ], [VENDOR, MODEL, [TYPE, MOBILE]], [ + + /[\s\(;](xbox(?:\sone)?)[\s\);]/i // Microsoft Xbox + ], [MODEL, [VENDOR, 'Microsoft'], [TYPE, CONSOLE]], [ + /(kin\.[onetw]{3})/i // Microsoft Kin + ], [[MODEL, /\./g, ' '], [VENDOR, 'Microsoft'], [TYPE, MOBILE]], [ + + // Motorola + /\s(milestone|droid(?:[2-4x]|\s(?:bionic|x2|pro|razr))?(:?\s4g)?)[\w\s]+build\//i, + /mot[\s-]?(\w+)*/i, + /(XT\d{3,4}) build\//i, + /(nexus\s6)/i + ], [MODEL, [VENDOR, 'Motorola'], [TYPE, MOBILE]], [ + /android.+\s(mz60\d|xoom[\s2]{0,2})\sbuild\//i + ], [MODEL, [VENDOR, 'Motorola'], [TYPE, TABLET]], [ + + /hbbtv\/\d+\.\d+\.\d+\s+\([\w\s]*;\s*(\w[^;]*);([^;]*)/i // HbbTV devices + ], [[VENDOR, util.trim], [MODEL, util.trim], [TYPE, SMARTTV]], [ + + /hbbtv.+maple;(\d+)/i + ], [[MODEL, /^/, 'SmartTV'], [VENDOR, 'Samsung'], [TYPE, SMARTTV]], [ + + /\(dtv[\);].+(aquos)/i // Sharp + ], [MODEL, [VENDOR, 'Sharp'], [TYPE, SMARTTV]], [ + + /android.+((sch-i[89]0\d|shw-m380s|gt-p\d{4}|gt-n\d+|sgh-t8[56]9|nexus 10))/i, + /((SM-T\w+))/i + ], [[VENDOR, 'Samsung'], MODEL, [TYPE, TABLET]], [ // Samsung + /smart-tv.+(samsung)/i + ], [VENDOR, [TYPE, SMARTTV], MODEL], [ + /((s[cgp]h-\w+|gt-\w+|galaxy\snexus|sm-\w[\w\d]+))/i, + /(sam[sung]*)[\s-]*(\w+-?[\w-]*)*/i, + /sec-((sgh\w+))/i + ], [[VENDOR, 'Samsung'], MODEL, [TYPE, MOBILE]], [ + + /sie-(\w+)*/i // Siemens + ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [ + + /(maemo|nokia).*(n900|lumia\s\d+)/i, // Nokia + /(nokia)[\s_-]?([\w-]+)*/i + ], [[VENDOR, 'Nokia'], MODEL, [TYPE, MOBILE]], [ + + /android\s3\.[\s\w;-]{10}(a\d{3})/i // Acer + ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [ + + /android.+([vl]k\-?\d{3})\s+build/i // LG Tablet + ], [MODEL, [VENDOR, 'LG'], [TYPE, TABLET]], [ + /android\s3\.[\s\w;-]{10}(lg?)-([06cv9]{3,4})/i // LG Tablet + ], [[VENDOR, 'LG'], MODEL, [TYPE, TABLET]], [ + /(lg) netcast\.tv/i // LG SmartTV + ], [VENDOR, MODEL, [TYPE, SMARTTV]], [ + /(nexus\s[45])/i, // LG + /lg[e;\s\/-]+(\w+)*/i, + /android.+lg(\-?[\d\w]+)\s+build/i + ], [MODEL, [VENDOR, 'LG'], [TYPE, MOBILE]], [ + + /android.+(ideatab[a-z0-9\-\s]+)/i // Lenovo + ], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [ + + /linux;.+((jolla));/i // Jolla + ], [VENDOR, MODEL, [TYPE, MOBILE]], [ + + /((pebble))app\/[\d\.]+\s/i // Pebble + ], [VENDOR, MODEL, [TYPE, WEARABLE]], [ + + /android.+;\s(oppo)\s?([\w\s]+)\sbuild/i // OPPO + ], [VENDOR, MODEL, [TYPE, MOBILE]], [ + + /crkey/i // Google Chromecast + ], [[MODEL, 'Chromecast'], [VENDOR, 'Google']], [ + + /android.+;\s(glass)\s\d/i // Google Glass + ], [MODEL, [VENDOR, 'Google'], [TYPE, WEARABLE]], [ + + /android.+;\s(pixel c)\s/i // Google Pixel C + ], [MODEL, [VENDOR, 'Google'], [TYPE, TABLET]], [ + + /android.+;\s(pixel xl|pixel)\s/i // Google Pixel + ], [MODEL, [VENDOR, 'Google'], [TYPE, MOBILE]], [ + + /android.+(\w+)\s+build\/hm\1/i, // Xiaomi Hongmi 'numeric' models + /android.+(hm[\s\-_]*note?[\s_]*(?:\d\w)?)\s+build/i, // Xiaomi Hongmi + /android.+(mi[\s\-_]*(?:one|one[\s_]plus|note lte)?[\s_]*(?:\d\w)?)\s+build/i, // Xiaomi Mi + /android.+(redmi[\s\-_]*(?:note)?(?:[\s_]*[\w\s]+)?)\s+build/i // Redmi Phones + ], [[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, MOBILE]], [ + /android.+(mi[\s\-_]*(?:pad)?(?:[\s_]*[\w\s]+)?)\s+build/i // Mi Pad tablets + ],[[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, TABLET]], [ + /android.+;\s(m[1-5]\snote)\sbuild/i // Meizu Tablet + ], [MODEL, [VENDOR, 'Meizu'], [TYPE, TABLET]], [ + + /android.+a000(1)\s+build/i // OnePlus + ], [MODEL, [VENDOR, 'OnePlus'], [TYPE, MOBILE]], [ + + /android.+[;\/]\s*(RCT[\d\w]+)\s+build/i // RCA Tablets + ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [ + + /android.+[;\/]\s*(Venue[\d\s]*)\s+build/i // Dell Venue Tablets + ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [ + + /android.+[;\/]\s*(Q[T|M][\d\w]+)\s+build/i // Verizon Tablet + ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [ + + /android.+[;\/]\s+(Barnes[&\s]+Noble\s+|BN[RT])(V?.*)\s+build/i // Barnes & Noble Tablet + ], [[VENDOR, 'Barnes & Noble'], MODEL, [TYPE, TABLET]], [ + + /android.+[;\/]\s+(TM\d{3}.*\b)\s+build/i // Barnes & Noble Tablet + ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [ + + /android.+[;\/]\s*(zte)?.+(k\d{2})\s+build/i // ZTE K Series Tablet + ], [[VENDOR, 'ZTE'], MODEL, [TYPE, TABLET]], [ + + /android.+[;\/]\s*(gen\d{3})\s+build.*49h/i // Swiss GEN Mobile + ], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [ + + /android.+[;\/]\s*(zur\d{3})\s+build/i // Swiss ZUR Tablet + ], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [ + + /android.+[;\/]\s*((Zeki)?TB.*\b)\s+build/i // Zeki Tablets + ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [ + + /(android).+[;\/]\s+([YR]\d{2}x?.*)\s+build/i, + /android.+[;\/]\s+(Dragon[\-\s]+Touch\s+|DT)(.+)\s+build/i // Dragon Touch Tablet + ], [[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]], [ + + /android.+[;\/]\s*(NS-?.+)\s+build/i // Insignia Tablets + ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [ + + /android.+[;\/]\s*((NX|Next)-?.+)\s+build/i // NextBook Tablets + ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [ + + /android.+[;\/]\s*(Xtreme\_?)?(V(1[045]|2[015]|30|40|60|7[05]|90))\s+build/i + ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [ // Voice Xtreme Phones + + /android.+[;\/]\s*(LVTEL\-?)?(V1[12])\s+build/i // LvTel Phones + ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [ + + /android.+[;\/]\s*(V(100MD|700NA|7011|917G).*\b)\s+build/i // Envizen Tablets + ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [ + + /android.+[;\/]\s*(Le[\s\-]+Pan)[\s\-]+(.*\b)\s+build/i // Le Pan Tablets + ], [VENDOR, MODEL, [TYPE, TABLET]], [ + + /android.+[;\/]\s*(Trio[\s\-]*.*)\s+build/i // MachSpeed Tablets + ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [ + + /android.+[;\/]\s*(Trinity)[\-\s]*(T\d{3})\s+build/i // Trinity Tablets + ], [VENDOR, MODEL, [TYPE, TABLET]], [ + + /android.+[;\/]\s*TU_(1491)\s+build/i // Rotor Tablets + ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [ + + /android.+(KS(.+))\s+build/i // Amazon Kindle Tablets + ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [ + + /android.+(Gigaset)[\s\-]+(Q.+)\s+build/i // Gigaset Tablets + ], [VENDOR, MODEL, [TYPE, TABLET]], [ + + /\s(tablet|tab)[;\/]/i, // Unidentifiable Tablet + /\s(mobile)(?:[;\/]|\ssafari)/i // Unidentifiable Mobile + ], [[TYPE, util.lowerize], VENDOR, MODEL], [ + + /(android.+)[;\/].+build/i // Generic Android Device + ], [MODEL, [VENDOR, 'Generic']] + + + /*////////////////////////// + // TODO: move to string map + //////////////////////////// + + /(C6603)/i // Sony Xperia Z C6603 + ], [[MODEL, 'Xperia Z C6603'], [VENDOR, 'Sony'], [TYPE, MOBILE]], [ + /(C6903)/i // Sony Xperia Z 1 + ], [[MODEL, 'Xperia Z 1'], [VENDOR, 'Sony'], [TYPE, MOBILE]], [ + + /(SM-G900[F|H])/i // Samsung Galaxy S5 + ], [[MODEL, 'Galaxy S5'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ + /(SM-G7102)/i // Samsung Galaxy Grand 2 + ], [[MODEL, 'Galaxy Grand 2'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ + /(SM-G530H)/i // Samsung Galaxy Grand Prime + ], [[MODEL, 'Galaxy Grand Prime'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ + /(SM-G313HZ)/i // Samsung Galaxy V + ], [[MODEL, 'Galaxy V'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ + /(SM-T805)/i // Samsung Galaxy Tab S 10.5 + ], [[MODEL, 'Galaxy Tab S 10.5'], [VENDOR, 'Samsung'], [TYPE, TABLET]], [ + /(SM-G800F)/i // Samsung Galaxy S5 Mini + ], [[MODEL, 'Galaxy S5 Mini'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ + /(SM-T311)/i // Samsung Galaxy Tab 3 8.0 + ], [[MODEL, 'Galaxy Tab 3 8.0'], [VENDOR, 'Samsung'], [TYPE, TABLET]], [ + + /(T3C)/i // Advan Vandroid T3C + ], [MODEL, [VENDOR, 'Advan'], [TYPE, TABLET]], [ + /(ADVAN T1J\+)/i // Advan Vandroid T1J+ + ], [[MODEL, 'Vandroid T1J+'], [VENDOR, 'Advan'], [TYPE, TABLET]], [ + /(ADVAN S4A)/i // Advan Vandroid S4A + ], [[MODEL, 'Vandroid S4A'], [VENDOR, 'Advan'], [TYPE, MOBILE]], [ + + /(V972M)/i // ZTE V972M + ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [ + + /(i-mobile)\s(IQ\s[\d\.]+)/i // i-mobile IQ + ], [VENDOR, MODEL, [TYPE, MOBILE]], [ + /(IQ6.3)/i // i-mobile IQ IQ 6.3 + ], [[MODEL, 'IQ 6.3'], [VENDOR, 'i-mobile'], [TYPE, MOBILE]], [ + /(i-mobile)\s(i-style\s[\d\.]+)/i // i-mobile i-STYLE + ], [VENDOR, MODEL, [TYPE, MOBILE]], [ + /(i-STYLE2.1)/i // i-mobile i-STYLE 2.1 + ], [[MODEL, 'i-STYLE 2.1'], [VENDOR, 'i-mobile'], [TYPE, MOBILE]], [ + + /(mobiistar touch LAI 512)/i // mobiistar touch LAI 512 + ], [[MODEL, 'Touch LAI 512'], [VENDOR, 'mobiistar'], [TYPE, MOBILE]], [ + + ///////////// + // END TODO + ///////////*/ + + ], + + engine : [[ + + /windows.+\sedge\/([\w\.]+)/i // EdgeHTML + ], [VERSION, [NAME, 'EdgeHTML']], [ + + /(presto)\/([\w\.]+)/i, // Presto + /(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m + /(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i, // KHTML/Tasman/Links + /(icab)[\/\s]([23]\.[\d\.]+)/i // iCab + ], [NAME, VERSION], [ + + /rv\:([\w\.]+).*(gecko)/i // Gecko + ], [VERSION, NAME] + ], + + os : [[ + + // Windows based + /microsoft\s(windows)\s(vista|xp)/i // Windows (iTunes) + ], [NAME, VERSION], [ + /(windows)\snt\s6\.2;\s(arm)/i, // Windows RT + /(windows\sphone(?:\sos)*)[\s\/]?([\d\.\s]+\w)*/i, // Windows Phone + /(windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i + ], [NAME, [VERSION, mapper.str, maps.os.windows.version]], [ + /(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i + ], [[NAME, 'Windows'], [VERSION, mapper.str, maps.os.windows.version]], [ + + // Mobile/Embedded OS + /\((bb)(10);/i // BlackBerry 10 + ], [[NAME, 'BlackBerry'], VERSION], [ + /(blackberry)\w*\/?([\w\.]+)*/i, // Blackberry + /(tizen)[\/\s]([\w\.]+)/i, // Tizen + /(android|webos|palm\sos|qnx|bada|rim\stablet\sos|meego|contiki)[\/\s-]?([\w\.]+)*/i, + // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo/Contiki + /linux;.+(sailfish);/i // Sailfish OS + ], [NAME, VERSION], [ + /(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i // Symbian + ], [[NAME, 'Symbian'], VERSION], [ + /\((series40);/i // Series 40 + ], [NAME], [ + /mozilla.+\(mobile;.+gecko.+firefox/i // Firefox OS + ], [[NAME, 'Firefox OS'], VERSION], [ + + // Console + /(nintendo|playstation)\s([wids34portablevu]+)/i, // Nintendo/Playstation + + // GNU/Linux based + /(mint)[\/\s\(]?(\w+)*/i, // Mint + /(mageia|vectorlinux)[;\s]/i, // Mageia/VectorLinux + /(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|(?=\s)arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus)[\/\s-]?(?!chrom)([\w\.-]+)*/i, + // Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware + // Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus + /(hurd|linux)\s?([\w\.]+)*/i, // Hurd/Linux + /(gnu)\s?([\w\.]+)*/i // GNU + ], [NAME, VERSION], [ + + /(cros)\s[\w]+\s([\w\.]+\w)/i // Chromium OS + ], [[NAME, 'Chromium OS'], VERSION],[ + + // Solaris + /(sunos)\s?([\w\.]+\d)*/i // Solaris + ], [[NAME, 'Solaris'], VERSION], [ + + // BSD based + /\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly + ], [NAME, VERSION],[ + + /(haiku)\s(\w+)/i // Haiku + ], [NAME, VERSION],[ + + /cfnetwork\/.+darwin/i, + /ip[honead]+(?:.*os\s([\w]+)\slike\smac|;\sopera)/i // iOS + ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [ + + /(mac\sos\sx)\s?([\w\s\.]+\w)*/i, + /(macintosh|mac(?=_powerpc)\s)/i // Mac OS + ], [[NAME, 'Mac OS'], [VERSION, /_/g, '.']], [ + + // Other + /((?:open)?solaris)[\/\s-]?([\w\.]+)*/i, // Solaris + /(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i, // AIX + /(plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos|openvms)/i, + // Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS/OpenVMS + /(unix)\s?([\w\.]+)*/i // UNIX + ], [NAME, VERSION] + ] + }; + + + ///////////////// + // Constructor + //////////////// + /* + var Browser = function (name, version) { + this[NAME] = name; + this[VERSION] = version; + }; + var CPU = function (arch) { + this[ARCHITECTURE] = arch; + }; + var Device = function (vendor, model, type) { + this[VENDOR] = vendor; + this[MODEL] = model; + this[TYPE] = type; + }; + var Engine = Browser; + var OS = Browser; + */ + var UAParser = function (uastring, extensions) { + + if (typeof uastring === 'object') { + extensions = uastring; + uastring = undefined; + } + + if (!(this instanceof UAParser)) { + return new UAParser(uastring, extensions).getResult(); + } + + var ua = uastring || ((window && window.navigator && window.navigator.userAgent) ? window.navigator.userAgent : EMPTY); + var rgxmap = extensions ? util.extend(regexes, extensions) : regexes; + //var browser = new Browser(); + //var cpu = new CPU(); + //var device = new Device(); + //var engine = new Engine(); + //var os = new OS(); + + this.getBrowser = function () { + var browser = { name: undefined, version: undefined }; + mapper.rgx.call(browser, ua, rgxmap.browser); + browser.major = util.major(browser.version); // deprecated + return browser; + }; + this.getCPU = function () { + var cpu = { architecture: undefined }; + mapper.rgx.call(cpu, ua, rgxmap.cpu); + return cpu; + }; + this.getDevice = function () { + var device = { vendor: undefined, model: undefined, type: undefined }; + mapper.rgx.call(device, ua, rgxmap.device); + return device; + }; + this.getEngine = function () { + var engine = { name: undefined, version: undefined }; + mapper.rgx.call(engine, ua, rgxmap.engine); + return engine; + }; + this.getOS = function () { + var os = { name: undefined, version: undefined }; + mapper.rgx.call(os, ua, rgxmap.os); + return os; + }; + this.getResult = function () { + return { + ua : this.getUA(), + browser : this.getBrowser(), + engine : this.getEngine(), + os : this.getOS(), + device : this.getDevice(), + cpu : this.getCPU() + }; + }; + this.getUA = function () { + return ua; + }; + this.setUA = function (uastring) { + ua = uastring; + //browser = new Browser(); + //cpu = new CPU(); + //device = new Device(); + //engine = new Engine(); + //os = new OS(); + return this; + }; + return this; + }; + + UAParser.VERSION = LIBVERSION; + UAParser.BROWSER = { + NAME : NAME, + MAJOR : MAJOR, // deprecated + VERSION : VERSION + }; + UAParser.CPU = { + ARCHITECTURE : ARCHITECTURE + }; + UAParser.DEVICE = { + MODEL : MODEL, + VENDOR : VENDOR, + TYPE : TYPE, + CONSOLE : CONSOLE, + MOBILE : MOBILE, + SMARTTV : SMARTTV, + TABLET : TABLET, + WEARABLE: WEARABLE, + EMBEDDED: EMBEDDED + }; + UAParser.ENGINE = { + NAME : NAME, + VERSION : VERSION + }; + UAParser.OS = { + NAME : NAME, + VERSION : VERSION + }; + //UAParser.Utils = util; + + /////////// + // Export + ////////// + + + // check js environment + if (typeof(exports) !== UNDEF_TYPE) { + // nodejs env + if (typeof module !== UNDEF_TYPE && module.exports) { + exports = module.exports = UAParser; + } + // TODO: test!!!!!!!! + /* + if (require && require.main === module && process) { + // cli + var jsonize = function (arr) { + var res = []; + for (var i in arr) { + res.push(new UAParser(arr[i]).getResult()); + } + process.stdout.write(JSON.stringify(res, null, 2) + '\n'); + }; + if (process.stdin.isTTY) { + // via args + jsonize(process.argv.slice(2)); + } else { + // via pipe + var str = ''; + process.stdin.on('readable', function() { + var read = process.stdin.read(); + if (read !== null) { + str += read; + } + }); + process.stdin.on('end', function () { + jsonize(str.replace(/\n$/, '').split('\n')); + }); + } + } + */ + exports.UAParser = UAParser; + } else { + // requirejs env (optional) + if (typeof(define) === FUNC_TYPE && define.amd) { + define(function () { + return UAParser; + }); + } else if (window) { + // browser env + window.UAParser = UAParser; + } + } + + // jQuery/Zepto specific (optional) + // Note: + // In AMD env the global scope should be kept clean, but jQuery is an exception. + // jQuery always exports to global scope, unless jQuery.noConflict(true) is used, + // and we should catch that. + var $ = window && (window.jQuery || window.Zepto); + if (typeof $ !== UNDEF_TYPE) { + var parser = new UAParser(); + $.ua = parser.getResult(); + $.ua.get = function () { + return parser.getUA(); + }; + $.ua.set = function (uastring) { + parser.setUA(uastring); + var result = parser.getResult(); + for (var prop in result) { + $.ua[prop] = result[prop]; + } + }; + } + +})(typeof window === 'object' ? window : this); + +},{}],21:[function(require,module,exports){ +var v1 = require('./v1'); +var v4 = require('./v4'); + +var uuid = v4; +uuid.v1 = v1; +uuid.v4 = v4; + +module.exports = uuid; + +},{"./v1":24,"./v4":25}],22:[function(require,module,exports){ +/** + * Convert array of 16 byte values to UUID string format of the form: + * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + */ +var byteToHex = []; +for (var i = 0; i < 256; ++i) { + byteToHex[i] = (i + 0x100).toString(16).substr(1); +} + +function bytesToUuid(buf, offset) { + var i = offset || 0; + var bth = byteToHex; + return bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]]; +} + +module.exports = bytesToUuid; + +},{}],23:[function(require,module,exports){ +(function (global){ +// Unique ID creation requires a high quality random # generator. In the +// browser this is a little complicated due to unknown quality of Math.random() +// and inconsistent support for the `crypto` API. We do the best we can via +// feature-detection +var rng; + +var crypto = global.crypto || global.msCrypto; // for IE 11 +if (crypto && crypto.getRandomValues) { + // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto + var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef + rng = function whatwgRNG() { + crypto.getRandomValues(rnds8); + return rnds8; + }; +} + +if (!rng) { + // Math.random()-based (RNG) + // + // If all else fails, use Math.random(). It's fast, but is of unspecified + // quality. + var rnds = new Array(16); + rng = function() { + for (var i = 0, r; i < 16; i++) { + if ((i & 0x03) === 0) r = Math.random() * 0x100000000; + rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; + } + + return rnds; + }; +} + +module.exports = rng; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],24:[function(require,module,exports){ +var rng = require('./lib/rng'); +var bytesToUuid = require('./lib/bytesToUuid'); + +// **`v1()` - Generate time-based UUID** +// +// Inspired by https://github.com/LiosK/UUID.js +// and http://docs.python.org/library/uuid.html + +// random #'s we need to init node and clockseq +var _seedBytes = rng(); + +// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) +var _nodeId = [ + _seedBytes[0] | 0x01, + _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5] +]; + +// Per 4.2.2, randomize (14 bit) clockseq +var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff; + +// Previous uuid creation time +var _lastMSecs = 0, _lastNSecs = 0; + +// See https://github.com/broofa/node-uuid for API details +function v1(options, buf, offset) { + var i = buf && offset || 0; + var b = buf || []; + + options = options || {}; + + var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; + + // 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. + var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime(); + + // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; + + // Time since last uuid creation (in msecs) + var 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` + var 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` + var 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` + var node = options.node || _nodeId; + for (var n = 0; n < 6; ++n) { + b[i + n] = node[n]; + } + + return buf ? buf : bytesToUuid(b); +} + +module.exports = v1; + +},{"./lib/bytesToUuid":22,"./lib/rng":23}],25:[function(require,module,exports){ +var rng = require('./lib/rng'); +var bytesToUuid = require('./lib/bytesToUuid'); + +function v4(options, buf, offset) { + var i = buf && offset || 0; + + if (typeof(options) == 'string') { + buf = options == 'binary' ? new Array(16) : null; + options = null; + } + options = options || {}; + + var rnds = options.random || (options.rng || rng)(); + + // 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) { + for (var ii = 0; ii < 16; ++ii) { + buf[i + ii] = rnds[ii]; + } + } + + return buf || bytesToUuid(rnds); +} + +module.exports = v4; + +},{"./lib/bytesToUuid":22,"./lib/rng":23}],26:[function(require,module,exports){ +(function (global){ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ + +'use strict'; + +var adapterFactory = require('./adapter_factory.js'); +module.exports = adapterFactory({window: global.window}); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"./adapter_factory.js":27}],27:[function(require,module,exports){ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ + +'use strict'; + +var utils = require('./utils'); +// Shimming starts here. +module.exports = function(dependencies, opts) { + var window = dependencies && dependencies.window; + + var options = { + shimChrome: true, + shimFirefox: true, + shimEdge: true, + shimSafari: true, + }; + + for (var key in opts) { + if (hasOwnProperty.call(opts, key)) { + options[key] = opts[key]; + } + } + + // Utils. + var logging = utils.log; + var browserDetails = utils.detectBrowser(window); + + // Uncomment the line below if you want logging to occur, including logging + // for the switch statement below. Can also be turned on in the browser via + // adapter.disableLog(false), but then logging from the switch statement below + // will not appear. + // require('./utils').disableLog(false); + + // Browser shims. + var chromeShim = require('./chrome/chrome_shim') || null; + var edgeShim = require('./edge/edge_shim') || null; + var firefoxShim = require('./firefox/firefox_shim') || null; + var safariShim = require('./safari/safari_shim') || null; + var commonShim = require('./common_shim') || null; + + // Export to the adapter global object visible in the browser. + var adapter = { + browserDetails: browserDetails, + commonShim: commonShim, + extractVersion: utils.extractVersion, + disableLog: utils.disableLog, + disableWarnings: utils.disableWarnings + }; + + // Shim browser if found. + switch (browserDetails.browser) { + case 'chrome': + if (!chromeShim || !chromeShim.shimPeerConnection || + !options.shimChrome) { + logging('Chrome shim is not included in this adapter release.'); + return adapter; + } + logging('adapter.js shimming chrome.'); + // Export to the adapter global object visible in the browser. + adapter.browserShim = chromeShim; + commonShim.shimCreateObjectURL(window); + + chromeShim.shimGetUserMedia(window); + chromeShim.shimMediaStream(window); + chromeShim.shimSourceObject(window); + chromeShim.shimPeerConnection(window); + chromeShim.shimOnTrack(window); + chromeShim.shimAddTrackRemoveTrack(window); + chromeShim.shimGetSendersWithDtmf(window); + + commonShim.shimRTCIceCandidate(window); + commonShim.shimMaxMessageSize(window); + commonShim.shimSendThrowTypeError(window); + break; + case 'firefox': + if (!firefoxShim || !firefoxShim.shimPeerConnection || + !options.shimFirefox) { + logging('Firefox shim is not included in this adapter release.'); + return adapter; + } + logging('adapter.js shimming firefox.'); + // Export to the adapter global object visible in the browser. + adapter.browserShim = firefoxShim; + commonShim.shimCreateObjectURL(window); + + firefoxShim.shimGetUserMedia(window); + firefoxShim.shimSourceObject(window); + firefoxShim.shimPeerConnection(window); + firefoxShim.shimOnTrack(window); + firefoxShim.shimRemoveStream(window); + + commonShim.shimRTCIceCandidate(window); + commonShim.shimMaxMessageSize(window); + commonShim.shimSendThrowTypeError(window); + break; + case 'edge': + if (!edgeShim || !edgeShim.shimPeerConnection || !options.shimEdge) { + logging('MS edge shim is not included in this adapter release.'); + return adapter; + } + logging('adapter.js shimming edge.'); + // Export to the adapter global object visible in the browser. + adapter.browserShim = edgeShim; + commonShim.shimCreateObjectURL(window); + + edgeShim.shimGetUserMedia(window); + edgeShim.shimPeerConnection(window); + edgeShim.shimReplaceTrack(window); + + // the edge shim implements the full RTCIceCandidate object. + + commonShim.shimMaxMessageSize(window); + commonShim.shimSendThrowTypeError(window); + break; + case 'safari': + if (!safariShim || !options.shimSafari) { + logging('Safari shim is not included in this adapter release.'); + return adapter; + } + logging('adapter.js shimming safari.'); + // Export to the adapter global object visible in the browser. + adapter.browserShim = safariShim; + commonShim.shimCreateObjectURL(window); + + safariShim.shimRTCIceServerUrls(window); + safariShim.shimCallbacksAPI(window); + safariShim.shimLocalStreamsAPI(window); + safariShim.shimRemoteStreamsAPI(window); + safariShim.shimTrackEventTransceiver(window); + safariShim.shimGetUserMedia(window); + safariShim.shimCreateOfferLegacy(window); + + commonShim.shimRTCIceCandidate(window); + commonShim.shimMaxMessageSize(window); + commonShim.shimSendThrowTypeError(window); + break; + default: + logging('Unsupported browser!'); + break; + } + + return adapter; +}; + +},{"./chrome/chrome_shim":28,"./common_shim":30,"./edge/edge_shim":31,"./firefox/firefox_shim":33,"./safari/safari_shim":35,"./utils":36}],28:[function(require,module,exports){ + +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ +'use strict'; +var utils = require('../utils.js'); +var logging = utils.log; + +module.exports = { + shimGetUserMedia: require('./getusermedia'), + shimMediaStream: function(window) { + window.MediaStream = window.MediaStream || window.webkitMediaStream; + }, + + shimOnTrack: function(window) { + if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in + window.RTCPeerConnection.prototype)) { + Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', { + get: function() { + return this._ontrack; + }, + set: function(f) { + if (this._ontrack) { + this.removeEventListener('track', this._ontrack); + } + this.addEventListener('track', this._ontrack = f); + } + }); + var origSetRemoteDescription = + window.RTCPeerConnection.prototype.setRemoteDescription; + window.RTCPeerConnection.prototype.setRemoteDescription = function() { + var pc = this; + if (!pc._ontrackpoly) { + pc._ontrackpoly = function(e) { + // onaddstream does not fire when a track is added to an existing + // stream. But stream.onaddtrack is implemented so we use that. + e.stream.addEventListener('addtrack', function(te) { + var receiver; + if (window.RTCPeerConnection.prototype.getReceivers) { + receiver = pc.getReceivers().find(function(r) { + return r.track && r.track.id === te.track.id; + }); + } else { + receiver = {track: te.track}; + } + + var event = new Event('track'); + event.track = te.track; + event.receiver = receiver; + event.transceiver = {receiver: receiver}; + event.streams = [e.stream]; + pc.dispatchEvent(event); + }); + e.stream.getTracks().forEach(function(track) { + var receiver; + if (window.RTCPeerConnection.prototype.getReceivers) { + receiver = pc.getReceivers().find(function(r) { + return r.track && r.track.id === track.id; + }); + } else { + receiver = {track: track}; + } + var event = new Event('track'); + event.track = track; + event.receiver = receiver; + event.transceiver = {receiver: receiver}; + event.streams = [e.stream]; + pc.dispatchEvent(event); + }); + }; + pc.addEventListener('addstream', pc._ontrackpoly); + } + return origSetRemoteDescription.apply(pc, arguments); + }; + } else if (!('RTCRtpTransceiver' in window)) { + utils.wrapPeerConnectionEvent(window, 'track', function(e) { + if (!e.transceiver) { + e.transceiver = {receiver: e.receiver}; + } + return e; + }); + } + }, + + shimGetSendersWithDtmf: function(window) { + // Overrides addTrack/removeTrack, depends on shimAddTrackRemoveTrack. + if (typeof window === 'object' && window.RTCPeerConnection && + !('getSenders' in window.RTCPeerConnection.prototype) && + 'createDTMFSender' in window.RTCPeerConnection.prototype) { + var shimSenderWithDtmf = function(pc, track) { + return { + track: track, + get dtmf() { + if (this._dtmf === undefined) { + if (track.kind === 'audio') { + this._dtmf = pc.createDTMFSender(track); + } else { + this._dtmf = null; + } + } + return this._dtmf; + }, + _pc: pc + }; + }; + + // augment addTrack when getSenders is not available. + if (!window.RTCPeerConnection.prototype.getSenders) { + window.RTCPeerConnection.prototype.getSenders = function() { + this._senders = this._senders || []; + return this._senders.slice(); // return a copy of the internal state. + }; + var origAddTrack = window.RTCPeerConnection.prototype.addTrack; + window.RTCPeerConnection.prototype.addTrack = function(track, stream) { + var pc = this; + var sender = origAddTrack.apply(pc, arguments); + if (!sender) { + sender = shimSenderWithDtmf(pc, track); + pc._senders.push(sender); + } + return sender; + }; + + var origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack; + window.RTCPeerConnection.prototype.removeTrack = function(sender) { + var pc = this; + origRemoveTrack.apply(pc, arguments); + var idx = pc._senders.indexOf(sender); + if (idx !== -1) { + pc._senders.splice(idx, 1); + } + }; + } + var origAddStream = window.RTCPeerConnection.prototype.addStream; + window.RTCPeerConnection.prototype.addStream = function(stream) { + var pc = this; + pc._senders = pc._senders || []; + origAddStream.apply(pc, [stream]); + stream.getTracks().forEach(function(track) { + pc._senders.push(shimSenderWithDtmf(pc, track)); + }); + }; + + var origRemoveStream = window.RTCPeerConnection.prototype.removeStream; + window.RTCPeerConnection.prototype.removeStream = function(stream) { + var pc = this; + pc._senders = pc._senders || []; + origRemoveStream.apply(pc, [stream]); + + stream.getTracks().forEach(function(track) { + var sender = pc._senders.find(function(s) { + return s.track === track; + }); + if (sender) { + pc._senders.splice(pc._senders.indexOf(sender), 1); // remove sender + } + }); + }; + } else if (typeof window === 'object' && window.RTCPeerConnection && + 'getSenders' in window.RTCPeerConnection.prototype && + 'createDTMFSender' in window.RTCPeerConnection.prototype && + window.RTCRtpSender && + !('dtmf' in window.RTCRtpSender.prototype)) { + var origGetSenders = window.RTCPeerConnection.prototype.getSenders; + window.RTCPeerConnection.prototype.getSenders = function() { + var pc = this; + var senders = origGetSenders.apply(pc, []); + senders.forEach(function(sender) { + sender._pc = pc; + }); + return senders; + }; + + Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', { + get: function() { + if (this._dtmf === undefined) { + if (this.track.kind === 'audio') { + this._dtmf = this._pc.createDTMFSender(this.track); + } else { + this._dtmf = null; + } + } + return this._dtmf; + } + }); + } + }, + + shimSourceObject: function(window) { + var URL = window && window.URL; + + if (typeof window === 'object') { + if (window.HTMLMediaElement && + !('srcObject' in window.HTMLMediaElement.prototype)) { + // Shim the srcObject property, once, when HTMLMediaElement is found. + Object.defineProperty(window.HTMLMediaElement.prototype, 'srcObject', { + get: function() { + return this._srcObject; + }, + set: function(stream) { + var self = this; + // Use _srcObject as a private property for this shim + this._srcObject = stream; + if (this.src) { + URL.revokeObjectURL(this.src); + } + + if (!stream) { + this.src = ''; + return undefined; + } + this.src = URL.createObjectURL(stream); + // We need to recreate the blob url when a track is added or + // removed. Doing it manually since we want to avoid a recursion. + stream.addEventListener('addtrack', function() { + if (self.src) { + URL.revokeObjectURL(self.src); + } + self.src = URL.createObjectURL(stream); + }); + stream.addEventListener('removetrack', function() { + if (self.src) { + URL.revokeObjectURL(self.src); + } + self.src = URL.createObjectURL(stream); + }); + } + }); + } + } + }, + + shimAddTrackRemoveTrackWithNative: function(window) { + // shim addTrack/removeTrack with native variants in order to make + // the interactions with legacy getLocalStreams behave as in other browsers. + // Keeps a mapping stream.id => [stream, rtpsenders...] + window.RTCPeerConnection.prototype.getLocalStreams = function() { + var pc = this; + this._shimmedLocalStreams = this._shimmedLocalStreams || {}; + return Object.keys(this._shimmedLocalStreams).map(function(streamId) { + return pc._shimmedLocalStreams[streamId][0]; + }); + }; + + var origAddTrack = window.RTCPeerConnection.prototype.addTrack; + window.RTCPeerConnection.prototype.addTrack = function(track, stream) { + if (!stream) { + return origAddTrack.apply(this, arguments); + } + this._shimmedLocalStreams = this._shimmedLocalStreams || {}; + + var sender = origAddTrack.apply(this, arguments); + if (!this._shimmedLocalStreams[stream.id]) { + this._shimmedLocalStreams[stream.id] = [stream, sender]; + } else if (this._shimmedLocalStreams[stream.id].indexOf(sender) === -1) { + this._shimmedLocalStreams[stream.id].push(sender); + } + return sender; + }; + + var origAddStream = window.RTCPeerConnection.prototype.addStream; + window.RTCPeerConnection.prototype.addStream = function(stream) { + var pc = this; + this._shimmedLocalStreams = this._shimmedLocalStreams || {}; + + stream.getTracks().forEach(function(track) { + var alreadyExists = pc.getSenders().find(function(s) { + return s.track === track; + }); + if (alreadyExists) { + throw new DOMException('Track already exists.', + 'InvalidAccessError'); + } + }); + var existingSenders = pc.getSenders(); + origAddStream.apply(this, arguments); + var newSenders = pc.getSenders().filter(function(newSender) { + return existingSenders.indexOf(newSender) === -1; + }); + this._shimmedLocalStreams[stream.id] = [stream].concat(newSenders); + }; + + var origRemoveStream = window.RTCPeerConnection.prototype.removeStream; + window.RTCPeerConnection.prototype.removeStream = function(stream) { + this._shimmedLocalStreams = this._shimmedLocalStreams || {}; + delete this._shimmedLocalStreams[stream.id]; + return origRemoveStream.apply(this, arguments); + }; + + var origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack; + window.RTCPeerConnection.prototype.removeTrack = function(sender) { + var pc = this; + this._shimmedLocalStreams = this._shimmedLocalStreams || {}; + if (sender) { + Object.keys(this._shimmedLocalStreams).forEach(function(streamId) { + var idx = pc._shimmedLocalStreams[streamId].indexOf(sender); + if (idx !== -1) { + pc._shimmedLocalStreams[streamId].splice(idx, 1); + } + if (pc._shimmedLocalStreams[streamId].length === 1) { + delete pc._shimmedLocalStreams[streamId]; + } + }); + } + return origRemoveTrack.apply(this, arguments); + }; + }, + + shimAddTrackRemoveTrack: function(window) { + var browserDetails = utils.detectBrowser(window); + // shim addTrack and removeTrack. + if (window.RTCPeerConnection.prototype.addTrack && + browserDetails.version >= 65) { + return this.shimAddTrackRemoveTrackWithNative(window); + } + + // also shim pc.getLocalStreams when addTrack is shimmed + // to return the original streams. + var origGetLocalStreams = window.RTCPeerConnection.prototype + .getLocalStreams; + window.RTCPeerConnection.prototype.getLocalStreams = function() { + var pc = this; + var nativeStreams = origGetLocalStreams.apply(this); + pc._reverseStreams = pc._reverseStreams || {}; + return nativeStreams.map(function(stream) { + return pc._reverseStreams[stream.id]; + }); + }; + + var origAddStream = window.RTCPeerConnection.prototype.addStream; + window.RTCPeerConnection.prototype.addStream = function(stream) { + var pc = this; + pc._streams = pc._streams || {}; + pc._reverseStreams = pc._reverseStreams || {}; + + stream.getTracks().forEach(function(track) { + var alreadyExists = pc.getSenders().find(function(s) { + return s.track === track; + }); + if (alreadyExists) { + throw new DOMException('Track already exists.', + 'InvalidAccessError'); + } + }); + // Add identity mapping for consistency with addTrack. + // Unless this is being used with a stream from addTrack. + if (!pc._reverseStreams[stream.id]) { + var newStream = new window.MediaStream(stream.getTracks()); + pc._streams[stream.id] = newStream; + pc._reverseStreams[newStream.id] = stream; + stream = newStream; + } + origAddStream.apply(pc, [stream]); + }; + + var origRemoveStream = window.RTCPeerConnection.prototype.removeStream; + window.RTCPeerConnection.prototype.removeStream = function(stream) { + var pc = this; + pc._streams = pc._streams || {}; + pc._reverseStreams = pc._reverseStreams || {}; + + origRemoveStream.apply(pc, [(pc._streams[stream.id] || stream)]); + delete pc._reverseStreams[(pc._streams[stream.id] ? + pc._streams[stream.id].id : stream.id)]; + delete pc._streams[stream.id]; + }; + + window.RTCPeerConnection.prototype.addTrack = function(track, stream) { + var pc = this; + if (pc.signalingState === 'closed') { + throw new DOMException( + 'The RTCPeerConnection\'s signalingState is \'closed\'.', + 'InvalidStateError'); + } + var streams = [].slice.call(arguments, 1); + if (streams.length !== 1 || + !streams[0].getTracks().find(function(t) { + return t === track; + })) { + // this is not fully correct but all we can manage without + // [[associated MediaStreams]] internal slot. + throw new DOMException( + 'The adapter.js addTrack polyfill only supports a single ' + + ' stream which is associated with the specified track.', + 'NotSupportedError'); + } + + var alreadyExists = pc.getSenders().find(function(s) { + return s.track === track; + }); + if (alreadyExists) { + throw new DOMException('Track already exists.', + 'InvalidAccessError'); + } + + pc._streams = pc._streams || {}; + pc._reverseStreams = pc._reverseStreams || {}; + var oldStream = pc._streams[stream.id]; + if (oldStream) { + // this is using odd Chrome behaviour, use with caution: + // https://bugs.chromium.org/p/webrtc/issues/detail?id=7815 + // Note: we rely on the high-level addTrack/dtmf shim to + // create the sender with a dtmf sender. + oldStream.addTrack(track); + + // Trigger ONN async. + Promise.resolve().then(function() { + pc.dispatchEvent(new Event('negotiationneeded')); + }); + } else { + var newStream = new window.MediaStream([track]); + pc._streams[stream.id] = newStream; + pc._reverseStreams[newStream.id] = stream; + pc.addStream(newStream); + } + return pc.getSenders().find(function(s) { + return s.track === track; + }); + }; + + // replace the internal stream id with the external one and + // vice versa. + function replaceInternalStreamId(pc, description) { + var sdp = description.sdp; + Object.keys(pc._reverseStreams || []).forEach(function(internalId) { + var externalStream = pc._reverseStreams[internalId]; + var internalStream = pc._streams[externalStream.id]; + sdp = sdp.replace(new RegExp(internalStream.id, 'g'), + externalStream.id); + }); + return new RTCSessionDescription({ + type: description.type, + sdp: sdp + }); + } + function replaceExternalStreamId(pc, description) { + var sdp = description.sdp; + Object.keys(pc._reverseStreams || []).forEach(function(internalId) { + var externalStream = pc._reverseStreams[internalId]; + var internalStream = pc._streams[externalStream.id]; + sdp = sdp.replace(new RegExp(externalStream.id, 'g'), + internalStream.id); + }); + return new RTCSessionDescription({ + type: description.type, + sdp: sdp + }); + } + ['createOffer', 'createAnswer'].forEach(function(method) { + var nativeMethod = window.RTCPeerConnection.prototype[method]; + window.RTCPeerConnection.prototype[method] = function() { + var pc = this; + var args = arguments; + var isLegacyCall = arguments.length && + typeof arguments[0] === 'function'; + if (isLegacyCall) { + return nativeMethod.apply(pc, [ + function(description) { + var desc = replaceInternalStreamId(pc, description); + args[0].apply(null, [desc]); + }, + function(err) { + if (args[1]) { + args[1].apply(null, err); + } + }, arguments[2] + ]); + } + return nativeMethod.apply(pc, arguments) + .then(function(description) { + return replaceInternalStreamId(pc, description); + }); + }; + }); + + var origSetLocalDescription = + window.RTCPeerConnection.prototype.setLocalDescription; + window.RTCPeerConnection.prototype.setLocalDescription = function() { + var pc = this; + if (!arguments.length || !arguments[0].type) { + return origSetLocalDescription.apply(pc, arguments); + } + arguments[0] = replaceExternalStreamId(pc, arguments[0]); + return origSetLocalDescription.apply(pc, arguments); + }; + + // TODO: mangle getStats: https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamstats-streamidentifier + + var origLocalDescription = Object.getOwnPropertyDescriptor( + window.RTCPeerConnection.prototype, 'localDescription'); + Object.defineProperty(window.RTCPeerConnection.prototype, + 'localDescription', { + get: function() { + var pc = this; + var description = origLocalDescription.get.apply(this); + if (description.type === '') { + return description; + } + return replaceInternalStreamId(pc, description); + } + }); + + window.RTCPeerConnection.prototype.removeTrack = function(sender) { + var pc = this; + if (pc.signalingState === 'closed') { + throw new DOMException( + 'The RTCPeerConnection\'s signalingState is \'closed\'.', + 'InvalidStateError'); + } + // We can not yet check for sender instanceof RTCRtpSender + // since we shim RTPSender. So we check if sender._pc is set. + if (!sender._pc) { + throw new DOMException('Argument 1 of RTCPeerConnection.removeTrack ' + + 'does not implement interface RTCRtpSender.', 'TypeError'); + } + var isLocal = sender._pc === pc; + if (!isLocal) { + throw new DOMException('Sender was not created by this connection.', + 'InvalidAccessError'); + } + + // Search for the native stream the senders track belongs to. + pc._streams = pc._streams || {}; + var stream; + Object.keys(pc._streams).forEach(function(streamid) { + var hasTrack = pc._streams[streamid].getTracks().find(function(track) { + return sender.track === track; + }); + if (hasTrack) { + stream = pc._streams[streamid]; + } + }); + + if (stream) { + if (stream.getTracks().length === 1) { + // if this is the last track of the stream, remove the stream. This + // takes care of any shimmed _senders. + pc.removeStream(pc._reverseStreams[stream.id]); + } else { + // relying on the same odd chrome behaviour as above. + stream.removeTrack(sender.track); + } + pc.dispatchEvent(new Event('negotiationneeded')); + } + }; + }, + + shimPeerConnection: function(window) { + var browserDetails = utils.detectBrowser(window); + + // The RTCPeerConnection object. + if (!window.RTCPeerConnection && window.webkitRTCPeerConnection) { + window.RTCPeerConnection = function(pcConfig, pcConstraints) { + // Translate iceTransportPolicy to iceTransports, + // see https://code.google.com/p/webrtc/issues/detail?id=4869 + // this was fixed in M56 along with unprefixing RTCPeerConnection. + logging('PeerConnection'); + if (pcConfig && pcConfig.iceTransportPolicy) { + pcConfig.iceTransports = pcConfig.iceTransportPolicy; + } + + return new window.webkitRTCPeerConnection(pcConfig, pcConstraints); + }; + window.RTCPeerConnection.prototype = + window.webkitRTCPeerConnection.prototype; + // wrap static methods. Currently just generateCertificate. + if (window.webkitRTCPeerConnection.generateCertificate) { + Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', { + get: function() { + return window.webkitRTCPeerConnection.generateCertificate; + } + }); + } + } else { + // migrate from non-spec RTCIceServer.url to RTCIceServer.urls + var OrigPeerConnection = window.RTCPeerConnection; + window.RTCPeerConnection = function(pcConfig, pcConstraints) { + if (pcConfig && pcConfig.iceServers) { + var newIceServers = []; + for (var i = 0; i < pcConfig.iceServers.length; i++) { + var server = pcConfig.iceServers[i]; + if (!server.hasOwnProperty('urls') && + server.hasOwnProperty('url')) { + utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls'); + server = JSON.parse(JSON.stringify(server)); + server.urls = server.url; + newIceServers.push(server); + } else { + newIceServers.push(pcConfig.iceServers[i]); + } + } + pcConfig.iceServers = newIceServers; + } + return new OrigPeerConnection(pcConfig, pcConstraints); + }; + window.RTCPeerConnection.prototype = OrigPeerConnection.prototype; + // wrap static methods. Currently just generateCertificate. + Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', { + get: function() { + return OrigPeerConnection.generateCertificate; + } + }); + } + + var origGetStats = window.RTCPeerConnection.prototype.getStats; + window.RTCPeerConnection.prototype.getStats = function(selector, + successCallback, errorCallback) { + var pc = this; + var args = arguments; + + // If selector is a function then we are in the old style stats so just + // pass back the original getStats format to avoid breaking old users. + if (arguments.length > 0 && typeof selector === 'function') { + return origGetStats.apply(this, arguments); + } + + // When spec-style getStats is supported, return those when called with + // either no arguments or the selector argument is null. + if (origGetStats.length === 0 && (arguments.length === 0 || + typeof arguments[0] !== 'function')) { + return origGetStats.apply(this, []); + } + + var fixChromeStats_ = function(response) { + var standardReport = {}; + var reports = response.result(); + reports.forEach(function(report) { + var standardStats = { + id: report.id, + timestamp: report.timestamp, + type: { + localcandidate: 'local-candidate', + remotecandidate: 'remote-candidate' + }[report.type] || report.type + }; + report.names().forEach(function(name) { + standardStats[name] = report.stat(name); + }); + standardReport[standardStats.id] = standardStats; + }); + + return standardReport; + }; + + // shim getStats with maplike support + var makeMapStats = function(stats) { + return new Map(Object.keys(stats).map(function(key) { + return [key, stats[key]]; + })); + }; + + if (arguments.length >= 2) { + var successCallbackWrapper_ = function(response) { + args[1](makeMapStats(fixChromeStats_(response))); + }; + + return origGetStats.apply(this, [successCallbackWrapper_, + arguments[0]]); + } + + // promise-support + return new Promise(function(resolve, reject) { + origGetStats.apply(pc, [ + function(response) { + resolve(makeMapStats(fixChromeStats_(response))); + }, reject]); + }).then(successCallback, errorCallback); + }; + + // add promise support -- natively available in Chrome 51 + if (browserDetails.version < 51) { + ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'] + .forEach(function(method) { + var nativeMethod = window.RTCPeerConnection.prototype[method]; + window.RTCPeerConnection.prototype[method] = function() { + var args = arguments; + var pc = this; + var promise = new Promise(function(resolve, reject) { + nativeMethod.apply(pc, [args[0], resolve, reject]); + }); + if (args.length < 2) { + return promise; + } + return promise.then(function() { + args[1].apply(null, []); + }, + function(err) { + if (args.length >= 3) { + args[2].apply(null, [err]); + } + }); + }; + }); + } + + // promise support for createOffer and createAnswer. Available (without + // bugs) since M52: crbug/619289 + if (browserDetails.version < 52) { + ['createOffer', 'createAnswer'].forEach(function(method) { + var nativeMethod = window.RTCPeerConnection.prototype[method]; + window.RTCPeerConnection.prototype[method] = function() { + var pc = this; + if (arguments.length < 1 || (arguments.length === 1 && + typeof arguments[0] === 'object')) { + var opts = arguments.length === 1 ? arguments[0] : undefined; + return new Promise(function(resolve, reject) { + nativeMethod.apply(pc, [resolve, reject, opts]); + }); + } + return nativeMethod.apply(this, arguments); + }; + }); + } + + // shim implicit creation of RTCSessionDescription/RTCIceCandidate + ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'] + .forEach(function(method) { + var nativeMethod = window.RTCPeerConnection.prototype[method]; + window.RTCPeerConnection.prototype[method] = function() { + arguments[0] = new ((method === 'addIceCandidate') ? + window.RTCIceCandidate : + window.RTCSessionDescription)(arguments[0]); + return nativeMethod.apply(this, arguments); + }; + }); + + // support for addIceCandidate(null or undefined) + var nativeAddIceCandidate = + window.RTCPeerConnection.prototype.addIceCandidate; + window.RTCPeerConnection.prototype.addIceCandidate = function() { + if (!arguments[0]) { + if (arguments[1]) { + arguments[1].apply(null); + } + return Promise.resolve(); + } + return nativeAddIceCandidate.apply(this, arguments); + }; + } +}; + +},{"../utils.js":36,"./getusermedia":29}],29:[function(require,module,exports){ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ +'use strict'; +var utils = require('../utils.js'); +var logging = utils.log; + +// Expose public methods. +module.exports = function(window) { + var browserDetails = utils.detectBrowser(window); + var navigator = window && window.navigator; + + var constraintsToChrome_ = function(c) { + if (typeof c !== 'object' || c.mandatory || c.optional) { + return c; + } + var cc = {}; + Object.keys(c).forEach(function(key) { + if (key === 'require' || key === 'advanced' || key === 'mediaSource') { + return; + } + var r = (typeof c[key] === 'object') ? c[key] : {ideal: c[key]}; + if (r.exact !== undefined && typeof r.exact === 'number') { + r.min = r.max = r.exact; + } + var oldname_ = function(prefix, name) { + if (prefix) { + return prefix + name.charAt(0).toUpperCase() + name.slice(1); + } + return (name === 'deviceId') ? 'sourceId' : name; + }; + if (r.ideal !== undefined) { + cc.optional = cc.optional || []; + var oc = {}; + if (typeof r.ideal === 'number') { + oc[oldname_('min', key)] = r.ideal; + cc.optional.push(oc); + oc = {}; + oc[oldname_('max', key)] = r.ideal; + cc.optional.push(oc); + } else { + oc[oldname_('', key)] = r.ideal; + cc.optional.push(oc); + } + } + if (r.exact !== undefined && typeof r.exact !== 'number') { + cc.mandatory = cc.mandatory || {}; + cc.mandatory[oldname_('', key)] = r.exact; + } else { + ['min', 'max'].forEach(function(mix) { + if (r[mix] !== undefined) { + cc.mandatory = cc.mandatory || {}; + cc.mandatory[oldname_(mix, key)] = r[mix]; + } + }); + } + }); + if (c.advanced) { + cc.optional = (cc.optional || []).concat(c.advanced); + } + return cc; + }; + + var shimConstraints_ = function(constraints, func) { + if (browserDetails.version >= 61) { + return func(constraints); + } + constraints = JSON.parse(JSON.stringify(constraints)); + if (constraints && typeof constraints.audio === 'object') { + var remap = function(obj, a, b) { + if (a in obj && !(b in obj)) { + obj[b] = obj[a]; + delete obj[a]; + } + }; + constraints = JSON.parse(JSON.stringify(constraints)); + remap(constraints.audio, 'autoGainControl', 'googAutoGainControl'); + remap(constraints.audio, 'noiseSuppression', 'googNoiseSuppression'); + constraints.audio = constraintsToChrome_(constraints.audio); + } + if (constraints && typeof constraints.video === 'object') { + // Shim facingMode for mobile & surface pro. + var face = constraints.video.facingMode; + face = face && ((typeof face === 'object') ? face : {ideal: face}); + var getSupportedFacingModeLies = browserDetails.version < 66; + + if ((face && (face.exact === 'user' || face.exact === 'environment' || + face.ideal === 'user' || face.ideal === 'environment')) && + !(navigator.mediaDevices.getSupportedConstraints && + navigator.mediaDevices.getSupportedConstraints().facingMode && + !getSupportedFacingModeLies)) { + delete constraints.video.facingMode; + var matches; + if (face.exact === 'environment' || face.ideal === 'environment') { + matches = ['back', 'rear']; + } else if (face.exact === 'user' || face.ideal === 'user') { + matches = ['front']; + } + if (matches) { + // Look for matches in label, or use last cam for back (typical). + return navigator.mediaDevices.enumerateDevices() + .then(function(devices) { + devices = devices.filter(function(d) { + return d.kind === 'videoinput'; + }); + var dev = devices.find(function(d) { + return matches.some(function(match) { + return d.label.toLowerCase().indexOf(match) !== -1; + }); + }); + if (!dev && devices.length && matches.indexOf('back') !== -1) { + dev = devices[devices.length - 1]; // more likely the back cam + } + if (dev) { + constraints.video.deviceId = face.exact ? {exact: dev.deviceId} : + {ideal: dev.deviceId}; + } + constraints.video = constraintsToChrome_(constraints.video); + logging('chrome: ' + JSON.stringify(constraints)); + return func(constraints); + }); + } + } + constraints.video = constraintsToChrome_(constraints.video); + } + logging('chrome: ' + JSON.stringify(constraints)); + return func(constraints); + }; + + var shimError_ = function(e) { + return { + name: { + PermissionDeniedError: 'NotAllowedError', + InvalidStateError: 'NotReadableError', + DevicesNotFoundError: 'NotFoundError', + ConstraintNotSatisfiedError: 'OverconstrainedError', + TrackStartError: 'NotReadableError', + MediaDeviceFailedDueToShutdown: 'NotReadableError', + MediaDeviceKillSwitchOn: 'NotReadableError' + }[e.name] || e.name, + message: e.message, + constraint: e.constraintName, + toString: function() { + return this.name + (this.message && ': ') + this.message; + } + }; + }; + + var getUserMedia_ = function(constraints, onSuccess, onError) { + shimConstraints_(constraints, function(c) { + navigator.webkitGetUserMedia(c, onSuccess, function(e) { + if (onError) { + onError(shimError_(e)); + } + }); + }); + }; + + navigator.getUserMedia = getUserMedia_; + + // Returns the result of getUserMedia as a Promise. + var getUserMediaPromise_ = function(constraints) { + return new Promise(function(resolve, reject) { + navigator.getUserMedia(constraints, resolve, reject); + }); + }; + + if (!navigator.mediaDevices) { + navigator.mediaDevices = { + getUserMedia: getUserMediaPromise_, + enumerateDevices: function() { + return new Promise(function(resolve) { + var kinds = {audio: 'audioinput', video: 'videoinput'}; + return window.MediaStreamTrack.getSources(function(devices) { + resolve(devices.map(function(device) { + return {label: device.label, + kind: kinds[device.kind], + deviceId: device.id, + groupId: ''}; + })); + }); + }); + }, + getSupportedConstraints: function() { + return { + deviceId: true, echoCancellation: true, facingMode: true, + frameRate: true, height: true, width: true + }; + } + }; + } + + // A shim for getUserMedia method on the mediaDevices object. + // TODO(KaptenJansson) remove once implemented in Chrome stable. + if (!navigator.mediaDevices.getUserMedia) { + navigator.mediaDevices.getUserMedia = function(constraints) { + return getUserMediaPromise_(constraints); + }; + } else { + // Even though Chrome 45 has navigator.mediaDevices and a getUserMedia + // function which returns a Promise, it does not accept spec-style + // constraints. + var origGetUserMedia = navigator.mediaDevices.getUserMedia. + bind(navigator.mediaDevices); + navigator.mediaDevices.getUserMedia = function(cs) { + return shimConstraints_(cs, function(c) { + return origGetUserMedia(c).then(function(stream) { + if (c.audio && !stream.getAudioTracks().length || + c.video && !stream.getVideoTracks().length) { + stream.getTracks().forEach(function(track) { + track.stop(); + }); + throw new DOMException('', 'NotFoundError'); + } + return stream; + }, function(e) { + return Promise.reject(shimError_(e)); + }); + }); + }; + } + + // Dummy devicechange event methods. + // TODO(KaptenJansson) remove once implemented in Chrome stable. + if (typeof navigator.mediaDevices.addEventListener === 'undefined') { + navigator.mediaDevices.addEventListener = function() { + logging('Dummy mediaDevices.addEventListener called.'); + }; + } + if (typeof navigator.mediaDevices.removeEventListener === 'undefined') { + navigator.mediaDevices.removeEventListener = function() { + logging('Dummy mediaDevices.removeEventListener called.'); + }; + } +}; + +},{"../utils.js":36}],30:[function(require,module,exports){ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ +'use strict'; + +var SDPUtils = require('sdp'); +var utils = require('./utils'); + +module.exports = { + shimRTCIceCandidate: function(window) { + // foundation is arbitrarily chosen as an indicator for full support for + // https://w3c.github.io/webrtc-pc/#rtcicecandidate-interface + if (window.RTCIceCandidate && 'foundation' in + window.RTCIceCandidate.prototype) { + return; + } + + var NativeRTCIceCandidate = window.RTCIceCandidate; + window.RTCIceCandidate = function(args) { + // Remove the a= which shouldn't be part of the candidate string. + if (typeof args === 'object' && args.candidate && + args.candidate.indexOf('a=') === 0) { + args = JSON.parse(JSON.stringify(args)); + args.candidate = args.candidate.substr(2); + } + + // Augment the native candidate with the parsed fields. + var nativeCandidate = new NativeRTCIceCandidate(args); + var parsedCandidate = SDPUtils.parseCandidate(args.candidate); + var augmentedCandidate = Object.assign(nativeCandidate, + parsedCandidate); + + // Add a serializer that does not serialize the extra attributes. + augmentedCandidate.toJSON = function() { + return { + candidate: augmentedCandidate.candidate, + sdpMid: augmentedCandidate.sdpMid, + sdpMLineIndex: augmentedCandidate.sdpMLineIndex, + usernameFragment: augmentedCandidate.usernameFragment, + }; + }; + return augmentedCandidate; + }; + + // Hook up the augmented candidate in onicecandidate and + // addEventListener('icecandidate', ...) + utils.wrapPeerConnectionEvent(window, 'icecandidate', function(e) { + if (e.candidate) { + Object.defineProperty(e, 'candidate', { + value: new window.RTCIceCandidate(e.candidate), + writable: 'false' + }); + } + return e; + }); + }, + + // shimCreateObjectURL must be called before shimSourceObject to avoid loop. + + shimCreateObjectURL: function(window) { + var URL = window && window.URL; + + if (!(typeof window === 'object' && window.HTMLMediaElement && + 'srcObject' in window.HTMLMediaElement.prototype && + URL.createObjectURL && URL.revokeObjectURL)) { + // Only shim CreateObjectURL using srcObject if srcObject exists. + return undefined; + } + + var nativeCreateObjectURL = URL.createObjectURL.bind(URL); + var nativeRevokeObjectURL = URL.revokeObjectURL.bind(URL); + var streams = new Map(), newId = 0; + + URL.createObjectURL = function(stream) { + if ('getTracks' in stream) { + var url = 'polyblob:' + (++newId); + streams.set(url, stream); + utils.deprecated('URL.createObjectURL(stream)', + 'elem.srcObject = stream'); + return url; + } + return nativeCreateObjectURL(stream); + }; + URL.revokeObjectURL = function(url) { + nativeRevokeObjectURL(url); + streams.delete(url); + }; + + var dsc = Object.getOwnPropertyDescriptor(window.HTMLMediaElement.prototype, + 'src'); + Object.defineProperty(window.HTMLMediaElement.prototype, 'src', { + get: function() { + return dsc.get.apply(this); + }, + set: function(url) { + this.srcObject = streams.get(url) || null; + return dsc.set.apply(this, [url]); + } + }); + + var nativeSetAttribute = window.HTMLMediaElement.prototype.setAttribute; + window.HTMLMediaElement.prototype.setAttribute = function() { + if (arguments.length === 2 && + ('' + arguments[0]).toLowerCase() === 'src') { + this.srcObject = streams.get(arguments[1]) || null; + } + return nativeSetAttribute.apply(this, arguments); + }; + }, + + shimMaxMessageSize: function(window) { + if (window.RTCSctpTransport || !window.RTCPeerConnection) { + return; + } + var browserDetails = utils.detectBrowser(window); + + if (!('sctp' in window.RTCPeerConnection.prototype)) { + Object.defineProperty(window.RTCPeerConnection.prototype, 'sctp', { + get: function() { + return typeof this._sctp === 'undefined' ? null : this._sctp; + } + }); + } + + var sctpInDescription = function(description) { + var sections = SDPUtils.splitSections(description.sdp); + sections.shift(); + return sections.some(function(mediaSection) { + var mLine = SDPUtils.parseMLine(mediaSection); + return mLine && mLine.kind === 'application' + && mLine.protocol.indexOf('SCTP') !== -1; + }); + }; + + var getRemoteFirefoxVersion = function(description) { + // TODO: Is there a better solution for detecting Firefox? + var match = description.sdp.match(/mozilla...THIS_IS_SDPARTA-(\d+)/); + if (match === null || match.length < 2) { + return -1; + } + var version = parseInt(match[1], 10); + // Test for NaN (yes, this is ugly) + return version !== version ? -1 : version; + }; + + var getCanSendMaxMessageSize = function(remoteIsFirefox) { + // Every implementation we know can send at least 64 KiB. + // Note: Although Chrome is technically able to send up to 256 KiB, the + // data does not reach the other peer reliably. + // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=8419 + var canSendMaxMessageSize = 65536; + if (browserDetails.browser === 'firefox') { + if (browserDetails.version < 57) { + if (remoteIsFirefox === -1) { + // FF < 57 will send in 16 KiB chunks using the deprecated PPID + // fragmentation. + canSendMaxMessageSize = 16384; + } else { + // However, other FF (and RAWRTC) can reassemble PPID-fragmented + // messages. Thus, supporting ~2 GiB when sending. + canSendMaxMessageSize = 2147483637; + } + } else { + // Currently, all FF >= 57 will reset the remote maximum message size + // to the default value when a data channel is created at a later + // stage. :( + // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831 + canSendMaxMessageSize = + browserDetails.version === 57 ? 65535 : 65536; + } + } + return canSendMaxMessageSize; + }; + + var getMaxMessageSize = function(description, remoteIsFirefox) { + // Note: 65536 bytes is the default value from the SDP spec. Also, + // every implementation we know supports receiving 65536 bytes. + var maxMessageSize = 65536; + + // FF 57 has a slightly incorrect default remote max message size, so + // we need to adjust it here to avoid a failure when sending. + // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1425697 + if (browserDetails.browser === 'firefox' + && browserDetails.version === 57) { + maxMessageSize = 65535; + } + + var match = SDPUtils.matchPrefix(description.sdp, 'a=max-message-size:'); + if (match.length > 0) { + maxMessageSize = parseInt(match[0].substr(19), 10); + } else if (browserDetails.browser === 'firefox' && + remoteIsFirefox !== -1) { + // If the maximum message size is not present in the remote SDP and + // both local and remote are Firefox, the remote peer can receive + // ~2 GiB. + maxMessageSize = 2147483637; + } + return maxMessageSize; + }; + + var origSetRemoteDescription = + window.RTCPeerConnection.prototype.setRemoteDescription; + window.RTCPeerConnection.prototype.setRemoteDescription = function() { + var pc = this; + pc._sctp = null; + + if (sctpInDescription(arguments[0])) { + // Check if the remote is FF. + var isFirefox = getRemoteFirefoxVersion(arguments[0]); + + // Get the maximum message size the local peer is capable of sending + var canSendMMS = getCanSendMaxMessageSize(isFirefox); + + // Get the maximum message size of the remote peer. + var remoteMMS = getMaxMessageSize(arguments[0], isFirefox); + + // Determine final maximum message size + var maxMessageSize; + if (canSendMMS === 0 && remoteMMS === 0) { + maxMessageSize = Number.POSITIVE_INFINITY; + } else if (canSendMMS === 0 || remoteMMS === 0) { + maxMessageSize = Math.max(canSendMMS, remoteMMS); + } else { + maxMessageSize = Math.min(canSendMMS, remoteMMS); + } + + // Create a dummy RTCSctpTransport object and the 'maxMessageSize' + // attribute. + var sctp = {}; + Object.defineProperty(sctp, 'maxMessageSize', { + get: function() { + return maxMessageSize; + } + }); + pc._sctp = sctp; + } + + return origSetRemoteDescription.apply(pc, arguments); + }; + }, + + shimSendThrowTypeError: function(window) { + // Note: Although Firefox >= 57 has a native implementation, the maximum + // message size can be reset for all data channels at a later stage. + // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831 + + var origCreateDataChannel = + window.RTCPeerConnection.prototype.createDataChannel; + window.RTCPeerConnection.prototype.createDataChannel = function() { + var pc = this; + var dataChannel = origCreateDataChannel.apply(pc, arguments); + var origDataChannelSend = dataChannel.send; + + // Patch 'send' method + dataChannel.send = function() { + var dc = this; + var data = arguments[0]; + var length = data.length || data.size || data.byteLength; + if (length > pc.sctp.maxMessageSize) { + throw new DOMException('Message too large (can send a maximum of ' + + pc.sctp.maxMessageSize + ' bytes)', 'TypeError'); + } + return origDataChannelSend.apply(dc, arguments); + }; + + return dataChannel; + }; + } +}; + +},{"./utils":36,"sdp":19}],31:[function(require,module,exports){ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ +'use strict'; + +var utils = require('../utils'); +var shimRTCPeerConnection = require('rtcpeerconnection-shim'); + +module.exports = { + shimGetUserMedia: require('./getusermedia'), + shimPeerConnection: function(window) { + var browserDetails = utils.detectBrowser(window); + + if (window.RTCIceGatherer) { + // ORTC defines an RTCIceCandidate object but no constructor. + // Not implemented in Edge. + if (!window.RTCIceCandidate) { + window.RTCIceCandidate = function(args) { + return args; + }; + } + // ORTC does not have a session description object but + // other browsers (i.e. Chrome) that will support both PC and ORTC + // in the future might have this defined already. + if (!window.RTCSessionDescription) { + window.RTCSessionDescription = function(args) { + return args; + }; + } + // this adds an additional event listener to MediaStrackTrack that signals + // when a tracks enabled property was changed. Workaround for a bug in + // addStream, see below. No longer required in 15025+ + if (browserDetails.version < 15025) { + var origMSTEnabled = Object.getOwnPropertyDescriptor( + window.MediaStreamTrack.prototype, 'enabled'); + Object.defineProperty(window.MediaStreamTrack.prototype, 'enabled', { + set: function(value) { + origMSTEnabled.set.call(this, value); + var ev = new Event('enabled'); + ev.enabled = value; + this.dispatchEvent(ev); + } + }); + } + } + + // ORTC defines the DTMF sender a bit different. + // https://github.com/w3c/ortc/issues/714 + if (window.RTCRtpSender && !('dtmf' in window.RTCRtpSender.prototype)) { + Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', { + get: function() { + if (this._dtmf === undefined) { + if (this.track.kind === 'audio') { + this._dtmf = new window.RTCDtmfSender(this); + } else if (this.track.kind === 'video') { + this._dtmf = null; + } + } + return this._dtmf; + } + }); + } + + window.RTCPeerConnection = + shimRTCPeerConnection(window, browserDetails.version); + }, + shimReplaceTrack: function(window) { + // ORTC has replaceTrack -- https://github.com/w3c/ortc/issues/614 + if (window.RTCRtpSender && + !('replaceTrack' in window.RTCRtpSender.prototype)) { + window.RTCRtpSender.prototype.replaceTrack = + window.RTCRtpSender.prototype.setTrack; + } + } +}; + +},{"../utils":36,"./getusermedia":32,"rtcpeerconnection-shim":10}],32:[function(require,module,exports){ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ +'use strict'; + +// Expose public methods. +module.exports = function(window) { + var navigator = window && window.navigator; + + var shimError_ = function(e) { + return { + name: {PermissionDeniedError: 'NotAllowedError'}[e.name] || e.name, + message: e.message, + constraint: e.constraint, + toString: function() { + return this.name; + } + }; + }; + + // getUserMedia error shim. + var origGetUserMedia = navigator.mediaDevices.getUserMedia. + bind(navigator.mediaDevices); + navigator.mediaDevices.getUserMedia = function(c) { + return origGetUserMedia(c).catch(function(e) { + return Promise.reject(shimError_(e)); + }); + }; +}; + +},{}],33:[function(require,module,exports){ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ +'use strict'; + +var utils = require('../utils'); + +module.exports = { + shimGetUserMedia: require('./getusermedia'), + shimOnTrack: function(window) { + if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in + window.RTCPeerConnection.prototype)) { + Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', { + get: function() { + return this._ontrack; + }, + set: function(f) { + if (this._ontrack) { + this.removeEventListener('track', this._ontrack); + this.removeEventListener('addstream', this._ontrackpoly); + } + this.addEventListener('track', this._ontrack = f); + this.addEventListener('addstream', this._ontrackpoly = function(e) { + e.stream.getTracks().forEach(function(track) { + var event = new Event('track'); + event.track = track; + event.receiver = {track: track}; + event.transceiver = {receiver: event.receiver}; + event.streams = [e.stream]; + this.dispatchEvent(event); + }.bind(this)); + }.bind(this)); + } + }); + } + if (typeof window === 'object' && window.RTCTrackEvent && + ('receiver' in window.RTCTrackEvent.prototype) && + !('transceiver' in window.RTCTrackEvent.prototype)) { + Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', { + get: function() { + return {receiver: this.receiver}; + } + }); + } + }, + + shimSourceObject: function(window) { + // Firefox has supported mozSrcObject since FF22, unprefixed in 42. + if (typeof window === 'object') { + if (window.HTMLMediaElement && + !('srcObject' in window.HTMLMediaElement.prototype)) { + // Shim the srcObject property, once, when HTMLMediaElement is found. + Object.defineProperty(window.HTMLMediaElement.prototype, 'srcObject', { + get: function() { + return this.mozSrcObject; + }, + set: function(stream) { + this.mozSrcObject = stream; + } + }); + } + } + }, + + shimPeerConnection: function(window) { + var browserDetails = utils.detectBrowser(window); + + if (typeof window !== 'object' || !(window.RTCPeerConnection || + window.mozRTCPeerConnection)) { + return; // probably media.peerconnection.enabled=false in about:config + } + // The RTCPeerConnection object. + if (!window.RTCPeerConnection) { + window.RTCPeerConnection = function(pcConfig, pcConstraints) { + if (browserDetails.version < 38) { + // .urls is not supported in FF < 38. + // create RTCIceServers with a single url. + if (pcConfig && pcConfig.iceServers) { + var newIceServers = []; + for (var i = 0; i < pcConfig.iceServers.length; i++) { + var server = pcConfig.iceServers[i]; + if (server.hasOwnProperty('urls')) { + for (var j = 0; j < server.urls.length; j++) { + var newServer = { + url: server.urls[j] + }; + if (server.urls[j].indexOf('turn') === 0) { + newServer.username = server.username; + newServer.credential = server.credential; + } + newIceServers.push(newServer); + } + } else { + newIceServers.push(pcConfig.iceServers[i]); + } + } + pcConfig.iceServers = newIceServers; + } + } + return new window.mozRTCPeerConnection(pcConfig, pcConstraints); + }; + window.RTCPeerConnection.prototype = + window.mozRTCPeerConnection.prototype; + + // wrap static methods. Currently just generateCertificate. + if (window.mozRTCPeerConnection.generateCertificate) { + Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', { + get: function() { + return window.mozRTCPeerConnection.generateCertificate; + } + }); + } + + window.RTCSessionDescription = window.mozRTCSessionDescription; + window.RTCIceCandidate = window.mozRTCIceCandidate; + } + + // shim away need for obsolete RTCIceCandidate/RTCSessionDescription. + ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'] + .forEach(function(method) { + var nativeMethod = window.RTCPeerConnection.prototype[method]; + window.RTCPeerConnection.prototype[method] = function() { + arguments[0] = new ((method === 'addIceCandidate') ? + window.RTCIceCandidate : + window.RTCSessionDescription)(arguments[0]); + return nativeMethod.apply(this, arguments); + }; + }); + + // support for addIceCandidate(null or undefined) + var nativeAddIceCandidate = + window.RTCPeerConnection.prototype.addIceCandidate; + window.RTCPeerConnection.prototype.addIceCandidate = function() { + if (!arguments[0]) { + if (arguments[1]) { + arguments[1].apply(null); + } + return Promise.resolve(); + } + return nativeAddIceCandidate.apply(this, arguments); + }; + + // shim getStats with maplike support + var makeMapStats = function(stats) { + var map = new Map(); + Object.keys(stats).forEach(function(key) { + map.set(key, stats[key]); + map[key] = stats[key]; + }); + return map; + }; + + var modernStatsTypes = { + inboundrtp: 'inbound-rtp', + outboundrtp: 'outbound-rtp', + candidatepair: 'candidate-pair', + localcandidate: 'local-candidate', + remotecandidate: 'remote-candidate' + }; + + var nativeGetStats = window.RTCPeerConnection.prototype.getStats; + window.RTCPeerConnection.prototype.getStats = function( + selector, + onSucc, + onErr + ) { + return nativeGetStats.apply(this, [selector || null]) + .then(function(stats) { + if (browserDetails.version < 48) { + stats = makeMapStats(stats); + } + if (browserDetails.version < 53 && !onSucc) { + // Shim only promise getStats with spec-hyphens in type names + // Leave callback version alone; misc old uses of forEach before Map + try { + stats.forEach(function(stat) { + stat.type = modernStatsTypes[stat.type] || stat.type; + }); + } catch (e) { + if (e.name !== 'TypeError') { + throw e; + } + // Avoid TypeError: "type" is read-only, in old versions. 34-43ish + stats.forEach(function(stat, i) { + stats.set(i, Object.assign({}, stat, { + type: modernStatsTypes[stat.type] || stat.type + })); + }); + } + } + return stats; + }) + .then(onSucc, onErr); + }; + }, + + shimRemoveStream: function(window) { + if (!window.RTCPeerConnection || + 'removeStream' in window.RTCPeerConnection.prototype) { + return; + } + window.RTCPeerConnection.prototype.removeStream = function(stream) { + var pc = this; + utils.deprecated('removeStream', 'removeTrack'); + this.getSenders().forEach(function(sender) { + if (sender.track && stream.getTracks().indexOf(sender.track) !== -1) { + pc.removeTrack(sender); + } + }); + }; + } +}; + +},{"../utils":36,"./getusermedia":34}],34:[function(require,module,exports){ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ +'use strict'; + +var utils = require('../utils'); +var logging = utils.log; + +// Expose public methods. +module.exports = function(window) { + var browserDetails = utils.detectBrowser(window); + var navigator = window && window.navigator; + var MediaStreamTrack = window && window.MediaStreamTrack; + + var shimError_ = function(e) { + return { + name: { + InternalError: 'NotReadableError', + NotSupportedError: 'TypeError', + PermissionDeniedError: 'NotAllowedError', + SecurityError: 'NotAllowedError' + }[e.name] || e.name, + message: { + 'The operation is insecure.': 'The request is not allowed by the ' + + 'user agent or the platform in the current context.' + }[e.message] || e.message, + constraint: e.constraint, + toString: function() { + return this.name + (this.message && ': ') + this.message; + } + }; + }; + + // getUserMedia constraints shim. + var getUserMedia_ = function(constraints, onSuccess, onError) { + var constraintsToFF37_ = function(c) { + if (typeof c !== 'object' || c.require) { + return c; + } + var require = []; + Object.keys(c).forEach(function(key) { + if (key === 'require' || key === 'advanced' || key === 'mediaSource') { + return; + } + var r = c[key] = (typeof c[key] === 'object') ? + c[key] : {ideal: c[key]}; + if (r.min !== undefined || + r.max !== undefined || r.exact !== undefined) { + require.push(key); + } + if (r.exact !== undefined) { + if (typeof r.exact === 'number') { + r. min = r.max = r.exact; + } else { + c[key] = r.exact; + } + delete r.exact; + } + if (r.ideal !== undefined) { + c.advanced = c.advanced || []; + var oc = {}; + if (typeof r.ideal === 'number') { + oc[key] = {min: r.ideal, max: r.ideal}; + } else { + oc[key] = r.ideal; + } + c.advanced.push(oc); + delete r.ideal; + if (!Object.keys(r).length) { + delete c[key]; + } + } + }); + if (require.length) { + c.require = require; + } + return c; + }; + constraints = JSON.parse(JSON.stringify(constraints)); + if (browserDetails.version < 38) { + logging('spec: ' + JSON.stringify(constraints)); + if (constraints.audio) { + constraints.audio = constraintsToFF37_(constraints.audio); + } + if (constraints.video) { + constraints.video = constraintsToFF37_(constraints.video); + } + logging('ff37: ' + JSON.stringify(constraints)); + } + return navigator.mozGetUserMedia(constraints, onSuccess, function(e) { + onError(shimError_(e)); + }); + }; + + // Returns the result of getUserMedia as a Promise. + var getUserMediaPromise_ = function(constraints) { + return new Promise(function(resolve, reject) { + getUserMedia_(constraints, resolve, reject); + }); + }; + + // Shim for mediaDevices on older versions. + if (!navigator.mediaDevices) { + navigator.mediaDevices = {getUserMedia: getUserMediaPromise_, + addEventListener: function() { }, + removeEventListener: function() { } + }; + } + navigator.mediaDevices.enumerateDevices = + navigator.mediaDevices.enumerateDevices || function() { + return new Promise(function(resolve) { + var infos = [ + {kind: 'audioinput', deviceId: 'default', label: '', groupId: ''}, + {kind: 'videoinput', deviceId: 'default', label: '', groupId: ''} + ]; + resolve(infos); + }); + }; + + if (browserDetails.version < 41) { + // Work around http://bugzil.la/1169665 + var orgEnumerateDevices = + navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices); + navigator.mediaDevices.enumerateDevices = function() { + return orgEnumerateDevices().then(undefined, function(e) { + if (e.name === 'NotFoundError') { + return []; + } + throw e; + }); + }; + } + if (browserDetails.version < 49) { + var origGetUserMedia = navigator.mediaDevices.getUserMedia. + bind(navigator.mediaDevices); + navigator.mediaDevices.getUserMedia = function(c) { + return origGetUserMedia(c).then(function(stream) { + // Work around https://bugzil.la/802326 + if (c.audio && !stream.getAudioTracks().length || + c.video && !stream.getVideoTracks().length) { + stream.getTracks().forEach(function(track) { + track.stop(); + }); + throw new DOMException('The object can not be found here.', + 'NotFoundError'); + } + return stream; + }, function(e) { + return Promise.reject(shimError_(e)); + }); + }; + } + if (!(browserDetails.version > 55 && + 'autoGainControl' in navigator.mediaDevices.getSupportedConstraints())) { + var remap = function(obj, a, b) { + if (a in obj && !(b in obj)) { + obj[b] = obj[a]; + delete obj[a]; + } + }; + + var nativeGetUserMedia = navigator.mediaDevices.getUserMedia. + bind(navigator.mediaDevices); + navigator.mediaDevices.getUserMedia = function(c) { + if (typeof c === 'object' && typeof c.audio === 'object') { + c = JSON.parse(JSON.stringify(c)); + remap(c.audio, 'autoGainControl', 'mozAutoGainControl'); + remap(c.audio, 'noiseSuppression', 'mozNoiseSuppression'); + } + return nativeGetUserMedia(c); + }; + + if (MediaStreamTrack && MediaStreamTrack.prototype.getSettings) { + var nativeGetSettings = MediaStreamTrack.prototype.getSettings; + MediaStreamTrack.prototype.getSettings = function() { + var obj = nativeGetSettings.apply(this, arguments); + remap(obj, 'mozAutoGainControl', 'autoGainControl'); + remap(obj, 'mozNoiseSuppression', 'noiseSuppression'); + return obj; + }; + } + + if (MediaStreamTrack && MediaStreamTrack.prototype.applyConstraints) { + var nativeApplyConstraints = MediaStreamTrack.prototype.applyConstraints; + MediaStreamTrack.prototype.applyConstraints = function(c) { + if (this.kind === 'audio' && typeof c === 'object') { + c = JSON.parse(JSON.stringify(c)); + remap(c, 'autoGainControl', 'mozAutoGainControl'); + remap(c, 'noiseSuppression', 'mozNoiseSuppression'); + } + return nativeApplyConstraints.apply(this, [c]); + }; + } + } + navigator.getUserMedia = function(constraints, onSuccess, onError) { + if (browserDetails.version < 44) { + return getUserMedia_(constraints, onSuccess, onError); + } + // Replace Firefox 44+'s deprecation warning with unprefixed version. + utils.deprecated('navigator.getUserMedia', + 'navigator.mediaDevices.getUserMedia'); + navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError); + }; +}; + +},{"../utils":36}],35:[function(require,module,exports){ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ +'use strict'; +var utils = require('../utils'); + +module.exports = { + shimLocalStreamsAPI: function(window) { + if (typeof window !== 'object' || !window.RTCPeerConnection) { + return; + } + if (!('getLocalStreams' in window.RTCPeerConnection.prototype)) { + window.RTCPeerConnection.prototype.getLocalStreams = function() { + if (!this._localStreams) { + this._localStreams = []; + } + return this._localStreams; + }; + } + if (!('getStreamById' in window.RTCPeerConnection.prototype)) { + window.RTCPeerConnection.prototype.getStreamById = function(id) { + var result = null; + if (this._localStreams) { + this._localStreams.forEach(function(stream) { + if (stream.id === id) { + result = stream; + } + }); + } + if (this._remoteStreams) { + this._remoteStreams.forEach(function(stream) { + if (stream.id === id) { + result = stream; + } + }); + } + return result; + }; + } + if (!('addStream' in window.RTCPeerConnection.prototype)) { + var _addTrack = window.RTCPeerConnection.prototype.addTrack; + window.RTCPeerConnection.prototype.addStream = function(stream) { + if (!this._localStreams) { + this._localStreams = []; + } + if (this._localStreams.indexOf(stream) === -1) { + this._localStreams.push(stream); + } + var pc = this; + stream.getTracks().forEach(function(track) { + _addTrack.call(pc, track, stream); + }); + }; + + window.RTCPeerConnection.prototype.addTrack = function(track, stream) { + if (stream) { + if (!this._localStreams) { + this._localStreams = [stream]; + } else if (this._localStreams.indexOf(stream) === -1) { + this._localStreams.push(stream); + } + } + return _addTrack.call(this, track, stream); + }; + } + if (!('removeStream' in window.RTCPeerConnection.prototype)) { + window.RTCPeerConnection.prototype.removeStream = function(stream) { + if (!this._localStreams) { + this._localStreams = []; + } + var index = this._localStreams.indexOf(stream); + if (index === -1) { + return; + } + this._localStreams.splice(index, 1); + var pc = this; + var tracks = stream.getTracks(); + this.getSenders().forEach(function(sender) { + if (tracks.indexOf(sender.track) !== -1) { + pc.removeTrack(sender); + } + }); + }; + } + }, + shimRemoteStreamsAPI: function(window) { + if (typeof window !== 'object' || !window.RTCPeerConnection) { + return; + } + if (!('getRemoteStreams' in window.RTCPeerConnection.prototype)) { + window.RTCPeerConnection.prototype.getRemoteStreams = function() { + return this._remoteStreams ? this._remoteStreams : []; + }; + } + if (!('onaddstream' in window.RTCPeerConnection.prototype)) { + Object.defineProperty(window.RTCPeerConnection.prototype, 'onaddstream', { + get: function() { + return this._onaddstream; + }, + set: function(f) { + var pc = this; + if (this._onaddstream) { + this.removeEventListener('addstream', this._onaddstream); + this.removeEventListener('track', this._onaddstreampoly); + } + this.addEventListener('addstream', this._onaddstream = f); + this.addEventListener('track', this._onaddstreampoly = function(e) { + e.streams.forEach(function(stream) { + if (!pc._remoteStreams) { + pc._remoteStreams = []; + } + if (pc._remoteStreams.indexOf(stream) >= 0) { + return; + } + pc._remoteStreams.push(stream); + var event = new Event('addstream'); + event.stream = stream; + pc.dispatchEvent(event); + }); + }); + } + }); + } + }, + shimCallbacksAPI: function(window) { + if (typeof window !== 'object' || !window.RTCPeerConnection) { + return; + } + var prototype = window.RTCPeerConnection.prototype; + var createOffer = prototype.createOffer; + var createAnswer = prototype.createAnswer; + var setLocalDescription = prototype.setLocalDescription; + var setRemoteDescription = prototype.setRemoteDescription; + var addIceCandidate = prototype.addIceCandidate; + + prototype.createOffer = function(successCallback, failureCallback) { + var options = (arguments.length >= 2) ? arguments[2] : arguments[0]; + var promise = createOffer.apply(this, [options]); + if (!failureCallback) { + return promise; + } + promise.then(successCallback, failureCallback); + return Promise.resolve(); + }; + + prototype.createAnswer = function(successCallback, failureCallback) { + var options = (arguments.length >= 2) ? arguments[2] : arguments[0]; + var promise = createAnswer.apply(this, [options]); + if (!failureCallback) { + return promise; + } + promise.then(successCallback, failureCallback); + return Promise.resolve(); + }; + + var withCallback = function(description, successCallback, failureCallback) { + var promise = setLocalDescription.apply(this, [description]); + if (!failureCallback) { + return promise; + } + promise.then(successCallback, failureCallback); + return Promise.resolve(); + }; + prototype.setLocalDescription = withCallback; + + withCallback = function(description, successCallback, failureCallback) { + var promise = setRemoteDescription.apply(this, [description]); + if (!failureCallback) { + return promise; + } + promise.then(successCallback, failureCallback); + return Promise.resolve(); + }; + prototype.setRemoteDescription = withCallback; + + withCallback = function(candidate, successCallback, failureCallback) { + var promise = addIceCandidate.apply(this, [candidate]); + if (!failureCallback) { + return promise; + } + promise.then(successCallback, failureCallback); + return Promise.resolve(); + }; + prototype.addIceCandidate = withCallback; + }, + shimGetUserMedia: function(window) { + var navigator = window && window.navigator; + + if (!navigator.getUserMedia) { + if (navigator.webkitGetUserMedia) { + navigator.getUserMedia = navigator.webkitGetUserMedia.bind(navigator); + } else if (navigator.mediaDevices && + navigator.mediaDevices.getUserMedia) { + navigator.getUserMedia = function(constraints, cb, errcb) { + navigator.mediaDevices.getUserMedia(constraints) + .then(cb, errcb); + }.bind(navigator); + } + } + }, + shimRTCIceServerUrls: function(window) { + // migrate from non-spec RTCIceServer.url to RTCIceServer.urls + var OrigPeerConnection = window.RTCPeerConnection; + window.RTCPeerConnection = function(pcConfig, pcConstraints) { + if (pcConfig && pcConfig.iceServers) { + var newIceServers = []; + for (var i = 0; i < pcConfig.iceServers.length; i++) { + var server = pcConfig.iceServers[i]; + if (!server.hasOwnProperty('urls') && + server.hasOwnProperty('url')) { + utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls'); + server = JSON.parse(JSON.stringify(server)); + server.urls = server.url; + delete server.url; + newIceServers.push(server); + } else { + newIceServers.push(pcConfig.iceServers[i]); + } + } + pcConfig.iceServers = newIceServers; + } + return new OrigPeerConnection(pcConfig, pcConstraints); + }; + window.RTCPeerConnection.prototype = OrigPeerConnection.prototype; + // wrap static methods. Currently just generateCertificate. + if ('generateCertificate' in window.RTCPeerConnection) { + Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', { + get: function() { + return OrigPeerConnection.generateCertificate; + } + }); + } + }, + shimTrackEventTransceiver: function(window) { + // Add event.transceiver member over deprecated event.receiver + if (typeof window === 'object' && window.RTCPeerConnection && + ('receiver' in window.RTCTrackEvent.prototype) && + // can't check 'transceiver' in window.RTCTrackEvent.prototype, as it is + // defined for some reason even when window.RTCTransceiver is not. + !window.RTCTransceiver) { + Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', { + get: function() { + return {receiver: this.receiver}; + } + }); + } + }, + + shimCreateOfferLegacy: function(window) { + var origCreateOffer = window.RTCPeerConnection.prototype.createOffer; + window.RTCPeerConnection.prototype.createOffer = function(offerOptions) { + var pc = this; + if (offerOptions) { + var audioTransceiver = pc.getTransceivers().find(function(transceiver) { + return transceiver.sender.track && + transceiver.sender.track.kind === 'audio'; + }); + if (offerOptions.offerToReceiveAudio === false && audioTransceiver) { + if (audioTransceiver.direction === 'sendrecv') { + if (audioTransceiver.setDirection) { + audioTransceiver.setDirection('sendonly'); + } else { + audioTransceiver.direction = 'sendonly'; + } + } else if (audioTransceiver.direction === 'recvonly') { + if (audioTransceiver.setDirection) { + audioTransceiver.setDirection('inactive'); + } else { + audioTransceiver.direction = 'inactive'; + } + } + } else if (offerOptions.offerToReceiveAudio === true && + !audioTransceiver) { + pc.addTransceiver('audio'); + } + + var videoTransceiver = pc.getTransceivers().find(function(transceiver) { + return transceiver.sender.track && + transceiver.sender.track.kind === 'video'; + }); + if (offerOptions.offerToReceiveVideo === false && videoTransceiver) { + if (videoTransceiver.direction === 'sendrecv') { + videoTransceiver.setDirection('sendonly'); + } else if (videoTransceiver.direction === 'recvonly') { + videoTransceiver.setDirection('inactive'); + } + } else if (offerOptions.offerToReceiveVideo === true && + !videoTransceiver) { + pc.addTransceiver('video'); + } + } + return origCreateOffer.apply(pc, arguments); + }; + } +}; + +},{"../utils":36}],36:[function(require,module,exports){ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. + */ + /* eslint-env node */ +'use strict'; + +var logDisabled_ = true; +var deprecationWarnings_ = true; + +/** + * Extract browser version out of the provided user agent string. + * + * @param {!string} uastring userAgent string. + * @param {!string} expr Regular expression used as match criteria. + * @param {!number} pos position in the version string to be returned. + * @return {!number} browser version. + */ +function extractVersion(uastring, expr, pos) { + var match = uastring.match(expr); + return match && match.length >= pos && parseInt(match[pos], 10); +} + +// Wraps the peerconnection event eventNameToWrap in a function +// which returns the modified event object. +function wrapPeerConnectionEvent(window, eventNameToWrap, wrapper) { + if (!window.RTCPeerConnection) { + return; + } + var proto = window.RTCPeerConnection.prototype; + var nativeAddEventListener = proto.addEventListener; + proto.addEventListener = function(nativeEventName, cb) { + if (nativeEventName !== eventNameToWrap) { + return nativeAddEventListener.apply(this, arguments); + } + var wrappedCallback = function(e) { + cb(wrapper(e)); + }; + this._eventMap = this._eventMap || {}; + this._eventMap[cb] = wrappedCallback; + return nativeAddEventListener.apply(this, [nativeEventName, + wrappedCallback]); + }; + + var nativeRemoveEventListener = proto.removeEventListener; + proto.removeEventListener = function(nativeEventName, cb) { + if (nativeEventName !== eventNameToWrap || !this._eventMap + || !this._eventMap[cb]) { + return nativeRemoveEventListener.apply(this, arguments); + } + var unwrappedCb = this._eventMap[cb]; + delete this._eventMap[cb]; + return nativeRemoveEventListener.apply(this, [nativeEventName, + unwrappedCb]); + }; + + Object.defineProperty(proto, 'on' + eventNameToWrap, { + get: function() { + return this['_on' + eventNameToWrap]; + }, + set: function(cb) { + if (this['_on' + eventNameToWrap]) { + this.removeEventListener(eventNameToWrap, + this['_on' + eventNameToWrap]); + delete this['_on' + eventNameToWrap]; + } + if (cb) { + this.addEventListener(eventNameToWrap, + this['_on' + eventNameToWrap] = cb); + } + } + }); +} + +// Utility methods. +module.exports = { + extractVersion: extractVersion, + wrapPeerConnectionEvent: wrapPeerConnectionEvent, + disableLog: function(bool) { + if (typeof bool !== 'boolean') { + return new Error('Argument type: ' + typeof bool + + '. Please use a boolean.'); + } + logDisabled_ = bool; + return (bool) ? 'adapter.js logging disabled' : + 'adapter.js logging enabled'; + }, + + /** + * Disable or enable deprecation warnings + * @param {!boolean} bool set to true to disable warnings. + */ + disableWarnings: function(bool) { + if (typeof bool !== 'boolean') { + return new Error('Argument type: ' + typeof bool + + '. Please use a boolean.'); + } + deprecationWarnings_ = !bool; + return 'adapter.js deprecation warnings ' + (bool ? 'disabled' : 'enabled'); + }, + + log: function() { + if (typeof window === 'object') { + if (logDisabled_) { + return; + } + if (typeof console !== 'undefined' && typeof console.log === 'function') { + console.log.apply(console, arguments); + } + } + }, + + /** + * Shows a deprecation warning suggesting the modern and spec-compatible API. + */ + deprecated: function(oldMethod, newMethod) { + if (!deprecationWarnings_) { + return; + } + console.warn(oldMethod + ' is deprecated, please use ' + newMethod + + ' instead.'); + }, + + /** + * Browser detector. + * + * @return {object} result containing browser and version + * properties. + */ + detectBrowser: function(window) { + var navigator = window && window.navigator; + + // Returned result object. + var result = {}; + result.browser = null; + result.version = null; + + // Fail early if it's not a browser + if (typeof window === 'undefined' || !window.navigator) { + result.browser = 'Not a browser.'; + return result; + } + + if (navigator.mozGetUserMedia) { // Firefox. + result.browser = 'firefox'; + result.version = extractVersion(navigator.userAgent, + /Firefox\/(\d+)\./, 1); + } else if (navigator.webkitGetUserMedia) { + // Chrome, Chromium, Webview, Opera. + // Version matches Chrome/WebRTC version. + result.browser = 'chrome'; + result.version = extractVersion(navigator.userAgent, + /Chrom(e|ium)\/(\d+)\./, 2); + } else if (navigator.mediaDevices && + navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)) { // Edge. + result.browser = 'edge'; + result.version = extractVersion(navigator.userAgent, + /Edge\/(\d+).(\d+)$/, 2); + } else if (navigator.mediaDevices && + navigator.userAgent.match(/AppleWebKit\/(\d+)\./)) { // Safari. + result.browser = 'safari'; + result.version = extractVersion(navigator.userAgent, + /AppleWebKit\/(\d+)\./, 1); + } else { // Default fallthrough: not supported. + result.browser = 'Not a supported browser.'; + return result; + } + + return result; + } +}; + +},{}],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); + 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.4 - git.io/ee + * Unlicense - http://unlicense.org/ + * Oliver Caldwell - http://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; + } +}(this || {})); + +},{}],39:[function(require,module,exports){ +(function (process,global){ +'use strict'; +// Last Updated On: 2017-12-09 2:29:22 PM UTC +// ________________ +// DetectRTC v1.3.6 +// Open-Sourced: https://github.com/muaz-khan/DetectRTC +// -------------------------------------------------- +// Muaz Khan - www.MuazKhan.com +// MIT License - www.WebRTC-Experiment.com/licence +// -------------------------------------------------- +(function () { + var browserFakeUserAgent = 'Fake/5.0 (FakeOS) AppleWebKit/123 (KHTML, like Gecko) Fake/12.3.4567.89 Fake/123.45'; + var isNodejs = typeof process === 'object' && typeof process.versions === 'object' && process.versions.node && /*node-process*/ !process.browser; + if (isNodejs) { + var version = process.versions.node.toString().replace('v', ''); + browserFakeUserAgent = 'Nodejs/' + version + ' (NodeOS) AppleWebKit/' + version + ' (KHTML, like Gecko) Nodejs/' + version + ' Nodejs/' + version; + } + (function (that) { + if (typeof window !== 'undefined') { + return; + } + if (typeof window === 'undefined' && typeof global !== 'undefined') { + global.navigator = { + userAgent: browserFakeUserAgent, + getUserMedia: function () { } + }; + /*global window:true */ + that.window = global; + } + else if (typeof window === 'undefined') { + // window = this; + } + if (typeof location === 'undefined') { + /*global location:true */ + that.location = { + protocol: 'file:', + href: '', + hash: '' + }; + } + if (typeof screen === 'undefined') { + /*global screen:true */ + that.screen = { + width: 0, + height: 0 + }; + } + })(typeof global !== 'undefined' ? global : window); + /*global navigator:true */ + var navigator = window.navigator; + if (typeof navigator !== 'undefined') { + if (typeof navigator.webkitGetUserMedia !== 'undefined') { + navigator.getUserMedia = navigator.webkitGetUserMedia; + } + if (typeof navigator.mozGetUserMedia !== 'undefined') { + navigator.getUserMedia = navigator.mozGetUserMedia; + } + } + else { + navigator = { + getUserMedia: function () { }, + userAgent: browserFakeUserAgent + }; + } + var isMobileDevice = !!(/Android|webOS|iPhone|iPad|iPod|BB10|BlackBerry|IEMobile|Opera Mini|Mobile|mobile/i.test(navigator.userAgent || '')); + var isEdge = navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob); + var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; + var isFirefox = typeof window.InstallTrigger !== 'undefined'; + var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); + var isChrome = !!window.chrome && !isOpera; + var isIE = typeof document !== 'undefined' && !!document.documentMode && !isEdge; + // this one can also be used: + // https://www.websocket.org/js/stuff.js (DetectBrowser.js) + function getBrowserInfo() { + var nVer = navigator.appVersion; + var nAgt = navigator.userAgent; + var browserName = navigator.appName; + var fullVersion = '' + parseFloat(navigator.appVersion); + var majorVersion = parseInt(navigator.appVersion, 10); + var nameOffset, verOffset, ix; + // In Opera, the true version is after 'Opera' or after 'Version' + if (isOpera) { + browserName = 'Opera'; + try { + fullVersion = navigator.userAgent.split('OPR/')[1].split(' ')[0]; + majorVersion = fullVersion.split('.')[0]; + } + catch (e) { + fullVersion = '0.0.0.0'; + majorVersion = 0; + } + } + else if (isIE) { + verOffset = nAgt.indexOf('rv:'); + if (verOffset > 0) { + fullVersion = nAgt.substring(verOffset + 3); + } + else { + verOffset = nAgt.indexOf('MSIE'); + fullVersion = nAgt.substring(verOffset + 5); + } + browserName = 'IE'; + } + else if (isChrome) { + verOffset = nAgt.indexOf('Chrome'); + browserName = 'Chrome'; + fullVersion = nAgt.substring(verOffset + 7); + } + else if (isSafari) { + verOffset = nAgt.indexOf('Safari'); + browserName = 'Safari'; + fullVersion = nAgt.substring(verOffset + 7); + if ((verOffset = nAgt.indexOf('Version')) !== -1) { + fullVersion = nAgt.substring(verOffset + 8); + } + if (navigator.userAgent.indexOf('Version/') !== -1) { + fullVersion = navigator.userAgent.split('Version/')[1].split(' ')[0]; + } + } + else if (isFirefox) { + verOffset = nAgt.indexOf('Firefox'); + browserName = 'Firefox'; + fullVersion = nAgt.substring(verOffset + 8); + } + else if ((nameOffset = nAgt.lastIndexOf(' ') + 1) < (verOffset = nAgt.lastIndexOf('/'))) { + browserName = nAgt.substring(nameOffset, verOffset); + fullVersion = nAgt.substring(verOffset + 1); + if (browserName.toLowerCase() === browserName.toUpperCase()) { + browserName = navigator.appName; + } + } + if (isEdge) { + browserName = 'Edge'; + fullVersion = navigator.userAgent.split('Edge/')[1]; + // fullVersion = parseInt(navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)[2], 10).toString(); + } + // trim the fullVersion string at semicolon/space/bracket if present + if ((ix = fullVersion.search(/[; \)]/)) !== -1) { + fullVersion = fullVersion.substring(0, ix); + } + majorVersion = parseInt('' + fullVersion, 10); + if (isNaN(majorVersion)) { + fullVersion = '' + parseFloat(navigator.appVersion); + majorVersion = parseInt(navigator.appVersion, 10); + } + return { + fullVersion: fullVersion, + version: majorVersion, + name: browserName, + isPrivateBrowsing: false + }; + } + // via: https://gist.github.com/cou929/7973956 + function retry(isDone, next) { + var currentTrial = 0, maxRetry = 50, interval = 10, isTimeout = false; + var id = window.setInterval(function () { + if (isDone()) { + window.clearInterval(id); + next(isTimeout); + } + if (currentTrial++ > maxRetry) { + window.clearInterval(id); + isTimeout = true; + next(isTimeout); + } + }, 10); + } + function isIE10OrLater(userAgent) { + var ua = userAgent.toLowerCase(); + if (ua.indexOf('msie') === 0 && ua.indexOf('trident') === 0) { + return false; + } + var match = /(?:msie|rv:)\s?([\d\.]+)/.exec(ua); + if (match && parseInt(match[1], 10) >= 10) { + return true; + } + return false; + } + function detectPrivateMode(callback) { + var isPrivate; + try { + if (window.webkitRequestFileSystem) { + window.webkitRequestFileSystem(window.TEMPORARY, 1, function () { + isPrivate = false; + }, function (e) { + isPrivate = true; + }); + } + else if (window.indexedDB && /Firefox/.test(window.navigator.userAgent)) { + var db; + try { + db = window.indexedDB.open('test'); + db.onerror = function () { + return true; + }; + } + catch (e) { + isPrivate = true; + } + if (typeof isPrivate === 'undefined') { + retry(function isDone() { + return db.readyState === 'done' ? true : false; + }, function next(isTimeout) { + if (!isTimeout) { + isPrivate = db.result ? false : true; + } + }); + } + } + else if (isIE10OrLater(window.navigator.userAgent)) { + isPrivate = false; + try { + if (!window.indexedDB) { + isPrivate = true; + } + } + catch (e) { + isPrivate = true; + } + } + else if (window.localStorage && /Safari/.test(window.navigator.userAgent)) { + try { + window.localStorage.setItem('test', 1); + } + catch (e) { + isPrivate = true; + } + if (typeof isPrivate === 'undefined') { + isPrivate = false; + window.localStorage.removeItem('test'); + } + } + } + catch (e) { + isPrivate = false; + } + retry(function isDone() { + return typeof isPrivate !== 'undefined' ? true : false; + }, function next(isTimeout) { + callback(isPrivate); + }); + } + var isMobile = { + Android: function () { + return navigator.userAgent.match(/Android/i); + }, + BlackBerry: function () { + return navigator.userAgent.match(/BlackBerry|BB10/i); + }, + iOS: function () { + return navigator.userAgent.match(/iPhone|iPad|iPod/i); + }, + Opera: function () { + return navigator.userAgent.match(/Opera Mini/i); + }, + Windows: function () { + return navigator.userAgent.match(/IEMobile/i); + }, + any: function () { + return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows()); + }, + getOsName: function () { + var osName = 'Unknown OS'; + if (isMobile.Android()) { + osName = 'Android'; + } + if (isMobile.BlackBerry()) { + osName = 'BlackBerry'; + } + if (isMobile.iOS()) { + osName = 'iOS'; + } + if (isMobile.Opera()) { + osName = 'Opera Mini'; + } + if (isMobile.Windows()) { + osName = 'Windows'; + } + return osName; + } + }; + // via: http://jsfiddle.net/ChristianL/AVyND/ + function detectDesktopOS() { + var unknown = '-'; + var nVer = navigator.appVersion; + var nAgt = navigator.userAgent; + var os = unknown; + var clientStrings = [{ + s: 'Windows 10', + r: /(Windows 10.0|Windows NT 10.0)/ + }, { + s: 'Windows 8.1', + r: /(Windows 8.1|Windows NT 6.3)/ + }, { + s: 'Windows 8', + r: /(Windows 8|Windows NT 6.2)/ + }, { + s: 'Windows 7', + r: /(Windows 7|Windows NT 6.1)/ + }, { + s: 'Windows Vista', + r: /Windows NT 6.0/ + }, { + s: 'Windows Server 2003', + r: /Windows NT 5.2/ + }, { + s: 'Windows XP', + r: /(Windows NT 5.1|Windows XP)/ + }, { + s: 'Windows 2000', + r: /(Windows NT 5.0|Windows 2000)/ + }, { + s: 'Windows ME', + r: /(Win 9x 4.90|Windows ME)/ + }, { + s: 'Windows 98', + r: /(Windows 98|Win98)/ + }, { + s: 'Windows 95', + r: /(Windows 95|Win95|Windows_95)/ + }, { + s: 'Windows NT 4.0', + r: /(Windows NT 4.0|WinNT4.0|WinNT|Windows NT)/ + }, { + s: 'Windows CE', + r: /Windows CE/ + }, { + s: 'Windows 3.11', + r: /Win16/ + }, { + s: 'Android', + r: /Android/ + }, { + s: 'Open BSD', + r: /OpenBSD/ + }, { + s: 'Sun OS', + r: /SunOS/ + }, { + s: 'Linux', + r: /(Linux|X11)/ + }, { + s: 'iOS', + r: /(iPhone|iPad|iPod)/ + }, { + s: 'Mac OS X', + r: /Mac OS X/ + }, { + s: 'Mac OS', + r: /(MacPPC|MacIntel|Mac_PowerPC|Macintosh)/ + }, { + s: 'QNX', + r: /QNX/ + }, { + s: 'UNIX', + r: /UNIX/ + }, { + s: 'BeOS', + r: /BeOS/ + }, { + s: 'OS/2', + r: /OS\/2/ + }, { + s: 'Search Bot', + r: /(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/ + }]; + for (var i = 0, cs; cs = clientStrings[i]; i++) { + if (cs.r.test(nAgt)) { + os = cs.s; + break; + } + } + var osVersion = unknown; + if (/Windows/.test(os)) { + if (/Windows (.*)/.test(os)) { + osVersion = /Windows (.*)/.exec(os)[1]; + } + os = 'Windows'; + } + switch (os) { + case 'Mac OS X': + if (/Mac OS X (10[\.\_\d]+)/.test(nAgt)) { + osVersion = /Mac OS X (10[\.\_\d]+)/.exec(nAgt)[1]; + } + break; + case 'Android': + if (/Android ([\.\_\d]+)/.test(nAgt)) { + osVersion = /Android ([\.\_\d]+)/.exec(nAgt)[1]; + } + break; + case 'iOS': + if (/OS (\d+)_(\d+)_?(\d+)?/.test(nAgt)) { + osVersion = /OS (\d+)_(\d+)_?(\d+)?/.exec(nVer); + osVersion = osVersion[1] + '.' + osVersion[2] + '.' + (osVersion[3] | 0); + } + break; + } + return { + osName: os, + osVersion: osVersion + }; + } + var osName = 'Unknown OS'; + var osVersion = 'Unknown OS Version'; + function getAndroidVersion(ua) { + ua = (ua || navigator.userAgent).toLowerCase(); + var match = ua.match(/android\s([0-9\.]*)/); + return match ? match[1] : false; + } + var osInfo = detectDesktopOS(); + if (osInfo && osInfo.osName && osInfo.osName != '-') { + osName = osInfo.osName; + osVersion = osInfo.osVersion; + } + else if (isMobile.any()) { + osName = isMobile.getOsName(); + if (osName == 'Android') { + osVersion = getAndroidVersion(); + } + } + var isNodejs = typeof process === 'object' && typeof process.versions === 'object' && process.versions.node; + if (osName === 'Unknown OS' && isNodejs) { + osName = 'Nodejs'; + osVersion = process.versions.node.toString().replace('v', ''); + } + var isCanvasSupportsStreamCapturing = false; + var isVideoSupportsStreamCapturing = false; + ['captureStream', 'mozCaptureStream', 'webkitCaptureStream'].forEach(function (item) { + if (typeof document === 'undefined' || typeof document.createElement !== 'function') { + return; + } + if (!isCanvasSupportsStreamCapturing && item in document.createElement('canvas')) { + isCanvasSupportsStreamCapturing = true; + } + if (!isVideoSupportsStreamCapturing && item in document.createElement('video')) { + isVideoSupportsStreamCapturing = true; + } + }); + // via: https://github.com/diafygi/webrtc-ips + function DetectLocalIPAddress(callback, stream) { + if (!DetectRTC.isWebRTCSupported) { + return; + } + getIPs(function (ip) { + if (ip.match(/^(192\.168\.|169\.254\.|10\.|172\.(1[6-9]|2\d|3[01]))/)) { + callback('Local: ' + ip); + } + else { + callback('Public: ' + ip); + } + }, stream); + } + function getIPs(callback, stream) { + if (typeof document === 'undefined' || typeof document.getElementById !== 'function') { + return; + } + var ipDuplicates = {}; + var RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; + if (!RTCPeerConnection) { + var iframe = document.getElementById('iframe'); + if (!iframe) { + return; + } + var win = iframe.contentWindow; + RTCPeerConnection = win.RTCPeerConnection || win.mozRTCPeerConnection || win.webkitRTCPeerConnection; + } + if (!RTCPeerConnection) { + return; + } + var peerConfig = null; + if (DetectRTC.browser === 'Chrome' && DetectRTC.browser.version < 58) { + // todo: add support for older Opera + peerConfig = { + optional: [{ + RtpDataChannels: true + }] + }; + } + var servers = { + iceServers: [{ + urls: 'stun:stun.l.google.com:19302' + }] + }; + var pc = new RTCPeerConnection(servers, peerConfig); + if (stream) { + if (pc.addStream) { + pc.addStream(stream); + } + else if (pc.addTrack && stream.getTracks()[0]) { + pc.addTrack(stream.getTracks()[0], stream); + } + } + function handleCandidate(candidate) { + var ipRegex = /([0-9]{1,3}(\.[0-9]{1,3}){3})/; + var match = ipRegex.exec(candidate); + if (!match) { + return; + } + var ipAddress = match[1]; + if (ipDuplicates[ipAddress] === undefined) { + callback(ipAddress); + } + ipDuplicates[ipAddress] = true; + } + // listen for candidate events + pc.onicecandidate = function (ice) { + if (ice.candidate) { + handleCandidate(ice.candidate.candidate); + } + }; + // create data channel + if (!stream) { + try { + pc.createDataChannel('sctp', {}); + } + catch (e) { } + } + // create an offer sdp + if (DetectRTC.isPromisesSupported) { + pc.createOffer().then(function (result) { + pc.setLocalDescription(result).then(afterCreateOffer); + }); + } + else { + pc.createOffer(function (result) { + pc.setLocalDescription(result, afterCreateOffer, function () { }); + }, function () { }); + } + function afterCreateOffer() { + var lines = pc.localDescription.sdp.split('\n'); + lines.forEach(function (line) { + if (line.indexOf('a=candidate:') === 0) { + handleCandidate(line); + } + }); + } + } + var MediaDevices = []; + var audioInputDevices = []; + var audioOutputDevices = []; + var videoInputDevices = []; + if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) { + // Firefox 38+ seems having support of enumerateDevices + // Thanks @xdumaine/enumerateDevices + navigator.enumerateDevices = function (callback) { + var enumerateDevices = navigator.mediaDevices.enumerateDevices(); + if (enumerateDevices && enumerateDevices.then) { + navigator.mediaDevices.enumerateDevices().then(callback).catch(function () { + callback([]); + }); + } + else { + callback([]); + } + }; + } + // Media Devices detection + var canEnumerate = false; + /*global MediaStreamTrack:true */ + if (typeof MediaStreamTrack !== 'undefined' && 'getSources' in MediaStreamTrack) { + canEnumerate = true; + } + else if (navigator.mediaDevices && !!navigator.mediaDevices.enumerateDevices) { + canEnumerate = true; + } + var hasMicrophone = false; + var hasSpeakers = false; + var hasWebcam = false; + var isWebsiteHasMicrophonePermissions = false; + var isWebsiteHasWebcamPermissions = false; + // http://dev.w3.org/2011/webrtc/editor/getusermedia.html#mediadevices + function checkDeviceSupport(callback) { + if (!canEnumerate) { + if (callback) { + callback(); + } + return; + } + if (!navigator.enumerateDevices && window.MediaStreamTrack && window.MediaStreamTrack.getSources) { + navigator.enumerateDevices = window.MediaStreamTrack.getSources.bind(window.MediaStreamTrack); + } + if (!navigator.enumerateDevices && navigator.enumerateDevices) { + navigator.enumerateDevices = navigator.enumerateDevices.bind(navigator); + } + if (!navigator.enumerateDevices) { + if (callback) { + callback(); + } + return; + } + MediaDevices = []; + audioInputDevices = []; + audioOutputDevices = []; + videoInputDevices = []; + hasMicrophone = false; + hasSpeakers = false; + hasWebcam = false; + isWebsiteHasMicrophonePermissions = false; + isWebsiteHasWebcamPermissions = false; + // to prevent duplication + var alreadyUsedDevices = {}; + navigator.enumerateDevices(function (devices) { + devices.forEach(function (_device) { + var device = {}; + for (var d in _device) { + try { + if (typeof _device[d] !== 'function') { + device[d] = _device[d]; + } + } + catch (e) { } + } + if (alreadyUsedDevices[device.deviceId + device.label + device.kind]) { + return; + } + // if it is MediaStreamTrack.getSources + if (device.kind === 'audio') { + device.kind = 'audioinput'; + } + if (device.kind === 'video') { + device.kind = 'videoinput'; + } + if (!device.deviceId) { + device.deviceId = device.id; + } + if (!device.id) { + device.id = device.deviceId; + } + if (!device.label) { + device.isCustomLabel = true; + if (device.kind === 'videoinput') { + device.label = 'Camera ' + (videoInputDevices.length + 1); + } + else if (device.kind === 'audioinput') { + device.label = 'Microphone ' + (audioInputDevices.length + 1); + } + else if (device.kind === 'audiooutput') { + device.label = 'Speaker ' + (audioOutputDevices.length + 1); + } + else { + device.label = 'Please invoke getUserMedia once.'; + } + if (typeof DetectRTC !== 'undefined' && DetectRTC.browser.isChrome && DetectRTC.browser.version >= 46 && !/^(https:|chrome-extension:)$/g.test(location.protocol || '')) { + if (typeof document !== 'undefined' && typeof document.domain === 'string' && document.domain.search && document.domain.search(/localhost|127.0./g) === -1) { + device.label = 'HTTPs is required to get label of this ' + device.kind + ' device.'; + } + } + } + else { + // Firefox on Android still returns empty label + if (device.kind === 'videoinput' && !isWebsiteHasWebcamPermissions) { + isWebsiteHasWebcamPermissions = true; + } + if (device.kind === 'audioinput' && !isWebsiteHasMicrophonePermissions) { + isWebsiteHasMicrophonePermissions = true; + } + } + if (device.kind === 'audioinput') { + hasMicrophone = true; + if (audioInputDevices.indexOf(device) === -1) { + audioInputDevices.push(device); + } + } + if (device.kind === 'audiooutput') { + hasSpeakers = true; + if (audioOutputDevices.indexOf(device) === -1) { + audioOutputDevices.push(device); + } + } + if (device.kind === 'videoinput') { + hasWebcam = true; + if (videoInputDevices.indexOf(device) === -1) { + videoInputDevices.push(device); + } + } + // there is no 'videoouput' in the spec. + MediaDevices.push(device); + alreadyUsedDevices[device.deviceId + device.label + device.kind] = device; + }); + if (typeof DetectRTC !== 'undefined') { + // to sync latest outputs + DetectRTC.MediaDevices = MediaDevices; + DetectRTC.hasMicrophone = hasMicrophone; + DetectRTC.hasSpeakers = hasSpeakers; + DetectRTC.hasWebcam = hasWebcam; + DetectRTC.isWebsiteHasWebcamPermissions = isWebsiteHasWebcamPermissions; + DetectRTC.isWebsiteHasMicrophonePermissions = isWebsiteHasMicrophonePermissions; + DetectRTC.audioInputDevices = audioInputDevices; + DetectRTC.audioOutputDevices = audioOutputDevices; + DetectRTC.videoInputDevices = videoInputDevices; + } + if (callback) { + callback(); + } + }); + } + var DetectRTC = window.DetectRTC || {}; + // ---------- + // DetectRTC.browser.name || DetectRTC.browser.version || DetectRTC.browser.fullVersion + DetectRTC.browser = getBrowserInfo(); + detectPrivateMode(function (isPrivateBrowsing) { + DetectRTC.browser.isPrivateBrowsing = !!isPrivateBrowsing; + }); + // DetectRTC.isChrome || DetectRTC.isFirefox || DetectRTC.isEdge + DetectRTC.browser['is' + DetectRTC.browser.name] = true; + // ----------- + DetectRTC.osName = osName; + DetectRTC.osVersion = osVersion; + var isNodeWebkit = typeof process === 'object' && typeof process.versions === 'object' && process.versions['node-webkit']; + // --------- Detect if system supports WebRTC 1.0 or WebRTC 1.1. + var isWebRTCSupported = false; + ['RTCPeerConnection', 'webkitRTCPeerConnection', 'mozRTCPeerConnection', 'RTCIceGatherer'].forEach(function (item) { + if (isWebRTCSupported) { + return; + } + if (item in window) { + isWebRTCSupported = true; + } + }); + DetectRTC.isWebRTCSupported = isWebRTCSupported; + //------- + DetectRTC.isORTCSupported = typeof RTCIceGatherer !== 'undefined'; + // --------- Detect if WebAudio API are supported + var webAudio = { + isSupported: false, + isCreateMediaStreamSourceSupported: false + }; + ['AudioContext', 'webkitAudioContext', 'mozAudioContext', 'msAudioContext'].forEach(function (item) { + if (webAudio.isSupported) { + return; + } + if (item in window) { + webAudio.isSupported = true; + if (window[item] && 'createMediaStreamSource' in window[item].prototype) { + webAudio.isCreateMediaStreamSourceSupported = true; + } + } + }); + DetectRTC.isAudioContextSupported = webAudio.isSupported; + DetectRTC.isCreateMediaStreamSourceSupported = webAudio.isCreateMediaStreamSourceSupported; + // ---------- Detect if SCTP/RTP channels are supported. + var isRtpDataChannelsSupported = false; + if (DetectRTC.browser.isChrome && DetectRTC.browser.version > 31) { + isRtpDataChannelsSupported = true; + } + DetectRTC.isRtpDataChannelsSupported = isRtpDataChannelsSupported; + var isSCTPSupportd = false; + if (DetectRTC.browser.isFirefox && DetectRTC.browser.version > 28) { + isSCTPSupportd = true; + } + else if (DetectRTC.browser.isChrome && DetectRTC.browser.version > 25) { + isSCTPSupportd = true; + } + else if (DetectRTC.browser.isOpera && DetectRTC.browser.version >= 11) { + isSCTPSupportd = true; + } + DetectRTC.isSctpDataChannelsSupported = isSCTPSupportd; + // --------- + DetectRTC.isMobileDevice = isMobileDevice; // "isMobileDevice" boolean is defined in "getBrowserInfo.js" + // ------ + var isGetUserMediaSupported = false; + if (navigator.getUserMedia) { + isGetUserMediaSupported = true; + } + else if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { + isGetUserMediaSupported = true; + } + if (DetectRTC.browser.isChrome && DetectRTC.browser.version >= 46 && !/^(https:|chrome-extension:)$/g.test(location.protocol || '')) { + if (typeof document !== 'undefined' && typeof document.domain === 'string' && document.domain.search && document.domain.search(/localhost|127.0./g) === -1) { + isGetUserMediaSupported = 'Requires HTTPs'; + } + } + if (DetectRTC.osName === 'Nodejs') { + isGetUserMediaSupported = false; + } + DetectRTC.isGetUserMediaSupported = isGetUserMediaSupported; + var displayResolution = ''; + if (screen.width) { + var width = (screen.width) ? screen.width : ''; + var height = (screen.height) ? screen.height : ''; + displayResolution += '' + width + ' x ' + height; + } + DetectRTC.displayResolution = displayResolution; + function getAspectRatio(w, h) { + function gcd(a, b) { + return (b == 0) ? a : gcd(b, a % b); + } + var r = gcd(w, h); + return (w / r) / (h / r); + } + DetectRTC.displayAspectRatio = getAspectRatio(screen.width, screen.height).toFixed(2); + // ---------- + DetectRTC.isCanvasSupportsStreamCapturing = isCanvasSupportsStreamCapturing; + DetectRTC.isVideoSupportsStreamCapturing = isVideoSupportsStreamCapturing; + if (DetectRTC.browser.name == 'Chrome' && DetectRTC.browser.version >= 53) { + if (!DetectRTC.isCanvasSupportsStreamCapturing) { + DetectRTC.isCanvasSupportsStreamCapturing = 'Requires chrome flag: enable-experimental-web-platform-features'; + } + if (!DetectRTC.isVideoSupportsStreamCapturing) { + DetectRTC.isVideoSupportsStreamCapturing = 'Requires chrome flag: enable-experimental-web-platform-features'; + } + } + // ------ + DetectRTC.DetectLocalIPAddress = DetectLocalIPAddress; + DetectRTC.isWebSocketsSupported = 'WebSocket' in window && 2 === window.WebSocket.CLOSING; + DetectRTC.isWebSocketsBlocked = !DetectRTC.isWebSocketsSupported; + if (DetectRTC.osName === 'Nodejs') { + DetectRTC.isWebSocketsSupported = true; + DetectRTC.isWebSocketsBlocked = false; + } + DetectRTC.checkWebSocketsSupport = function (callback) { + callback = callback || function () { }; + try { + var starttime; + var websocket = new WebSocket('wss://echo.websocket.org:443/'); + websocket.onopen = function () { + DetectRTC.isWebSocketsBlocked = false; + starttime = (new Date).getTime(); + websocket.send('ping'); + }; + websocket.onmessage = function () { + DetectRTC.WebsocketLatency = (new Date).getTime() - starttime + 'ms'; + callback(); + websocket.close(); + websocket = null; + }; + websocket.onerror = function () { + DetectRTC.isWebSocketsBlocked = true; + callback(); + }; + } + catch (e) { + DetectRTC.isWebSocketsBlocked = true; + callback(); + } + }; + // ------- + DetectRTC.load = function (callback) { + callback = callback || function () { }; + checkDeviceSupport(callback); + }; + // check for microphone/camera support! + if (typeof checkDeviceSupport === 'function') { + // checkDeviceSupport(); + } + if (typeof MediaDevices !== 'undefined') { + DetectRTC.MediaDevices = MediaDevices; + } + else { + DetectRTC.MediaDevices = []; + } + DetectRTC.hasMicrophone = hasMicrophone; + DetectRTC.hasSpeakers = hasSpeakers; + DetectRTC.hasWebcam = hasWebcam; + DetectRTC.isWebsiteHasWebcamPermissions = isWebsiteHasWebcamPermissions; + DetectRTC.isWebsiteHasMicrophonePermissions = isWebsiteHasMicrophonePermissions; + DetectRTC.audioInputDevices = audioInputDevices; + DetectRTC.audioOutputDevices = audioOutputDevices; + DetectRTC.videoInputDevices = videoInputDevices; + // ------ + var isSetSinkIdSupported = false; + if (typeof document !== 'undefined' && typeof document.createElement === 'function' && 'setSinkId' in document.createElement('video')) { + isSetSinkIdSupported = true; + } + DetectRTC.isSetSinkIdSupported = isSetSinkIdSupported; + // ----- + var isRTPSenderReplaceTracksSupported = false; + if (DetectRTC.browser.isFirefox && typeof mozRTCPeerConnection !== 'undefined' /*&& DetectRTC.browser.version > 39*/) { + /*global mozRTCPeerConnection:true */ + if ('getSenders' in mozRTCPeerConnection.prototype) { + isRTPSenderReplaceTracksSupported = true; + } + } + else if (DetectRTC.browser.isChrome && typeof webkitRTCPeerConnection !== 'undefined') { + /*global webkitRTCPeerConnection:true */ + if ('getSenders' in webkitRTCPeerConnection.prototype) { + isRTPSenderReplaceTracksSupported = true; + } + } + DetectRTC.isRTPSenderReplaceTracksSupported = isRTPSenderReplaceTracksSupported; + //------ + var isRemoteStreamProcessingSupported = false; + if (DetectRTC.browser.isFirefox && DetectRTC.browser.version > 38) { + isRemoteStreamProcessingSupported = true; + } + DetectRTC.isRemoteStreamProcessingSupported = isRemoteStreamProcessingSupported; + //------- + var isApplyConstraintsSupported = false; + /*global MediaStreamTrack:true */ + if (typeof MediaStreamTrack !== 'undefined' && 'applyConstraints' in MediaStreamTrack.prototype) { + isApplyConstraintsSupported = true; + } + DetectRTC.isApplyConstraintsSupported = isApplyConstraintsSupported; + //------- + var isMultiMonitorScreenCapturingSupported = false; + if (DetectRTC.browser.isFirefox && DetectRTC.browser.version >= 43) { + // version 43 merely supports platforms for multi-monitors + // version 44 will support exact multi-monitor selection i.e. you can select any monitor for screen capturing. + isMultiMonitorScreenCapturingSupported = true; + } + DetectRTC.isMultiMonitorScreenCapturingSupported = isMultiMonitorScreenCapturingSupported; + DetectRTC.isPromisesSupported = !!('Promise' in window); + if (typeof DetectRTC === 'undefined') { + window.DetectRTC = {}; + } + var MediaStream = window.MediaStream; + if (typeof MediaStream === 'undefined' && typeof webkitMediaStream !== 'undefined') { + MediaStream = webkitMediaStream; + } + if (typeof MediaStream !== 'undefined') { + DetectRTC.MediaStream = Object.keys(MediaStream.prototype); + } + else + DetectRTC.MediaStream = false; + if (typeof MediaStreamTrack !== 'undefined') { + DetectRTC.MediaStreamTrack = Object.keys(MediaStreamTrack.prototype); + } + else + DetectRTC.MediaStreamTrack = false; + var RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; + if (typeof RTCPeerConnection !== 'undefined') { + DetectRTC.RTCPeerConnection = Object.keys(RTCPeerConnection.prototype); + } + else + DetectRTC.RTCPeerConnection = false; + window.DetectRTC = DetectRTC; + if (typeof module !== 'undefined' /* && !!module.exports*/) { + module.exports = DetectRTC; + } + if (typeof define === 'function' && define.amd) { + define('DetectRTC', [], function () { + return DetectRTC; + }); + } +})(); + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"_process":9}],40:[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]; + // Check it's empty + 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; + +},{}],41:[function(require,module,exports){ +/* + * (C) Copyright 2014 Kurento (http://kurento.org/) + * + * 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. + * + */ +var JsonRpcClient = require('./jsonrpcclient'); +exports.JsonRpcClient = JsonRpcClient; + +},{"./jsonrpcclient":42}],42:[function(require,module,exports){ +/* + * (C) Copyright 2014 Kurento (http://kurento.org/) + * + * 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. + * + */ +var RpcBuilder = require('../'); +var WebSocketWithReconnection = require('./transports/webSocketWithReconnection'); +Date.now = Date.now || function () { + return +new Date; +}; +var PING_INTERVAL = 5000; +var RECONNECTING = 'RECONNECTING'; +var CONNECTED = 'CONNECTED'; +var DISCONNECTED = 'DISCONNECTED'; +var Logger = console; +/** + * + * heartbeat: interval in ms for each heartbeat message, + * sendCloseMessage : true / false, before closing the connection, it sends a closeSession message + *
+ * ws : {
+ * 	uri : URI to conntect to,
+ *  useSockJS : true (use SockJS) / false (use WebSocket) by default,
+ * 	onconnected : callback method to invoke when connection is successful,
+ * 	ondisconnect : callback method to invoke when the connection is lost,
+ * 	onreconnecting : callback method to invoke when the client is reconnecting,
+ * 	onreconnected : callback method to invoke when the client succesfully reconnects,
+ * 	onerror : callback method to invoke when there is an error
+ * },
+ * rpc : {
+ * 	requestTimeout : timeout for a request,
+ * 	sessionStatusChanged: callback method for changes in session status,
+ * 	mediaRenegotiation: mediaRenegotiation
+ * }
+ * 
+ */ +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; + } + 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; + enabledPings = true; + updateNotReconnectIfLessThan(); + usePing(); + 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; + 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) { + if (method !== 'ping') { + Logger.debug('Request: method:' + method + " params:" + JSON.stringify(params)); + } + 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"); + } + } + /* + * If configuration.hearbeat has any value, the ping-pong will work with the interval + * of configuration.hearbeat + */ + function usePing() { + if (!pingPongStarted) { + Logger.debug("Starting ping (if configured)"); + pingPongStarted = true; + if (configuration.heartbeat != undefined) { + pingInterval = setInterval(sendPing, configuration.heartbeat); + sendPing(); + } + } + } + this.close = function () { + Logger.debug("Closing jsonRpcClient explicitly by client"); + if (pingInterval != undefined) { + Logger.debug("Clearing ping interval"); + clearInterval(pingInterval); + } + pingPongStarted = false; + enabledPings = false; + if (configuration.sendCloseMessage) { + Logger.debug("Sending close message"); + this.send('closeSession', null, function (error, result) { + if (error) { + Logger.error("Error sending close message: " + JSON.stringify(error)); + } + ws.close(); + }); + } + else { + ws.close(); + } + }; + // This method is only for testing + this.forceClose = function (millis) { + ws.forceClose(millis); + }; + this.reconnect = function () { + ws.reconnectWs(); + }; +} +module.exports = JsonRpcClient; + +},{"../":45,"./transports/webSocketWithReconnection":44}],43:[function(require,module,exports){ +/* + * (C) Copyright 2014 Kurento (http://kurento.org/) + * + * 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. + * + */ +var WebSocketWithReconnection = require('./webSocketWithReconnection'); +exports.WebSocketWithReconnection = WebSocketWithReconnection; + +},{"./webSocketWithReconnection":44}],44:[function(require,module,exports){ +(function (global){ +/* + * (C) Copyright 2013-2015 Kurento (http://kurento.org/) + * + * 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. + */ +"use strict"; +var BrowserWebSocket = global.WebSocket || global.MozWebSocket; +var Logger = console; +/** + * Get either the `WebSocket` or `MozWebSocket` globals + * in the browser or try to resolve WebSocket-compatible + * interface exposed by `ws` for Node-like environment. + */ +/*var WebSocket = BrowserWebSocket; +if (!WebSocket && typeof window === 'undefined') { + try { + WebSocket = require('ws'); + } catch (e) { } +}*/ +//var SockJS = require('sockjs-client'); +var MAX_RETRIES = 2000; // Forever... +var RETRY_TIME_MS = 3000; // FIXME: Implement exponential wait times... +var CONNECTING = 0; +var OPEN = 1; +var CLOSING = 2; +var CLOSED = 3; +/* +config = { + uri : wsUri, + useSockJS : true (use SockJS) / false (use WebSocket) by default, + onconnected : callback method to invoke when connection is successful, + ondisconnect : callback method to invoke when the connection is lost, + onreconnecting : callback method to invoke when the client is reconnecting, + onreconnected : callback method to invoke when the client succesfully reconnects, + }; +*/ +function WebSocketWithReconnection(config) { + var closing = false; + var registerMessageHandler; + var wsUri = config.uri; + var useSockJS = config.useSockJS; + var reconnecting = false; + var forcingDisconnection = false; + var ws; + if (useSockJS) { + ws = new SockJS(wsUri); + } + else { + ws = new WebSocket(wsUri); + } + ws.onopen = function () { + logConnected(ws, 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); + } + }; + function logConnected(ws, wsUri) { + try { + Logger.debug("WebSocket connected to " + wsUri); + } + catch (e) { + Logger.error(e); + } + } + var reconnectionOnClose = function () { + if (ws.readyState === CLOSED) { + if (closing) { + Logger.debug("Connection closed by user"); + } + else { + Logger.debug("Connection closed unexpectecly. Reconnecting..."); + reconnectToSameUri(MAX_RETRIES, 1); + } + } + else { + Logger.debug("Close callback from previous websocket. Ignoring it"); + } + }; + ws.onclose = reconnectionOnClose; + function reconnectToSameUri(maxRetries, numRetries) { + Logger.debug("reconnectToSameUri (attempt #" + numRetries + ", max=" + maxRetries + ")"); + if (numRetries === 1) { + if (reconnecting) { + Logger.warn("Trying to reconnectToNewUri when reconnecting... Ignoring this reconnection."); + return; + } + else { + reconnecting = true; + } + if (config.onreconnecting) { + config.onreconnecting(); + } + } + if (forcingDisconnection) { + reconnectToNewUri(maxRetries, numRetries, wsUri); + } + else { + if (config.newWsUriOnReconnection) { + config.newWsUriOnReconnection(function (error, newWsUri) { + if (error) { + Logger.debug(error); + setTimeout(function () { + reconnectToSameUri(maxRetries, numRetries + 1); + }, RETRY_TIME_MS); + } + else { + reconnectToNewUri(maxRetries, numRetries, newWsUri); + } + }); + } + else { + reconnectToNewUri(maxRetries, numRetries, wsUri); + } + } + } + // TODO Test retries. How to force not connection? + function reconnectToNewUri(maxRetries, numRetries, reconnectWsUri) { + Logger.debug("Reconnection attempt #" + numRetries); + ws.close(); + wsUri = reconnectWsUri || wsUri; + var newWs; + if (useSockJS) { + newWs = new SockJS(wsUri); + } + else { + newWs = new WebSocket(wsUri); + } + newWs.onopen = function () { + Logger.debug("Reconnected after " + numRetries + " attempts..."); + logConnected(newWs, wsUri); + reconnecting = false; + registerMessageHandler(); + if (config.onreconnected()) { + config.onreconnected(); + } + newWs.onclose = reconnectionOnClose; + }; + var onErrorOrClose = function (error) { + Logger.warn("Reconnection error: ", error); + if (numRetries === maxRetries) { + if (config.ondisconnect) { + config.ondisconnect(); + } + } + else { + setTimeout(function () { + reconnectToSameUri(maxRetries, numRetries + 1); + }, RETRY_TIME_MS); + } + }; + newWs.onerror = onErrorOrClose; + ws = newWs; + } + this.close = function () { + closing = true; + ws.close(); + }; + // This method is only for testing + this.forceClose = function (millis) { + Logger.debug("Testing: Force WebSocket close"); + if (millis) { + Logger.debug("Testing: Change wsUri for " + millis + " millis to simulate net failure"); + var goodWsUri = wsUri; + wsUri = "wss://21.234.12.34.4:443/"; + forcingDisconnection = true; + setTimeout(function () { + Logger.debug("Testing: Recover good wsUri " + goodWsUri); + wsUri = goodWsUri; + forcingDisconnection = false; + }, millis); + } + ws.close(); + }; + this.reconnectWs = function () { + Logger.debug("reconnectWs"); + reconnectToSameUri(MAX_RETRIES, 1, wsUri); + }; + this.send = function (message) { + ws.send(message); + }; + this.addEventListener = function (type, callback) { + registerMessageHandler = function () { + ws.addEventListener(type, callback); + }; + registerMessageHandler(); + }; +} +module.exports = WebSocketWithReconnection; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],45:[function(require,module,exports){ +/* + * (C) Copyright 2014 Kurento (http://kurento.org/) + * + * 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. + * + */ +var defineProperty_IE8 = false; +if (Object.defineProperty) { + try { + Object.defineProperty({}, "x", {}); + } + catch (e) { + defineProperty_IE8 = true; + } +} +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind +if (!Function.prototype.bind) { + Function.prototype.bind = function (oThis) { + if (typeof this !== 'function') { + // closest thing possible to the ECMAScript 5 + // internal IsCallable 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; + // Transport as a function + if (transport instanceof Function) + return { send: transport }; + // WebSocket & DataChannel + if (transport.send instanceof Function) + return transport; + // Message API (Inter-window & WebWorker) + if (transport.postMessage instanceof Function) { + transport.send = transport.postMessage; + return transport; + } + // Stream API + if (transport.write instanceof Function) { + transport.send = transport.write; + return transport; + } + // Transports that only can receive messages, but not send + if (transport.onmessage !== undefined) + return; + if (transport.pause instanceof Function) + return; + throw new SyntaxError("Transport is not a function nor a valid object"); +} +; +/** + * Representation of a RPC notification + * + * @class + * + * @constructor + * + * @param {String} method -method of the notification + * @param params - parameters of the notification + */ +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 }); + } +} +; +/** + * @class + * + * @constructor + * + * @param {object} packer + * + * @param {object} [options] + * + * @param {object} [transport] + * + * @param {Function} [onRequest] + */ +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) { + // Remove listener from old transport + if (transport) { + // W3C transports + if (transport.removeEventListener) + transport.removeEventListener('message', transportMessage); + else if (transport.removeListener) + transport.removeListener('data', transportMessage); + } + ; + // Set listener on new transport + if (value) { + // W3C transports + 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 = {}; + /** + * Store the response to prevent to process duplicate request later + */ + function storeResponse(message, id, dest) { + var response = { + message: message, + /** Timeout to auto-clean old responses */ + timeout: setTimeout(function () { + responses.remove(id, dest); + }, response_timeout) + }; + responses.set(response, id, dest); + } + ; + /** + * Store the response to ignore duplicated messages later + */ + function storeProcessedResponse(ack, from) { + var timeout = setTimeout(function () { + processedResponses.remove(ack, from); + }, duplicates_timeout); + processedResponses.set(timeout, ack, from); + } + ; + /** + * Representation of a RPC request + * + * @class + * @extends RpcNotification + * + * @constructor + * + * @param {String} method -method of the notification + * @param params - parameters of the notification + * @param {Integer} id - identifier of the request + * @param [from] - source of the notification + */ + 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); + /** + * @constant {Boolean} duplicated + */ + 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); + /** + * Generate a response to this request + * + * @param {Error} [error] + * @param {*} [result] + * + * @returns {string} + */ + this.reply = function (error, result, transport) { + // Fix optional parameters + 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); + // Duplicated request, remove old response timeout + if (response) + clearTimeout(response.timeout); + if (from != undefined) { + if (error) + error.dest = from; + if (result) + result.dest = from; + } + ; + var message; + // New request or overriden one, create new response with provided data + if (error || result != undefined) { + if (self.peerID != undefined) { + if (error) + error.from = self.peerID; + else + result.from = self.peerID; + } + // Protocol indicates that responses has own request methods + 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); + // Store the response to prevent to process a duplicated request later + storeResponse(message, id, from); + // Return the stored response so it can be directly send back + 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); + // Start duplicated responses timeout + storeProcessedResponse(key.id, key.dest); + } + ; + /** + * Allow to cancel a request and don't wait for a response + * + * If `message` is not given, cancel all the request + */ + this.cancel = function (message) { + if (message) + return cancel(message); + for (var message in message2Key) + cancel(message); + }; + this.close = function () { + // Prevent to receive new messages + var transport = this.getTransport(); + if (transport && transport.close) + transport.close(); + // Request & processed responses + this.cancel(); + processedResponses.forEach(clearTimeout); + // Responses + responses.forEach(function (response) { + clearTimeout(response.timeout); + }); + }; + /** + * Generates and encode a JsonRPC 2.0 message + * + * @param {String} method -method of the notification + * @param params - parameters of the notification + * @param [dest] - destination of the notification + * @param {object} [transport] - transport where to send the message + * @param [callback] - function called when a response to this request is + * received. If not defined, a notification will be send instead + * + * @returns {string} A raw JsonRPC 2.0 request or notification string + */ + this.encode = function (method, params, dest, transport, callback) { + // Fix optional parameters + 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; + } + ; + // Encode message + 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); + } + ; + // Return the packed message + message = packer.pack(message); + transport = transport || this.getTransport(); + if (transport) + return transport.send(message); + return message; + }; + /** + * Decode and process a JsonRPC 2.0 message + * + * @param {string} message - string with the content of the message + * + * @returns {RpcNotification|RpcRequest|undefined} - the representation of the + * notification or the request. If a response was processed, it will return + * `undefined` to notify that it was processed + * + * @throws {TypeError} - Message is not defined + */ + this.decode = function (message, transport) { + if (!message) + throw new TypeError("Message is not defined"); + try { + message = packer.unpack(message); + } + catch (e) { + // Ignore invalid messages + 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; + // Ignore messages send by us + if (self.peerID != undefined && from == self.peerID) + return; + // Notification + if (id == undefined && ack == undefined) { + var notification = new RpcNotification(method, params); + if (self.emit('request', notification)) + return; + return notification; + } + ; + function processRequest() { + // If we have a transport and it's a duplicated request, reply inmediatly + 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); + // Update duplicated responses timeout + clearTimeout(timeout); + storeProcessedResponse(ack, from); + } + ; + // Request, or response with own method + if (method) { + // Check if it's a response with own 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); + } + // Request + return processRequest(); + } + ; + var error = message.error; + var result = message.result; + // Ignore responses not send to us + if (error && error.dest && error.dest != self.peerID) + return; + if (result && result.dest && result.dest != self.peerID) + return; + // Response + 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); + } + ; + // Process response + 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":40,"./clients":41,"./clients/transports":43,"./packers":48,"events":1,"inherits":6}],46:[function(require,module,exports){ +/** + * JsonRPC 2.0 packer + */ +/** + * Pack a JsonRPC 2.0 message + * + * @param {Object} message - object to be packaged. It requires to have all the + * fields needed by the JsonRPC 2.0 message that it's going to be generated + * + * @return {String} - the stringified JsonRPC 2.0 message + */ +function pack(message, id) { + var result = { + jsonrpc: "2.0" + }; + // Request + if (message.method) { + result.method = message.method; + if (message.params) + result.params = message.params; + // Request is a notification + 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); +} +; +/** + * Unpack a JsonRPC 2.0 message + * + * @param {String} message - string with the content of the JsonRPC 2.0 message + * + * @throws {TypeError} - Invalid JsonRPC version + * + * @return {Object} - object filled with the JsonRPC 2.0 message content + */ +function unpack(message) { + var result = message; + if (typeof message === 'string' || message instanceof String) { + result = JSON.parse(message); + } + // Check if it's a valid message + var version = result.jsonrpc; + if (version !== '2.0') + throw new TypeError("Invalid JsonRPC version '" + version + "': " + message); + // Response + 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; + // Check only result or error is defined, not both or none + 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 unpacked message + return result; +} +; +exports.pack = pack; +exports.unpack = unpack; + +},{}],47:[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; + +},{}],48:[function(require,module,exports){ +var JsonRPC = require('./JsonRPC'); +var XmlRPC = require('./XmlRPC'); +exports.JsonRPC = JsonRPC; +exports.XmlRPC = XmlRPC; + +},{"./JsonRPC":46,"./XmlRPC":47}],49:[function(require,module,exports){ +/* + * (C) Copyright 2014-2015 Kurento (http://kurento.org/) + * + * 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. + */ +var freeice = require('freeice'); +var inherits = require('inherits'); +var UAParser = require('ua-parser-js'); +var uuid = require('uuid'); +var hark = require('hark'); +var EventEmitter = require('events').EventEmitter; +var recursive = require('merge').recursive.bind(undefined, true); +var sdpTranslator = require('sdp-translator'); +var logger = window.Logger || console; +// var gUM = navigator.mediaDevices.getUserMedia || function (constraints) { +// return new Promise(navigator.getUserMedia(constraints, function (stream) { +// videoStream = stream +// start() +// }).eror(callback)); +// } +/*try { + require('kurento-browser-extensions') +} catch (error) { + if (typeof getScreenConstraints === 'undefined') { + logger.warn('screen sharing is not available') + + getScreenConstraints = function getScreenConstraints(sendSource, callback) { + callback(new Error("This library is not enabled for screen sharing")) + } + } +}*/ +var MEDIA_CONSTRAINTS = { + audio: true, + video: { + width: 640, + framerate: 15 + } +}; +// Somehow, the UAParser constructor gets an empty window object. +// We need to pass the user agent string in order to get information +var ua = (window && window.navigator) ? window.navigator.userAgent : ''; +var parser = new UAParser(ua); +var browser = parser.getBrowser(); +var usePlanB = false; +if (browser.name === 'Chrome' || browser.name === 'Chromium') { + logger.debug(browser.name + ": using SDP PlanB"); + usePlanB = true; +} +function noop(error) { + if (error) + logger.error(error); +} +function trackStop(track) { + track.stop && track.stop(); +} +function streamStop(stream) { + stream.getTracks().forEach(trackStop); +} +/** + * Returns a string representation of a SessionDescription object. + */ +var dumpSDP = function (description) { + if (typeof description === 'undefined' || description === null) { + return ''; + } + return 'type: ' + description.type + '\r\n' + description.sdp; +}; +function bufferizeCandidates(pc, onerror) { + var candidatesQueue = []; + pc.addEventListener('signalingstatechange', function () { + if (this.signalingState === 'stable') { + while (candidatesQueue.length) { + var entry = candidatesQueue.shift(); + this.addIceCandidate(entry.candidate, entry.callback, entry.callback); + } + } + }); + return function (candidate, callback) { + callback = callback || onerror; + switch (pc.signalingState) { + case 'closed': + callback(new Error('PeerConnection object is closed')); + break; + case 'stable': + if (pc.remoteDescription) { + pc.addIceCandidate(candidate, callback, callback); + } + break; + default: + candidatesQueue.push({ + candidate: candidate, + callback: callback + }); + } + }; +} +/* Simulcast utilities */ +function removeFIDFromOffer(sdp) { + var n = sdp.indexOf("a=ssrc-group:FID"); + if (n > 0) { + return sdp.slice(0, n); + } + else { + return sdp; + } +} +function getSimulcastInfo(videoStream) { + var videoTracks = videoStream.getVideoTracks(); + if (!videoTracks.length) { + logger.warn('No video tracks available in the video stream'); + return ''; + } + var lines = [ + 'a=x-google-flag:conference', + 'a=ssrc-group:SIM 1 2 3', + 'a=ssrc:1 cname:localVideo', + 'a=ssrc:1 msid:' + videoStream.id + ' ' + videoTracks[0].id, + 'a=ssrc:1 mslabel:' + videoStream.id, + 'a=ssrc:1 label:' + videoTracks[0].id, + 'a=ssrc:2 cname:localVideo', + 'a=ssrc:2 msid:' + videoStream.id + ' ' + videoTracks[0].id, + 'a=ssrc:2 mslabel:' + videoStream.id, + 'a=ssrc:2 label:' + videoTracks[0].id, + 'a=ssrc:3 cname:localVideo', + 'a=ssrc:3 msid:' + videoStream.id + ' ' + videoTracks[0].id, + 'a=ssrc:3 mslabel:' + videoStream.id, + 'a=ssrc:3 label:' + videoTracks[0].id + ]; + lines.push(''); + return lines.join('\n'); +} +/** + * Wrapper object of an RTCPeerConnection. This object is aimed to simplify the + * development of WebRTC-based applications. + * + * @constructor module:kurentoUtils.WebRtcPeer + * + * @param {String} mode Mode in which the PeerConnection will be configured. + * Valid values are: 'recv', 'send', and 'sendRecv' + * @param localVideo Video tag for the local stream + * @param remoteVideo Video tag for the remote stream + * @param {MediaStream} videoStream Stream to be used as primary source + * (typically video and audio, or only video if combined with audioStream) for + * localVideo and to be added as stream to the RTCPeerConnection + * @param {MediaStream} audioStream Stream to be used as second source + * (typically for audio) for localVideo and to be added as stream to the + * RTCPeerConnection + */ +function WebRtcPeer(mode, options, callback) { + if (!(this instanceof WebRtcPeer)) { + return new WebRtcPeer(mode, options, callback); + } + WebRtcPeer.super_.call(this); + if (options instanceof Function) { + callback = options; + options = undefined; + } + options = options || {}; + callback = (callback || noop).bind(this); + var self = this; + var localVideo = options.localVideo; + var remoteVideo = options.remoteVideo; + var videoStream = options.videoStream; + var audioStream = options.audioStream; + var mediaConstraints = options.mediaConstraints; + var connectionConstraints = options.connectionConstraints; + var pc = options.peerConnection; + var sendSource = options.sendSource || 'webcam'; + var dataChannelConfig = options.dataChannelConfig; + var useDataChannels = options.dataChannels || false; + var dataChannel; + var guid = uuid.v4(); + var configuration = recursive({ + iceServers: freeice() + }, options.configuration); + var onicecandidate = options.onicecandidate; + if (onicecandidate) + this.on('icecandidate', onicecandidate); + var oncandidategatheringdone = options.oncandidategatheringdone; + if (oncandidategatheringdone) { + this.on('candidategatheringdone', oncandidategatheringdone); + } + var simulcast = options.simulcast; + var multistream = options.multistream; + var interop = new sdpTranslator.Interop(); + var candidatesQueueOut = []; + var candidategatheringdone = false; + Object.defineProperties(this, { + 'peerConnection': { + get: function () { + return pc; + } + }, + 'id': { + value: options.id || guid, + writable: false + }, + 'remoteVideo': { + get: function () { + return remoteVideo; + } + }, + 'localVideo': { + get: function () { + return localVideo; + } + }, + 'dataChannel': { + get: function () { + return dataChannel; + } + }, + /** + * @member {(external:ImageData|undefined)} currentFrame + */ + 'currentFrame': { + get: function () { + // [ToDo] Find solution when we have a remote stream but we didn't set + // a remoteVideo tag + if (!remoteVideo) + return; + if (remoteVideo.readyState < remoteVideo.HAVE_CURRENT_DATA) + throw new Error('No video stream data available'); + var canvas = document.createElement('canvas'); + canvas.width = remoteVideo.videoWidth; + canvas.height = remoteVideo.videoHeight; + canvas.getContext('2d').drawImage(remoteVideo, 0, 0); + return canvas; + } + } + }); + // Init PeerConnection + if (!pc) { + pc = new RTCPeerConnection(configuration); + if (useDataChannels && !dataChannel) { + var dcId = 'WebRtcPeer-' + self.id; + var dcOptions = undefined; + if (dataChannelConfig) { + dcId = dataChannelConfig.id || dcId; + dcOptions = dataChannelConfig.options; + } + dataChannel = pc.createDataChannel(dcId, dcOptions); + if (dataChannelConfig) { + dataChannel.onopen = dataChannelConfig.onopen; + dataChannel.onclose = dataChannelConfig.onclose; + dataChannel.onmessage = dataChannelConfig.onmessage; + dataChannel.onbufferedamountlow = dataChannelConfig.onbufferedamountlow; + dataChannel.onerror = dataChannelConfig.onerror || noop; + } + } + } + pc.addEventListener('icecandidate', function (event) { + var candidate = event.candidate; + if (EventEmitter.listenerCount(self, 'icecandidate') || + EventEmitter.listenerCount(self, 'candidategatheringdone')) { + if (candidate) { + var cand; + if (multistream && usePlanB) { + cand = interop.candidateToUnifiedPlan(candidate); + } + else { + cand = candidate; + } + self.emit('icecandidate', cand); + candidategatheringdone = false; + } + else if (!candidategatheringdone) { + self.emit('candidategatheringdone'); + candidategatheringdone = true; + } + } + else if (!candidategatheringdone) { + // Not listening to 'icecandidate' or 'candidategatheringdone' events, queue + // the candidate until one of them is listened + candidatesQueueOut.push(candidate); + if (!candidate) + candidategatheringdone = true; + } + }); + pc.ontrack = options.onaddstream; + pc.onnegotiationneeded = options.onnegotiationneeded; + this.on('newListener', function (event, listener) { + if (event === 'icecandidate' || event === 'candidategatheringdone') { + while (candidatesQueueOut.length) { + var candidate = candidatesQueueOut.shift(); + if (!candidate === (event === 'candidategatheringdone')) { + listener(candidate); + } + } + } + }); + var addIceCandidate = bufferizeCandidates(pc); + /** + * Callback function invoked when an ICE candidate is received. Developers are + * expected to invoke this function in order to complete the SDP negotiation. + * + * @function module:kurentoUtils.WebRtcPeer.prototype.addIceCandidate + * + * @param iceCandidate - Literal object with the ICE candidate description + * @param callback - Called when the ICE candidate has been added. + */ + this.addIceCandidate = function (iceCandidate, callback) { + var candidate; + if (multistream && usePlanB) { + candidate = interop.candidateToPlanB(iceCandidate); + } + else { + candidate = new RTCIceCandidate(iceCandidate); + } + logger.debug('Remote ICE candidate received', iceCandidate); + callback = (callback || noop).bind(this); + addIceCandidate(candidate, callback); + }; + this.generateOffer = function (callback) { + callback = callback.bind(this); + var offerAudio = true; + var offerVideo = true; + // Constraints must have both blocks + if (mediaConstraints) { + offerAudio = (typeof mediaConstraints.audio === 'boolean') ? + mediaConstraints.audio : true; + offerVideo = (typeof mediaConstraints.video === 'boolean') ? + mediaConstraints.video : true; + } + var browserDependantConstraints = { + offerToReceiveAudio: (mode !== 'sendonly' && offerAudio), + offerToReceiveVideo: (mode !== 'sendonly' && offerVideo) + }; + //FIXME: clarify possible constraints passed to createOffer() + /*var constraints = recursive(browserDependantConstraints, + connectionConstraints)*/ + var constraints = browserDependantConstraints; + logger.debug('constraints: ' + JSON.stringify(constraints)); + pc.createOffer(constraints).then(function (offer) { + logger.debug('Created SDP offer'); + offer = mangleSdpToAddSimulcast(offer); + return pc.setLocalDescription(offer); + }).then(function () { + var localDescription = pc.localDescription; + logger.debug('Local description set', localDescription.sdp); + if (multistream && usePlanB) { + localDescription = interop.toUnifiedPlan(localDescription); + logger.debug('offer::origPlanB->UnifiedPlan', dumpSDP(localDescription)); + } + callback(null, localDescription.sdp, self.processAnswer.bind(self)); + }).catch(callback); + }; + this.getLocalSessionDescriptor = function () { + return pc.localDescription; + }; + this.getRemoteSessionDescriptor = function () { + return pc.remoteDescription; + }; + function setRemoteVideo() { + if (remoteVideo) { + var stream = pc.getRemoteStreams()[0]; + var url = stream ? URL.createObjectURL(stream) : ''; + remoteVideo.pause(); + remoteVideo.src = url; + remoteVideo.load(); + logger.debug('Remote URL:', url); + } + } + this.showLocalVideo = function () { + localVideo.src = URL.createObjectURL(videoStream); + localVideo.muted = true; + }; + this.send = function (data) { + if (dataChannel && dataChannel.readyState === 'open') { + dataChannel.send(data); + } + else { + logger.warn('Trying to send data over a non-existing or closed data channel'); + } + }; + /** + * Callback function invoked when a SDP answer is received. Developers are + * expected to invoke this function in order to complete the SDP negotiation. + * + * @function module:kurentoUtils.WebRtcPeer.prototype.processAnswer + * + * @param sdpAnswer - Description of sdpAnswer + * @param callback - + * Invoked after the SDP answer is processed, or there is an error. + */ + this.processAnswer = function (sdpAnswer, callback) { + callback = (callback || noop).bind(this); + var answer = new RTCSessionDescription({ + type: 'answer', + sdp: sdpAnswer + }); + if (multistream && usePlanB) { + var planBAnswer = interop.toPlanB(answer); + logger.debug('asnwer::planB', dumpSDP(planBAnswer)); + answer = planBAnswer; + } + logger.debug('SDP answer received, setting remote description'); + if (pc.signalingState === 'closed') { + return callback('PeerConnection is closed'); + } + pc.setRemoteDescription(answer, function () { + setRemoteVideo(); + callback(); + }, callback); + }; + /** + * Callback function invoked when a SDP offer is received. Developers are + * expected to invoke this function in order to complete the SDP negotiation. + * + * @function module:kurentoUtils.WebRtcPeer.prototype.processOffer + * + * @param sdpOffer - Description of sdpOffer + * @param callback - Called when the remote description has been set + * successfully. + */ + this.processOffer = function (sdpOffer, callback) { + callback = callback.bind(this); + var offer = new RTCSessionDescription({ + type: 'offer', + sdp: sdpOffer + }); + if (multistream && usePlanB) { + var planBOffer = interop.toPlanB(offer); + logger.debug('offer::planB', dumpSDP(planBOffer)); + offer = planBOffer; + } + logger.debug('SDP offer received, setting remote description'); + if (pc.signalingState === 'closed') { + return callback('PeerConnection is closed'); + } + pc.setRemoteDescription(offer).then(function () { + return setRemoteVideo(); + }).then(function () { + return pc.createAnswer(); + }).then(function (answer) { + answer = mangleSdpToAddSimulcast(answer); + logger.debug('Created SDP answer'); + return pc.setLocalDescription(answer); + }).then(function () { + var localDescription = pc.localDescription; + if (multistream && usePlanB) { + localDescription = interop.toUnifiedPlan(localDescription); + logger.debug('answer::origPlanB->UnifiedPlan', dumpSDP(localDescription)); + } + logger.debug('Local description set', localDescription.sdp); + callback(null, localDescription.sdp); + }).catch(callback); + }; + function mangleSdpToAddSimulcast(answer) { + if (simulcast) { + if (browser.name === 'Chrome' || browser.name === 'Chromium') { + logger.debug('Adding multicast info'); + answer = new RTCSessionDescription({ + 'type': answer.type, + 'sdp': removeFIDFromOffer(answer.sdp) + getSimulcastInfo(videoStream) + }); + } + else { + logger.warn('Simulcast is only available in Chrome browser.'); + } + } + return answer; + } + /** + * This function creates the RTCPeerConnection object taking into account the + * properties received in the constructor. It starts the SDP negotiation + * process: generates the SDP offer and invokes the onsdpoffer callback. This + * callback is expected to send the SDP offer, in order to obtain an SDP + * answer from another peer. + */ + function start() { + if (pc.signalingState === 'closed') { + callback('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue'); + } + if (videoStream && localVideo) { + self.showLocalVideo(); + } + if (videoStream) { + pc.addStream(videoStream); + } + if (audioStream) { + pc.addStream(audioStream); + } + // [Hack] https://code.google.com/p/chromium/issues/detail?id=443558 + var browser = parser.getBrowser(); + if (mode === 'sendonly' && + (browser.name === 'Chrome' || browser.name === 'Chromium') && + browser.major === 39) { + mode = 'sendrecv'; + } + callback(); + } + if (mode !== 'recvonly' && !videoStream && !audioStream) { + function getMedia(constraints) { + if (constraints === undefined) { + constraints = MEDIA_CONSTRAINTS; + } + navigator.mediaDevices.getUserMedia(constraints).then(function (stream) { + videoStream = stream; + start(); + }).catch(callback); + } + if (sendSource === 'webcam') { + getMedia(mediaConstraints); + } + else { + getScreenConstraints(sendSource, function (error, constraints_) { + if (error) + return callback(error); + constraints = [mediaConstraints]; + constraints.unshift(constraints_); + getMedia(recursive.apply(undefined, constraints)); + }, guid); + } + } + else { + setTimeout(start, 0); + } + this.on('_dispose', function () { + if (localVideo) { + localVideo.pause(); + localVideo.src = ''; + localVideo.load(); + //Unmute local video in case the video tag is later used for remote video + localVideo.muted = false; + } + if (remoteVideo) { + remoteVideo.pause(); + remoteVideo.src = ''; + remoteVideo.load(); + } + self.removeAllListeners(); + if (window.cancelChooseDesktopMedia !== undefined) { + window.cancelChooseDesktopMedia(guid); + } + }); +} +inherits(WebRtcPeer, EventEmitter); +function createEnableDescriptor(type) { + var method = 'get' + type + 'Tracks'; + return { + enumerable: true, + get: function () { + // [ToDo] Should return undefined if not all tracks have the same value? + if (!this.peerConnection) + return; + var streams = this.peerConnection.getLocalStreams(); + if (!streams.length) + return; + for (var i = 0, stream; stream = streams[i]; i++) { + var tracks = stream[method](); + for (var j = 0, track; track = tracks[j]; j++) + if (!track.enabled) + return false; + } + return true; + }, + set: function (value) { + function trackSetEnable(track) { + track.enabled = value; + } + this.peerConnection.getLocalStreams().forEach(function (stream) { + stream[method]().forEach(trackSetEnable); + }); + } + }; +} +Object.defineProperties(WebRtcPeer.prototype, { + 'enabled': { + enumerable: true, + get: function () { + return this.audioEnabled && this.videoEnabled; + }, + set: function (value) { + this.audioEnabled = this.videoEnabled = value; + } + }, + 'audioEnabled': createEnableDescriptor('Audio'), + 'videoEnabled': createEnableDescriptor('Video') +}); +WebRtcPeer.prototype.getLocalStream = function (index) { + if (this.peerConnection) { + return this.peerConnection.getLocalStreams()[index || 0]; + } +}; +WebRtcPeer.prototype.getRemoteStream = function (index) { + if (this.peerConnection) { + return this.peerConnection.getRemoteStreams()[index || 0]; + } +}; +/** + * @description This method frees the resources used by WebRtcPeer. + * + * @function module:kurentoUtils.WebRtcPeer.prototype.dispose + */ +WebRtcPeer.prototype.dispose = function () { + logger.debug('Disposing WebRtcPeer'); + var pc = this.peerConnection; + var dc = this.dataChannel; + try { + if (dc) { + if (dc.signalingState === 'closed') + return; + dc.close(); + } + if (pc) { + if (pc.signalingState === 'closed') + return; + pc.getLocalStreams().forEach(streamStop); + // FIXME This is not yet implemented in firefox + // if(videoStream) pc.removeStream(videoStream); + // if(audioStream) pc.removeStream(audioStream); + pc.close(); + } + } + catch (err) { + logger.warn('Exception disposing webrtc peer ' + err); + } + this.emit('_dispose'); +}; +// +// Specialized child classes +// +function WebRtcPeerRecvonly(options, callback) { + if (!(this instanceof WebRtcPeerRecvonly)) { + return new WebRtcPeerRecvonly(options, callback); + } + WebRtcPeerRecvonly.super_.call(this, 'recvonly', options, callback); +} +inherits(WebRtcPeerRecvonly, WebRtcPeer); +function WebRtcPeerSendonly(options, callback) { + if (!(this instanceof WebRtcPeerSendonly)) { + return new WebRtcPeerSendonly(options, callback); + } + WebRtcPeerSendonly.super_.call(this, 'sendonly', options, callback); +} +inherits(WebRtcPeerSendonly, WebRtcPeer); +function WebRtcPeerSendrecv(options, callback) { + if (!(this instanceof WebRtcPeerSendrecv)) { + return new WebRtcPeerSendrecv(options, callback); + } + WebRtcPeerSendrecv.super_.call(this, 'sendrecv', options, callback); +} +inherits(WebRtcPeerSendrecv, WebRtcPeer); +function harkUtils(stream, options) { + return hark(stream, options); +} +exports.bufferizeCandidates = bufferizeCandidates; +exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly; +exports.WebRtcPeerSendonly = WebRtcPeerSendonly; +exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv; +exports.hark = harkUtils; + +},{"events":1,"freeice":2,"hark":5,"inherits":6,"merge":7,"sdp-translator":16,"ua-parser-js":20,"uuid":21}],50:[function(require,module,exports){ +/* + * (C) Copyright 2014 Kurento (http://kurento.org/) + * + * 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. + * + */ +/** + * This module contains a set of reusable components that have been found useful + * during the development of the WebRTC applications with Kurento. + * + * @module kurentoUtils + * + * @copyright 2014 Kurento (http://kurento.org/) + * @license ALv2 + */ +var WebRtcPeer = require('./WebRtcPeer'); +exports.WebRtcPeer = WebRtcPeer; + +},{"./WebRtcPeer":49}],51:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var OpenVidu_1 = require("./OpenVidu"); +//This export with --standalone option allows using OpenVidu from bowser with namespace +//export { OpenVidu } from './OpenVidu'; +//This "hack" allows to use OpenVidu from the global space window +if (window) { + window["OpenVidu"] = OpenVidu_1.OpenVidu; +} +//Command to generate bundle.js without namespace +//watchify Main.ts -p [ tsify ] --exclude kurento-browser-extensions --debug -o ../static/js/OpenVidu.js -v + +},{"./OpenVidu":52}],52:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/* + * (C) Copyright 2017 OpenVidu (http://openvidu.io/) + * + * 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. + * + */ +var OpenViduInternal_1 = require("../OpenViduInternal/OpenViduInternal"); +var Session_1 = require("./Session"); +var Publisher_1 = require("./Publisher"); +var OpenViduError_1 = require("../OpenViduInternal/OpenViduError"); +var LocalRecorder_1 = require("../OpenViduInternal/LocalRecorder"); +var adapter = require("webrtc-adapter"); +var screenSharingAuto = require("../ScreenSharing/Screen-Capturing-Auto.js"); +var DetectRTC = require("../KurentoUtils/DetectRTC"); +if (window) { + window["adapter"] = adapter; +} +var OpenVidu = /** @class */ (function () { + function OpenVidu() { + this.openVidu = new OpenViduInternal_1.OpenViduInternal(); + console.info("'OpenVidu' initialized"); + } + ; + OpenVidu.prototype.initSession = function (param1, param2) { + if (typeof param2 == "string") { + return new Session_1.Session(this.openVidu.initSession(param2), this); + } + else { + return new Session_1.Session(this.openVidu.initSession(param1), this); + } + }; + OpenVidu.prototype.initPublisher = function (parentId, cameraOptions, callback) { + var publisher; + if (cameraOptions != null) { + cameraOptions.audio = cameraOptions.audio != null ? cameraOptions.audio : true; + cameraOptions.video = cameraOptions.video != null ? cameraOptions.video : true; + if (!cameraOptions.screen) { + // Webcam and/or microphone is being requested + var cameraOptionsAux = { + sendAudio: cameraOptions.audio != null ? cameraOptions.audio : true, + sendVideo: cameraOptions.video != null ? cameraOptions.video : true, + activeAudio: cameraOptions.audioActive != null ? cameraOptions.audioActive : true, + activeVideo: cameraOptions.videoActive != null ? cameraOptions.videoActive : true, + dataChannel: true, + mediaConstraints: this.openVidu.generateMediaConstraints(cameraOptions) + }; + cameraOptions = cameraOptionsAux; + publisher = new Publisher_1.Publisher(this.openVidu.initPublisherTagged(parentId, cameraOptions, true, callback), parentId, false); + console.info("'Publisher' initialized"); + return publisher; + } + else { + // Screen share is being requested + publisher = new Publisher_1.Publisher(this.openVidu.initPublisherScreen(parentId, true, callback), parentId, true); + if (DetectRTC.browser.name === 'Firefox' && DetectRTC.browser.version >= 52) { + screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) { + cameraOptions = { + sendAudio: cameraOptions.audio, + sendVideo: cameraOptions.video, + activeAudio: cameraOptions.audioActive != null ? cameraOptions.audioActive : true, + activeVideo: cameraOptions.videoActive != null ? cameraOptions.videoActive : true, + dataChannel: true, + mediaConstraints: { + video: screenConstraints.video, + audio: false + } + }; + publisher.stream.configureScreenOptions(cameraOptions); + console.info("'Publisher' initialized"); + publisher.stream.ee.emitEvent('can-request-screen'); + }); + return publisher; + } + else if (DetectRTC.browser.name === 'Chrome') { + // Screen is being requested + /*screenSharing.isChromeExtensionAvailable((availability) => { + switch (availability) { + case 'available': + console.warn('EXTENSION AVAILABLE!!!'); + screenSharing.getScreenConstraints((error, screenConstraints) => { + if (!error) { + console.warn(screenConstraints); + } + }); + break; + case 'unavailable': + console.warn('EXTENSION NOT AVAILABLE!!!'); + break; + case 'isFirefox': + console.warn('IT IS FIREFOX!!!'); + screenSharing.getScreenConstraints((error, screenConstraints) => { + if (!error) { + console.warn(screenConstraints); + } + }); + break; + } + });*/ + screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) { + if (error === 'not-installed') { + var error_1 = new OpenViduError_1.OpenViduError("SCREEN_EXTENSION_NOT_INSTALLED" /* SCREEN_EXTENSION_NOT_INSTALLED */, 'https://chrome.google.com/webstore/detail/screen-capturing/ajhifddimkapgcifgcodmmfdlknahffk'); + console.error(error_1); + if (callback) + callback(error_1); + return; + } + else if (error === 'permission-denied') { + var error_2 = new OpenViduError_1.OpenViduError("SCREEN_CAPTURE_DENIED" /* SCREEN_CAPTURE_DENIED */, 'You must allow access to one window of your desktop'); + console.error(error_2); + if (callback) + callback(error_2); + return; + } + cameraOptions = { + sendAudio: cameraOptions.audio != null ? cameraOptions.audio : true, + sendVideo: cameraOptions.video != null ? cameraOptions.video : true, + activeAudio: cameraOptions.audioActive != null ? cameraOptions.audioActive : true, + activeVideo: cameraOptions.videoActive != null ? cameraOptions.videoActive : true, + dataChannel: true, + mediaConstraints: { + video: screenConstraints.video, + audio: false + } + }; + publisher.stream.configureScreenOptions(cameraOptions); + publisher.stream.ee.emitEvent('can-request-screen'); + }, function (error) { + console.error('getScreenId error', error); + return; + }); + console.info("'Publisher' initialized"); + return publisher; + } + else { + console.error('Screen sharing not supported on ' + DetectRTC.browser.name); + if (!!callback) + callback(new OpenViduError_1.OpenViduError("SCREEN_SHARING_NOT_SUPPORTED" /* SCREEN_SHARING_NOT_SUPPORTED */, 'Screen sharing not supported on ' + DetectRTC.browser.name + ' ' + DetectRTC.browser.version)); + } + } + } + else { + cameraOptions = { + sendAudio: true, + sendVideo: true, + activeAudio: true, + activeVideo: true, + dataChannel: true, + mediaConstraints: { + audio: true, + video: { width: { ideal: 1280 } } + } + }; + publisher = new Publisher_1.Publisher(this.openVidu.initPublisherTagged(parentId, cameraOptions, true, callback), parentId, false); + console.info("'Publisher' initialized"); + return publisher; + } + }; + OpenVidu.prototype.reinitPublisher = function (publisher) { + if (publisher.stream.typeOfVideo !== 'SCREEN') { + publisher = new Publisher_1.Publisher(this.openVidu.initPublisherTagged(publisher.stream.getParentId(), publisher.stream.outboundOptions, false), publisher.stream.getParentId(), false); + console.info("'Publisher' initialized"); + return publisher; + } + else { + publisher = new Publisher_1.Publisher(this.openVidu.initPublisherScreen(publisher.stream.getParentId(), false), publisher.stream.getParentId(), true); + if (DetectRTC.browser.name === 'Firefox' && DetectRTC.browser.version >= 52) { + screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) { + publisher.stream.outboundOptions.mediaConstraints.video = screenConstraints.video; + publisher.stream.configureScreenOptions(publisher.stream.outboundOptions); + console.info("'Publisher' initialized"); + publisher.stream.ee.emitEvent('can-request-screen'); + }); + return publisher; + } + else if (DetectRTC.browser.name === 'Chrome') { + screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) { + if (error === 'not-installed') { + var error_3 = new OpenViduError_1.OpenViduError("SCREEN_EXTENSION_NOT_INSTALLED" /* SCREEN_EXTENSION_NOT_INSTALLED */, 'https://chrome.google.com/webstore/detail/screen-capturing/ajhifddimkapgcifgcodmmfdlknahffk'); + console.error(error_3); + return; + } + else if (error === 'permission-denied') { + var error_4 = new OpenViduError_1.OpenViduError("SCREEN_CAPTURE_DENIED" /* SCREEN_CAPTURE_DENIED */, 'You must allow access to one window of your desktop'); + console.error(error_4); + return; + } + publisher.stream.outboundOptions.mediaConstraints.video = screenConstraints.video; + publisher.stream.configureScreenOptions(publisher.stream.outboundOptions); + publisher.stream.ee.emitEvent('can-request-screen'); + }, function (error) { + console.error('getScreenId error', error); + return; + }); + console.info("'Publisher' initialized"); + return publisher; + } + else { + console.error('Screen sharing not supported on ' + DetectRTC.browser.name); + } + } + }; + OpenVidu.prototype.checkSystemRequirements = function () { + var defaultWebRTCSupport = DetectRTC.isWebRTCSupported; + var browser = DetectRTC.browser.name; + var version = DetectRTC.browser.version; + if ((browser !== 'Chrome') && (browser !== 'Firefox') && (browser !== 'Opera')) { + return 0; + } + else { + return defaultWebRTCSupport ? 1 : 0; + } + }; + OpenVidu.prototype.getDevices = function (callback) { + navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) { + callback(null, deviceInfos); + }).catch(function (error) { + console.error("Error getting devices", error); + callback(error, null); + }); + }; + OpenVidu.prototype.enableProdMode = function () { + console.log = function () { }; + console.debug = function () { }; + console.info = function () { }; + console.warn = function () { }; + }; + OpenVidu.prototype.initLocalRecorder = function (stream) { + return new LocalRecorder_1.LocalRecorder(stream); + }; + return OpenVidu; +}()); +exports.OpenVidu = OpenVidu; + +},{"../KurentoUtils/DetectRTC":39,"../OpenViduInternal/LocalRecorder":57,"../OpenViduInternal/OpenViduError":58,"../OpenViduInternal/OpenViduInternal":59,"../ScreenSharing/Screen-Capturing-Auto.js":63,"./Publisher":53,"./Session":54,"webrtc-adapter":26}],53:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var EventEmitter = require("wolfy87-eventemitter"); +var Publisher = /** @class */ (function () { + function Publisher(stream, parentId, isScreenRequested) { + var _this = this; + this.ee = new EventEmitter(); + this.accessAllowed = false; + this.isScreenRequested = false; + this.stream = stream; + this.isScreenRequested = isScreenRequested; + // Listens to the deactivation of the default behaviour upon the deletion of a Stream object + this.ee.addListener('stream-destroyed-default', function (event) { + var s = event.stream; + s.addOnceEventListener('video-removed', function () { + _this.ee.emitEvent('videoElementDestroyed'); + }); + s.removeVideo(); + }); + if (document.getElementById(parentId) != null) { + this.element = document.getElementById(parentId); + } + } + Publisher.prototype.publishAudio = function (value) { + this.stream.getWebRtcPeer().audioEnabled = value; + }; + Publisher.prototype.publishVideo = function (value) { + this.stream.getWebRtcPeer().videoEnabled = value; + }; + Publisher.prototype.destroy = function () { + if (!!this.session) + this.session.unpublish(this); + this.stream.dispose(); + this.stream.removeVideo(this.element); + return this; + }; + Publisher.prototype.subscribeToRemote = function () { + this.stream.subscribeToMyRemote(); + }; + Publisher.prototype.on = function (eventName, callback) { + var _this = this; + this.ee.addListener(eventName, function (event) { + if (event) { + console.info("Event '" + eventName + "' triggered by 'Publisher'", event); + } + else { + console.info("Event '" + eventName + "' triggered by 'Publisher'"); + } + callback(event); + }); + if (eventName == 'streamCreated') { + if (this.stream.isPublisherPublished) { + this.ee.emitEvent('streamCreated', [{ stream: this.stream }]); + } + else { + this.stream.addEventListener('stream-created-by-publisher', function () { + _this.ee.emitEvent('streamCreated', [{ stream: _this.stream }]); + }); + } + } + if (eventName == 'videoElementCreated') { + if (this.stream.isVideoELementCreated) { + this.ee.emitEvent('videoElementCreated', [{ + element: this.stream.getVideoElement() + }]); + } + else { + this.stream.addEventListener('video-element-created-by-stream', function (element) { + _this.id = element.id; + _this.ee.emitEvent('videoElementCreated', [{ + element: element.element + }]); + }); + } + } + if (eventName == 'videoPlaying') { + var video = this.stream.getVideoElement(); + if (!this.stream.displayMyRemote() && video && + video.currentTime > 0 && + video.paused == false && + video.ended == false && + video.readyState == 4) { + this.ee.emitEvent('videoPlaying', [{ + element: this.stream.getVideoElement() + }]); + } + else { + this.stream.addEventListener('video-is-playing', function (element) { + _this.ee.emitEvent('videoPlaying', [{ + element: element.element + }]); + }); + } + } + if (eventName == 'remoteVideoPlaying') { + var video = this.stream.getVideoElement(); + if (this.stream.displayMyRemote() && video && + video.currentTime > 0 && + video.paused == false && + video.ended == false && + video.readyState == 4) { + this.ee.emitEvent('remoteVideoPlaying', [{ + element: this.stream.getVideoElement() + }]); + } + else { + this.stream.addEventListener('remote-video-is-playing', function (element) { + _this.ee.emitEvent('remoteVideoPlaying', [{ + element: element.element + }]); + }); + } + } + if (eventName == 'accessAllowed') { + if (this.stream.accessIsAllowed) { + this.ee.emitEvent('accessAllowed'); + } + else { + this.stream.addEventListener('access-allowed-by-publisher', function () { + _this.ee.emitEvent('accessAllowed'); + }); + } + } + if (eventName == 'accessDenied') { + if (this.stream.accessIsDenied) { + this.ee.emitEvent('accessDenied'); + } + else { + this.stream.addEventListener('access-denied-by-publisher', function () { + _this.ee.emitEvent('accessDenied'); + }); + } + } + }; + return Publisher; +}()); +exports.Publisher = Publisher; + +},{"wolfy87-eventemitter":38}],54:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var OpenViduError_1 = require("../OpenViduInternal/OpenViduError"); +var Subscriber_1 = require("./Subscriber"); +var EventEmitter = require("wolfy87-eventemitter"); +var DetectRTC = require("../KurentoUtils/DetectRTC"); +var Session = /** @class */ (function () { + function Session(session, openVidu) { + var _this = this; + this.session = session; + this.openVidu = openVidu; + this.ee = new EventEmitter(); + this.sessionId = session.getSessionId(); + // Listens to the deactivation of the default behaviour upon the deletion of a Stream object + this.session.addEventListener('stream-destroyed-default', function (event) { + event.stream.removeVideo(); + }); + // Listens to the deactivation of the default behaviour upon the disconnection of a Session + this.session.addEventListener('session-disconnected-default', function () { + var s; + for (var streamId in _this.session.getRemoteStreams()) { + _this.session.getRemoteStreams()[streamId].removeVideo(); + } + if (_this.connection && (Object.keys(_this.connection.getStreams()).length > 0)) { + for (var streamId in _this.connection.getStreams()) { + _this.connection.getStreams()[streamId].removeVideo(); + } + } + }); + // Sets or updates the value of 'connection' property. Triggered by SessionInternal when succesful connection + this.session.addEventListener('update-connection-object', function (event) { + _this.connection = event.connection; + }); + } + Session.prototype.connect = function (param1, param2, param3) { + // Early configuration to deactivate automatic subscription to streams + if (param3) { + if (this.openVidu.checkSystemRequirements()) { + this.session.configure({ + sessionId: this.session.getSessionId(), + participantId: param1, + metadata: this.session.stringClientMetadata(param2), + subscribeToStreams: false + }); + this.session.connect(param1, param3); + } + else { + param3(new OpenViduError_1.OpenViduError("BROWSER_NOT_SUPPORTED" /* BROWSER_NOT_SUPPORTED */, 'Browser ' + DetectRTC.browser.name + ' ' + DetectRTC.browser.version + ' is not supported in OpenVidu')); + } + } + else { + if (this.openVidu.checkSystemRequirements()) { + this.session.configure({ + sessionId: this.session.getSessionId(), + participantId: param1, + metadata: '', + subscribeToStreams: false + }); + this.session.connect(param1, param2); + } + else { + param2(new OpenViduError_1.OpenViduError("BROWSER_NOT_SUPPORTED" /* BROWSER_NOT_SUPPORTED */, 'Browser ' + DetectRTC.browser.name + ' ' + DetectRTC.browser.version + ' is not supported in OpenVidu')); + } + } + }; + Session.prototype.disconnect = function () { + var _this = this; + this.openVidu.openVidu.close(false); + this.session.emitEvent('sessionDisconnected', [{ + preventDefault: function () { _this.session.removeEvent('session-disconnected-default'); } + }]); + this.session.emitEvent('session-disconnected-default', [{}]); + }; + Session.prototype.publish = function (publisher) { + var _this = this; + if (!publisher.stream.isPublisherPublished) { + if (publisher.isScreenRequested) { + if (!publisher.stream.isScreenRequestedReady) { + publisher.stream.addOnceEventListener('screen-ready', function () { + _this.streamPublish(publisher); + }); + } + else { + this.streamPublish(publisher); + } + } + else { + this.streamPublish(publisher); + } + } + else { + publisher = this.openVidu.reinitPublisher(publisher); + if (publisher.isScreenRequested && !publisher.stream.isScreenRequestedReady) { + publisher.stream.addOnceEventListener('screen-ready', function () { + _this.streamPublish(publisher); + }); + } + else { + this.streamPublish(publisher); + } + } + }; + Session.prototype.streamPublish = function (publisher) { + publisher.session = this; + this.connection.addStream(publisher.stream); + publisher.stream.publish(); + }; + Session.prototype.unpublish = function (publisher) { + this.session.unpublish(publisher); + }; + Session.prototype.on = function (eventName, callback) { + this.session.addEventListener(eventName, function (event) { + if (event) { + console.info("Event '" + eventName + "' triggered by 'Session'", event); + } + else { + console.info("Event '" + eventName + "' triggered by 'Session'"); + } + callback(event); + }); + }; + Session.prototype.once = function (eventName, callback) { + this.session.addOnceEventListener(eventName, function (event) { + callback(event); + }); + }; + Session.prototype.off = function (eventName, eventHandler) { + this.session.removeListener(eventName, eventHandler); + }; + Session.prototype.subscribe = function (param1, param2, param3) { + // Subscription + this.session.subscribe(param1); + var subscriber = new Subscriber_1.Subscriber(param1, param2); + param1.playOnlyVideo(param2, null); + return subscriber; + }; + Session.prototype.unsubscribe = function (subscriber) { + this.session.unsubscribe(subscriber.stream); + subscriber.stream.removeVideo(); + }; + Session.prototype.signal = function (signal, completionHandler) { + var signalMessage = {}; + if (signal.to && signal.to.length > 0) { + var connectionIds = []; + for (var i = 0; i < signal.to.length; i++) { + connectionIds.push(signal.to[i].connectionId); + } + signalMessage['to'] = connectionIds; + } + else { + signalMessage['to'] = []; + } + signalMessage['data'] = signal.data ? signal.data : ''; + signalMessage['type'] = signal.type ? signal.type : ''; + this.openVidu.openVidu.sendMessage(JSON.stringify(signalMessage)); + }; + return Session; +}()); +exports.Session = Session; + +},{"../KurentoUtils/DetectRTC":39,"../OpenViduInternal/OpenViduError":58,"./Subscriber":55,"wolfy87-eventemitter":38}],55:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var EventEmitter = require("wolfy87-eventemitter"); +var Subscriber = /** @class */ (function () { + function Subscriber(stream, parentId) { + var _this = this; + this.ee = new EventEmitter(); + this.stream = stream; + if (document.getElementById(parentId) != null) { + this.element = document.getElementById(parentId); + } + // Listens to deletion of the HTML video element of the Subscriber + this.stream.addEventListener('video-removed', function () { + _this.ee.emitEvent('videoElementDestroyed'); + }); + } + Subscriber.prototype.on = function (eventName, callback) { + var _this = this; + this.ee.addListener(eventName, function (event) { + if (event) { + console.info("Event '" + eventName + "' triggered by 'Subscriber'", event); + } + else { + console.info("Event '" + eventName + "' triggered by 'Subscriber'"); + } + callback(event); + }); + if (eventName == 'videoElementCreated') { + if (this.stream.isVideoELementCreated) { + this.ee.emitEvent('videoElementCreated', [{ + element: this.stream.getVideoElement() + }]); + } + else { + this.stream.addOnceEventListener('video-element-created-by-stream', function (element) { + _this.id = element.id; + _this.ee.emitEvent('videoElementCreated', [{ + element: element + }]); + }); + } + } + if (eventName == 'videoPlaying') { + var video = this.stream.getVideoElement(); + if (!this.stream.displayMyRemote() && video && + video.currentTime > 0 && + video.paused == false && + video.ended == false && + video.readyState == 4) { + this.ee.emitEvent('videoPlaying', [{ + element: this.stream.getVideoElement() + }]); + } + else { + this.stream.addOnceEventListener('video-is-playing', function (element) { + _this.ee.emitEvent('videoPlaying', [{ + element: element.element + }]); + }); + } + } + }; + return Subscriber; +}()); +exports.Subscriber = Subscriber; + +},{"wolfy87-eventemitter":38}],56:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Stream_1 = require("./Stream"); +var Connection = /** @class */ (function () { + function Connection(openVidu, local, room, options) { + this.openVidu = openVidu; + this.local = local; + this.room = room; + this.options = options; + this.streams = {}; + console.info("'Connection' created (" + (local ? "local" : "remote") + ")" + (local ? "" : ", with 'connectionId' [" + (options ? options.id : '') + "] ")); + if (options && !local) { + this.connectionId = options.id; + if (options.metadata) { + this.data = options.metadata; + } + if (options.streams) { + this.initRemoteStreams(options); + } + } + } + Connection.prototype.addStream = function (stream) { + stream.connection = this; + this.streams[stream.streamId] = stream; + //this.room.getStreams()[stream.streamId] = stream; + }; + Connection.prototype.removeStream = function (key) { + delete this.streams[key]; + //delete this.room.getStreams()[key]; + delete this.inboundStreamsOpts; + }; + Connection.prototype.setOptions = function (options) { + this.options = options; + }; + Connection.prototype.getStreams = function () { + return this.streams; + }; + Connection.prototype.dispose = function () { + for (var key in this.streams) { + this.streams[key].dispose(); + } + }; + Connection.prototype.sendIceCandidate = function (candidate) { + console.debug((this.local ? "Local" : "Remote"), "candidate for", this.connectionId, JSON.stringify(candidate)); + this.openVidu.sendRequest("onIceCandidate", { + endpointName: this.connectionId, + candidate: candidate.candidate, + sdpMid: candidate.sdpMid, + sdpMLineIndex: candidate.sdpMLineIndex + }, function (error, response) { + if (error) { + console.error("Error sending ICE candidate: " + + JSON.stringify(error)); + } + }); + }; + Connection.prototype.initRemoteStreams = function (options) { + var opts; + for (var _i = 0, _a = options.streams; _i < _a.length; _i++) { + opts = _a[_i]; + var streamOptions = { + id: opts.id, + connection: this, + recvAudio: (opts.audioActive == null ? true : opts.audioActive), + recvVideo: (opts.videoActive == null ? true : opts.videoActive), + typeOfVideo: opts.typeOfVideo, + }; + var stream = new Stream_1.Stream(this.openVidu, false, this.room, streamOptions); + this.addStream(stream); + this.inboundStreamsOpts = streamOptions; + } + console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + "] is now configured for receiving Streams with options: ", this.inboundStreamsOpts); + }; + return Connection; +}()); +exports.Connection = Connection; + +},{"./Stream":61}],57:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var LocalRecoderState; +(function (LocalRecoderState) { + LocalRecoderState["READY"] = "READY"; + LocalRecoderState["RECORDING"] = "RECORDING"; + LocalRecoderState["PAUSED"] = "PAUSED"; + LocalRecoderState["FINISHED"] = "FINISHED"; +})(LocalRecoderState = exports.LocalRecoderState || (exports.LocalRecoderState = {})); +var LocalRecorder = /** @class */ (function () { + function LocalRecorder(stream) { + this.chunks = []; + this.count = 0; + this.stream = stream; + this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection'; + this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord'; + this.state = "READY" /* READY */; + } + LocalRecorder.prototype.record = function () { + var _this = this; + if (typeof MediaRecorder === 'undefined') { + console.error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder'); + throw (Error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder')); + } + if (this.state !== "READY" /* READY */) { + throw (Error('\'LocalRecord.record()\' needs \'LocalRecord.state\' to be \'READY\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.clean()\' or init a new LocalRecorder before')); + } + console.log("Starting local recording of stream '" + this.stream.streamId + "' of connection '" + this.connectionId + "'"); + if (typeof MediaRecorder.isTypeSupported == 'function') { + var options = void 0; + if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) { + options = { mimeType: 'video/webm;codecs=vp9' }; + } + else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) { + options = { mimeType: 'video/webm;codecs=h264' }; + } + else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) { + options = { mimeType: 'video/webm;codecs=vp8' }; + } + console.log('Using mimeType ' + options.mimeType); + this.mediaRecorder = new MediaRecorder(this.stream.getMediaStream(), options); + } + else { + console.warn('isTypeSupported is not supported, using default codecs for browser'); + this.mediaRecorder = new MediaRecorder(this.stream.getMediaStream()); + } + this.mediaRecorder.start(10); + this.mediaRecorder.ondataavailable = function (e) { + _this.chunks.push(e.data); + }; + this.mediaRecorder.onerror = function (e) { + console.error('MediaRecorder error: ', e); + }; + this.mediaRecorder.onstart = function () { + console.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ")"); + }; + this.mediaRecorder.onstop = function () { + _this.onStopDefault(); + }; + this.mediaRecorder.onpause = function () { + console.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ")"); + }; + this.mediaRecorder.onresume = function () { + console.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ")"); + }; + this.mediaRecorder.onwarning = function (e) { + console.log('MediaRecorder warning: ' + e); + }; + this.state = "RECORDING" /* RECORDING */; + }; + LocalRecorder.prototype.stop = function () { + var _this = this; + return new Promise(function (resolve, reject) { + try { + if (_this.state === "READY" /* READY */ || _this.state === "FINISHED" /* 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(); + resolve(); + }; + } + catch (e) { + reject(e); + } + try { + _this.mediaRecorder.stop(); + } + catch (e) { + reject(e); + } + }); + }; + LocalRecorder.prototype.pause = function () { + if (this.state !== "RECORDING" /* RECORDING */) { + throw (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 = "PAUSED" /* PAUSED */; + }; + LocalRecorder.prototype.resume = function () { + if (this.state !== "PAUSED" /* PAUSED */) { + throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.pause()\' before')); + } + this.mediaRecorder.resume(); + this.state = "RECORDING" /* RECORDING */; + }; + LocalRecorder.prototype.preview = function (parentElement) { + if (this.state !== "FINISHED" /* 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 (typeof parentElement === "string") { + this.htmlParentElementId = parentElement; + var parentElementDom = document.getElementById(parentElement); + if (parentElementDom) { + this.videoPreview = parentElementDom.appendChild(this.videoPreview); + } + } + else { + this.htmlParentElementId = parentElement.id; + 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.count = 0; + delete _this.mediaRecorder; + _this.state = "READY" /* READY */; + }; + if (this.state === "RECORDING" /* RECORDING */ || this.state === "PAUSED" /* PAUSED */) { + this.stop().then(function () { return f(); }).catch(function () { return f(); }); + } + else { + f(); + } + }; + LocalRecorder.prototype.download = function () { + if (this.state !== "FINISHED" /* 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 + '.webm'; + a.click(); + window.URL.revokeObjectURL(url); + document.body.removeChild(a); + } + }; + LocalRecorder.prototype.getBlob = function () { + if (this.state !== "FINISHED" /* 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 !== "FINISHED" /* FINISHED */) { + 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') { + // Success response from server (HTTP status standard: 2XX is success) + resolve(http_1.responseText); + } + else { + reject(Error("Upload error: " + 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 !== "FINISHED" /* FINISHED */) { + 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 + ".webm"); + http_2.onreadystatechange = function () { + if (http_2.readyState === 4) { + if (http_2.status.toString().charAt(0) === '2') { + // Success response from server (HTTP status standard: 2XX is success) + resolve(http_2.responseText); + } + else { + reject(Error("Upload error: " + http_2.status)); + } + } + }; + http_2.send(sendable); + } + }); + }; + LocalRecorder.prototype.onStopDefault = function () { + console.log('MediaRecorder stopped (state=' + this.mediaRecorder.state + ")"); + this.blob = new Blob(this.chunks, { type: "video/webm" }); + this.chunks = []; + this.videoPreviewSrc = window.URL.createObjectURL(this.blob); + this.state = "FINISHED" /* FINISHED */; + }; + return LocalRecorder; +}()); +exports.LocalRecorder = LocalRecorder; + +},{}],58:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var OpenViduErrorName; +(function (OpenViduErrorName) { + OpenViduErrorName["BROWSER_NOT_SUPPORTED"] = "BROWSER_NOT_SUPPORTED"; + OpenViduErrorName["CAMERA_ACCESS_DENIED"] = "CAMERA_ACCESS_DENIED"; + OpenViduErrorName["MICROPHONE_ACCESS_DENIED"] = "MICROPHONE_ACCESS_DENIED"; + OpenViduErrorName["SCREEN_CAPTURE_DENIED"] = "SCREEN_CAPTURE_DENIED"; + OpenViduErrorName["NO_VIDEO_DEVICE"] = "NO_VIDEO_DEVICE"; + OpenViduErrorName["NO_INPUT_DEVICE"] = "NO_INPUT_DEVICE"; + OpenViduErrorName["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED"; + OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED"; + OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR"; +})(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {})); +var OpenViduError = /** @class */ (function () { + function OpenViduError(name, message) { + this.name = name; + this.message = message; + } + return OpenViduError; +}()); +exports.OpenViduError = OpenViduError; + +},{}],59:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/* + * (C) Copyright 2017 OpenVidu (http://openvidu.io/) + * + * 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. + * + */ +var SessionInternal_1 = require("./SessionInternal"); +var OpenViduError_1 = require("./OpenViduError"); +var Stream_1 = require("./Stream"); +var RpcBuilder = require("../KurentoUtils/kurento-jsonrpc"); +var OpenViduInternal = /** @class */ (function () { + function OpenViduInternal() { + this.recorder = false; + } + /* NEW METHODS */ + OpenViduInternal.prototype.initSession = function (sessionId) { + console.info("'Session' initialized with 'sessionId' [" + sessionId + "]"); + this.session = new SessionInternal_1.SessionInternal(this, sessionId); + return this.session; + }; + OpenViduInternal.prototype.initPublisherTagged = function (parentId, cameraOptions, newStream, callback) { + var _this = this; + if (newStream) { + if (cameraOptions == null) { + cameraOptions = { + sendAudio: true, + sendVideo: true, + activeAudio: true, + activeVideo: true, + dataChannel: true, + mediaConstraints: { + audio: true, + video: { width: { ideal: 1280 } } + } + }; + } + this.localStream = new Stream_1.Stream(this, true, this.session, cameraOptions); + } + this.localStream.requestCameraAccess(function (error, localStream) { + if (error) { + // Neither localStream or microphone device is allowed/able to capture media + console.error(error); + if (callback) { + callback(error); + } + _this.localStream.ee.emitEvent('access-denied-by-publisher'); + } + else { + _this.localStream.setVideoElement(_this.cameraReady(localStream, parentId)); + if (callback) { + callback(undefined); + } + } + }); + return this.localStream; + }; + OpenViduInternal.prototype.initPublisherScreen = function (parentId, newStream, callback) { + var _this = this; + if (newStream) { + this.localStream = new Stream_1.Stream(this, true, this.session, 'screen-options'); + } + this.localStream.addOnceEventListener('can-request-screen', function () { + _this.localStream.requestCameraAccess(function (error, localStream) { + if (error) { + _this.localStream.ee.emitEvent('access-denied-by-publisher'); + var errorName = "SCREEN_CAPTURE_DENIED" /* SCREEN_CAPTURE_DENIED */; + var errorMessage = 'You must allow access to one window of your desktop'; + var e = new OpenViduError_1.OpenViduError(errorName, errorMessage); + console.error(e); + if (callback) { + callback(e); + } + } + else { + _this.localStream.setVideoElement(_this.cameraReady(localStream, parentId)); + if (_this.localStream.getSendAudio()) { + // If the user wants to send audio with the screen capturing + navigator.mediaDevices.getUserMedia({ audio: true, video: false }) + .then(function (userStream) { + _this.localStream.getMediaStream().addTrack(userStream.getAudioTracks()[0]); + // Mute audio if 'activeAudio' property is false + if (userStream.getAudioTracks()[0] != null) { + userStream.getAudioTracks()[0].enabled = _this.localStream.outboundOptions.activeAudio; + } + _this.localStream.isScreenRequestedReady = true; + _this.localStream.ee.emitEvent('screen-ready'); + if (callback) { + callback(undefined); + } + }) + .catch(function (error) { + _this.localStream.ee.emitEvent('access-denied-by-publisher'); + console.error("Error accessing the microphone", error); + if (callback) { + var errorName = "MICROPHONE_ACCESS_DENIED" /* MICROPHONE_ACCESS_DENIED */; + var errorMessage = error.toString(); + callback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + } + }); + } + else { + _this.localStream.isScreenRequestedReady = true; + _this.localStream.ee.emitEvent('screen-ready'); + if (callback) { + callback(undefined); + } + } + } + }); + }); + return this.localStream; + }; + OpenViduInternal.prototype.cameraReady = function (localStream, parentId) { + this.localStream = localStream; + var videoElement = this.localStream.playOnlyVideo(parentId, null); + this.localStream.emitStreamReadyEvent(); + return videoElement; + }; + OpenViduInternal.prototype.getLocalStream = function () { + return this.localStream; + }; + /* NEW METHODS */ + OpenViduInternal.prototype.getWsUri = function () { + return this.wsUri; + }; + OpenViduInternal.prototype.setWsUri = function (wsUri) { + this.wsUri = wsUri; + }; + OpenViduInternal.prototype.getSecret = function () { + return this.secret; + }; + OpenViduInternal.prototype.setSecret = function (secret) { + this.secret = secret; + }; + OpenViduInternal.prototype.getRecorder = function () { + return this.recorder; + }; + OpenViduInternal.prototype.setRecorder = function (recorder) { + this.recorder = recorder; + }; + OpenViduInternal.prototype.getOpenViduServerURL = function () { + return 'https://' + this.wsUri.split("wss://")[1].split("/room")[0]; + }; + OpenViduInternal.prototype.getRoom = function () { + return this.session; + }; + OpenViduInternal.prototype.connect = function (callback) { + this.callback = callback; + this.initJsonRpcClient(this.wsUri); + }; + OpenViduInternal.prototype.initJsonRpcClient = function (wsUri) { + var config = { + heartbeat: 3000, + sendCloseMessage: false, + ws: { + uri: wsUri, + useSockJS: false, + onconnected: this.connectCallback.bind(this), + ondisconnect: this.disconnectCallback.bind(this), + onreconnecting: this.reconnectingCallback.bind(this), + onreconnected: this.reconnectedCallback.bind(this) + }, + rpc: { + requestTimeout: 15000, + //notifications + participantJoined: this.onParticipantJoined.bind(this), + participantPublished: this.onParticipantPublished.bind(this), + participantUnpublished: this.onParticipantUnpublished.bind(this), + participantLeft: this.onParticipantLeft.bind(this), + participantEvicted: this.onParticipantEvicted.bind(this), + sendMessage: this.onNewMessage.bind(this), + iceCandidate: this.iceCandidateEvent.bind(this), + mediaError: this.onMediaError.bind(this), + } + }; + this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config); + }; + OpenViduInternal.prototype.connectCallback = function (error) { + if (error) { + this.callback(error); + } + else { + this.callback(null); + } + }; + OpenViduInternal.prototype.isRoomAvailable = function () { + if (this.session !== undefined && this.session instanceof SessionInternal_1.SessionInternal) { + return true; + } + else { + console.warn('Session instance not found'); + return false; + } + }; + OpenViduInternal.prototype.disconnectCallback = function () { + console.warn('Websocket connection lost'); + if (this.isRoomAvailable()) { + this.session.onLostConnection(); + } + else { + alert('Connection error. Please reload page.'); + } + }; + OpenViduInternal.prototype.reconnectingCallback = function () { + console.warn('Websocket connection lost (reconnecting)'); + if (this.isRoomAvailable()) { + this.session.onLostConnection(); + } + else { + alert('Connection error. Please reload page.'); + } + }; + OpenViduInternal.prototype.reconnectedCallback = function () { + console.warn('Websocket reconnected'); + }; + OpenViduInternal.prototype.onParticipantJoined = function (params) { + if (this.isRoomAvailable()) { + this.session.onParticipantJoined(params); + } + }; + OpenViduInternal.prototype.onParticipantPublished = function (params) { + if (this.isRoomAvailable()) { + this.session.onParticipantPublished(params); + } + }; + OpenViduInternal.prototype.onParticipantUnpublished = function (params) { + if (this.isRoomAvailable()) { + this.session.onParticipantUnpublished(params); + } + }; + OpenViduInternal.prototype.onParticipantLeft = function (params) { + if (this.isRoomAvailable()) { + this.session.onParticipantLeft(params); + } + }; + OpenViduInternal.prototype.onParticipantEvicted = function (params) { + if (this.isRoomAvailable()) { + this.session.onParticipantEvicted(params); + } + }; + OpenViduInternal.prototype.onNewMessage = function (params) { + if (this.isRoomAvailable()) { + this.session.onNewMessage(params); + } + }; + OpenViduInternal.prototype.iceCandidateEvent = function (params) { + if (this.isRoomAvailable()) { + this.session.recvIceCandidate(params); + } + }; + OpenViduInternal.prototype.onRoomClosed = function (params) { + if (this.isRoomAvailable()) { + this.session.onRoomClosed(params); + } + }; + OpenViduInternal.prototype.onMediaError = function (params) { + if (this.isRoomAvailable()) { + this.session.onMediaError(params); + } + }; + OpenViduInternal.prototype.setRpcParams = function (params) { + this.rpcParams = params; + }; + OpenViduInternal.prototype.sendRequest = function (method, params, callback) { + if (params && params instanceof Function) { + callback = params; + params = undefined; + } + params = params || {}; + if (this.rpcParams && this.rpcParams !== null && this.rpcParams !== undefined) { + for (var index in this.rpcParams) { + if (this.rpcParams.hasOwnProperty(index)) { + params[index] = this.rpcParams[index]; + console.debug('RPC param added to request {' + index + ': ' + this.rpcParams[index] + '}'); + } + } + } + console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}'); + this.jsonRpcClient.send(method, params, callback); + }; + OpenViduInternal.prototype.close = function (forced) { + if (this.isRoomAvailable()) { + this.session.leave(forced, this.jsonRpcClient); + } + }; + ; + OpenViduInternal.prototype.disconnectParticipant = function (stream) { + if (this.isRoomAvailable()) { + this.session.disconnect(stream); + } + }; + //CHAT + OpenViduInternal.prototype.sendMessage = function (message) { + this.sendRequest('sendMessage', { + message: message + }, function (error, response) { + if (error) { + console.error(error); + } + }); + }; + ; + OpenViduInternal.prototype.generateMediaConstraints = function (cameraOptions) { + var mediaConstraints = { + audio: cameraOptions.audio, + video: {} + }; + if (!cameraOptions.video) { + mediaConstraints.video = false; + } + else { + var w = void 0, h = void 0; + switch (cameraOptions.quality) { + case 'LOW': + w = 320; + h = 240; + break; + case 'MEDIUM': + w = 640; + h = 480; + break; + case 'HIGH': + w = 1280; + h = 720; + break; + default: + w = 640; + h = 480; + } + mediaConstraints.video['width'] = { exact: w }; + mediaConstraints.video['height'] = { exact: h }; + //mediaConstraints.video['frameRate'] = { ideal: Number((document.getElementById('frameRate')).value) }; + } + return mediaConstraints; + }; + return OpenViduInternal; +}()); +exports.OpenViduInternal = OpenViduInternal; + +},{"../KurentoUtils/kurento-jsonrpc":45,"./OpenViduError":58,"./SessionInternal":60,"./Stream":61}],60:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Connection_1 = require("./Connection"); +var EventEmitter = require("wolfy87-eventemitter"); +var SECRET_PARAM = '?secret='; +var RECORDER_PARAM = '&recorder='; +var SessionInternal = /** @class */ (function () { + function SessionInternal(openVidu, sessionId) { + this.openVidu = openVidu; + this.ee = new EventEmitter(); + this.remoteStreams = {}; + this.participants = {}; + this.publishersSpeaking = []; + this.connected = false; + this.sessionId = this.getUrlWithoutSecret(sessionId); + this.localParticipant = new Connection_1.Connection(this.openVidu, true, this); + if (!this.openVidu.getWsUri() && !!sessionId) { + this.processOpenViduUrl(sessionId); + } + } + SessionInternal.prototype.processOpenViduUrl = function (url) { + var secret = this.getSecretFromUrl(url); + var recorder = this.getRecorderFromUrl(url); + if (!(secret == null)) { + this.openVidu.setSecret(secret); + } + if (!(recorder == null)) { + this.openVidu.setRecorder(recorder); + } + this.openVidu.setWsUri(this.getFinalUrl(url)); + }; + SessionInternal.prototype.getSecretFromUrl = function (url) { + var secret = ''; + if (url.indexOf(SECRET_PARAM) !== -1) { + var endOfSecret = url.lastIndexOf(RECORDER_PARAM); + if (endOfSecret !== -1) { + secret = url.substring(url.lastIndexOf(SECRET_PARAM) + SECRET_PARAM.length, endOfSecret); + } + else { + secret = url.substring(url.lastIndexOf(SECRET_PARAM) + SECRET_PARAM.length, url.length); + } + } + return secret; + }; + SessionInternal.prototype.getRecorderFromUrl = function (url) { + var recorder = ''; + if (url.indexOf(RECORDER_PARAM) !== -1) { + recorder = url.substring(url.lastIndexOf(RECORDER_PARAM) + RECORDER_PARAM.length, url.length); + } + return new Boolean(recorder).valueOf(); + ; + }; + SessionInternal.prototype.getUrlWithoutSecret = function (url) { + if (!url) { + console.error('sessionId is not defined'); + } + if (url.indexOf(SECRET_PARAM) !== -1) { + url = url.substring(0, url.lastIndexOf(SECRET_PARAM)); + } + return url; + }; + SessionInternal.prototype.getFinalUrl = function (url) { + url = this.getUrlWithoutSecret(url).substring(0, url.lastIndexOf('/')) + '/room'; + if (url.indexOf(".ngrok.io") !== -1) { + // OpenVidu server URL referes to a ngrok IP: secure wss protocol and delete port of URL + url = url.replace("ws://", "wss://"); + var regex = /\.ngrok\.io:\d+/; + url = url.replace(regex, ".ngrok.io"); + } + else if ((url.indexOf("localhost") !== -1) || (url.indexOf("127.0.0.1") != -1)) { + // OpenVidu server URL referes to localhost IP + } + return url; + }; + /* NEW METHODS */ + SessionInternal.prototype.connect = function (token, callback) { + var _this = this; + this.openVidu.connect(function (error) { + if (error) { + callback('ERROR CONNECTING TO OPENVIDU'); + } + else { + if (!token) { + token = _this.randomToken(); + } + var joinParams = { + token: token, + session: _this.sessionId, + metadata: _this.options.metadata, + secret: _this.openVidu.getSecret(), + recorder: _this.openVidu.getRecorder(), + dataChannels: false + }; + if (_this.localParticipant) { + if (Object.keys(_this.localParticipant.getStreams()).some(function (streamId) { + return _this.remoteStreams[streamId].isDataChannelEnabled(); + })) { + joinParams.dataChannels = true; + } + } + _this.openVidu.sendRequest('joinRoom', joinParams, function (error, response) { + if (error) { + callback(error); + } + else { + _this.connected = true; + var exParticipants = response.value; + // IMPORTANT: Update connectionId with value send by server + _this.localParticipant.connectionId = response.id; + _this.participants[response.id] = _this.localParticipant; + var roomEvent = { + participants: new Array(), + streams: new Array() + }; + var length_1 = exParticipants.length; + for (var i = 0; i < length_1; i++) { + var connection = new Connection_1.Connection(_this.openVidu, false, _this, exParticipants[i]); + connection.creationTime = new Date().getTime(); + _this.participants[connection.connectionId] = connection; + roomEvent.participants.push(connection); + var streams = connection.getStreams(); + for (var key in streams) { + roomEvent.streams.push(streams[key]); + if (_this.subscribeToStreams) { + streams[key].subscribe(); + } + } + } + // Update local Connection object properties with values returned by server + _this.localParticipant.data = response.metadata; + _this.localParticipant.creationTime = new Date().getTime(); + // Updates the value of property 'connection' in Session object + _this.ee.emitEvent('update-connection-object', [{ connection: _this.localParticipant }]); + // Own connection created event + _this.ee.emitEvent('connectionCreated', [{ connection: _this.localParticipant }]); + // One connection created event for each existing connection in the session + for (var _i = 0, _a = roomEvent.participants; _i < _a.length; _i++) { + var part = _a[_i]; + _this.ee.emitEvent('connectionCreated', [{ connection: part }]); + } + //if (this.subscribeToStreams) { + for (var _b = 0, _c = roomEvent.streams; _b < _c.length; _b++) { + var stream = _c[_b]; + _this.ee.emitEvent('streamCreated', [{ stream: stream }]); + // Store the remote stream + _this.remoteStreams[stream.streamId] = stream; + } + callback(undefined); + } + }); + } + }); + }; + /* NEW METHODS */ + SessionInternal.prototype.configure = function (options) { + this.options = options; + this.id = options.sessionId; + this.subscribeToStreams = options.subscribeToStreams == null ? true : options.subscribeToStreams; + this.updateSpeakerInterval = options.updateSpeakerInterval || 1500; + this.thresholdSpeaker = options.thresholdSpeaker || -50; + this.activateUpdateMainSpeaker(); + if (!this.openVidu.getWsUri()) { + this.processOpenViduUrl(options.sessionId); + } + }; + SessionInternal.prototype.getId = function () { + return this.id; + }; + SessionInternal.prototype.getSessionId = function () { + return this.sessionId; + }; + SessionInternal.prototype.activateUpdateMainSpeaker = function () { + /*setInterval(() => { + if (this.publishersSpeaking.length > 0) { + this.ee.emitEvent('publisherStartSpeaking', [{ + participantId: this.publishersSpeaking[this.publishersSpeaking.length - 1] + }]); + } + }, this.updateSpeakerInterval);*/ + }; + SessionInternal.prototype.getLocalParticipant = function () { + return this.localParticipant; + }; + SessionInternal.prototype.addEventListener = function (eventName, listener) { + this.ee.on(eventName, listener); + }; + SessionInternal.prototype.addOnceEventListener = function (eventName, listener) { + this.ee.once(eventName, listener); + }; + SessionInternal.prototype.removeListener = function (eventName, listener) { + this.ee.off(eventName, listener); + }; + SessionInternal.prototype.removeEvent = function (eventName) { + this.ee.removeEvent(eventName); + }; + SessionInternal.prototype.emitEvent = function (eventName, eventsArray) { + this.ee.emitEvent(eventName, eventsArray); + }; + SessionInternal.prototype.subscribe = function (stream) { + stream.subscribe(); + }; + SessionInternal.prototype.unsubscribe = function (stream) { + console.info("Unsubscribing from " + stream.connection.connectionId); + this.openVidu.sendRequest('unsubscribeFromVideo', { + sender: stream.connection.connectionId + }, function (error, response) { + if (error) { + console.error("Error unsubscribing from Subscriber", error); + } + else { + console.info("Unsubscribed correctly from " + stream.connection.connectionId); + } + stream.dispose(); + }); + }; + SessionInternal.prototype.onParticipantPublished = function (response) { + // Get the existing Connection created on 'onParticipantJoined' for + // existing participants or create a new one for new participants + var connection = this.participants[response.id]; + if (connection != null) { + // Update existing Connection + response.metadata = connection.data; + connection.setOptions(response); + connection.initRemoteStreams(response); + } + else { + // Create new Connection + connection = new Connection_1.Connection(this.openVidu, false, this, response); + } + var pid = connection.connectionId; + if (!(pid in this.participants)) { + console.debug("Remote Connection not found in connections list by its id [" + pid + "]"); + } + else { + console.debug("Remote Connection found in connections list by its id [" + pid + "]"); + } + this.participants[pid] = connection; + var streams = connection.getStreams(); + for (var key in streams) { + var stream = streams[key]; + if (!this.remoteStreams[stream.streamId]) { + // Avoid race condition between stream.subscribe() in "onParticipantPublished" and in "joinRoom" rpc callback + // This condition is false if openvidu-server sends "participantPublished" event to a subscriber participant that has + // already subscribed to certain stream in the callback of "joinRoom" method + if (this.subscribeToStreams) { + stream.subscribe(); + } + this.ee.emitEvent('streamCreated', [{ stream: stream }]); + // Store the remote stream + this.remoteStreams[stream.streamId] = stream; + } + } + }; + SessionInternal.prototype.onParticipantUnpublished = function (msg) { + var _this = this; + var connection = this.participants[msg.name]; + if (connection !== undefined) { + var streams = connection.getStreams(); + for (var key in streams) { + this.ee.emitEvent('streamDestroyed', [{ + stream: streams[key], + preventDefault: function () { _this.ee.removeEvent('stream-destroyed-default'); } + }]); + this.ee.emitEvent('stream-destroyed-default', [{ + stream: streams[key] + }]); + // Deleting the remote stream + var streamId = streams[key].streamId; + var stream = this.remoteStreams[streamId]; + stream.dispose(); + delete this.remoteStreams[stream.streamId]; + connection.removeStream(stream.streamId); + } + } + else { + console.warn("Participant " + msg.name + + " unknown. Participants: " + + JSON.stringify(this.participants)); + } + }; + SessionInternal.prototype.onParticipantJoined = function (response) { + var connection = new Connection_1.Connection(this.openVidu, false, this, response); + connection.creationTime = new Date().getTime(); + var pid = connection.connectionId; + if (!(pid in this.participants)) { + this.participants[pid] = connection; + } + else { + //use existing so that we don't lose streams info + console.warn("Connection already exists in connections list with " + + "the same connectionId, old:", this.participants[pid], ", joined now:", connection); + connection = this.participants[pid]; + } + this.ee.emitEvent('participant-joined', [{ + connection: connection + }]); + this.ee.emitEvent('connectionCreated', [{ + connection: connection + }]); + }; + SessionInternal.prototype.onParticipantLeft = function (msg) { + var _this = this; + var connection = this.participants[msg.name]; + if (connection !== undefined) { + this.ee.emitEvent('participant-left', [{ + connection: connection + }]); + var streams = connection.getStreams(); + for (var key in streams) { + this.ee.emitEvent('streamDestroyed', [{ + stream: streams[key], + preventDefault: function () { _this.ee.removeEvent('stream-destroyed-default'); } + }]); + this.ee.emitEvent('stream-destroyed-default', [{ + stream: streams[key] + }]); + // Deleting the remote stream + var streamId = streams[key].streamId; + delete this.remoteStreams[streamId]; + } + connection.dispose(); + delete this.participants[msg.name]; + this.ee.emitEvent('connectionDestroyed', [{ + connection: connection + }]); + } + else { + console.warn("Participant " + msg.name + + " unknown. Participants: " + + JSON.stringify(this.participants)); + } + }; + ; + SessionInternal.prototype.onParticipantEvicted = function (msg) { + this.ee.emitEvent('participant-evicted', [{ + localParticipant: this.localParticipant + }]); + }; + ; + SessionInternal.prototype.onNewMessage = function (msg) { + console.info("New signal: " + JSON.stringify(msg)); + this.ee.emitEvent('signal', [{ + data: msg.data, + from: this.participants[msg.from], + type: msg.type + }]); + this.ee.emitEvent('signal:' + msg.type, [{ + data: msg.data, + from: this.participants[msg.from], + type: msg.type + }]); + }; + SessionInternal.prototype.recvIceCandidate = function (msg) { + var candidate = { + candidate: msg.candidate, + sdpMid: msg.sdpMid, + sdpMLineIndex: msg.sdpMLineIndex + }; + var connection = this.participants[msg.endpointName]; + if (!connection) { + console.error("Participant not found for endpoint " + + msg.endpointName + ". Ice candidate will be ignored.", candidate); + return; + } + var streams = connection.getStreams(); + var _loop_1 = function (key) { + var stream = streams[key]; + stream.getWebRtcPeer().addIceCandidate(candidate, function (error) { + if (error) { + console.error("Error adding candidate for " + key + + " stream of endpoint " + msg.endpointName + + ": " + error); + } + }); + }; + for (var key in streams) { + _loop_1(key); + } + }; + SessionInternal.prototype.onRoomClosed = function (msg) { + console.info("Session closed: " + JSON.stringify(msg)); + var room = msg.room; + if (room !== undefined) { + this.ee.emitEvent('room-closed', [{ + room: room + }]); + } + else { + console.warn("Session undefined on session closed", msg); + } + }; + SessionInternal.prototype.onLostConnection = function () { + if (!this.connected) { + console.warn('Not connected to session: if you are not debugging, this is probably a certificate error'); + if (window.confirm('If you are not debugging, this is probably a certificate error at \"' + this.openVidu.getOpenViduServerURL() + '\"\n\nClick OK to navigate and accept it')) { + location.assign(this.openVidu.getOpenViduServerURL() + '/accept-certificate'); + } + ; + return; + } + console.warn('Lost connection in Session ' + this.id); + var room = this.id; + if (room !== undefined) { + this.ee.emitEvent('lost-connection', [{ room: room }]); + } + else { + console.warn('Session undefined when lost connection'); + } + }; + SessionInternal.prototype.onMediaError = function (params) { + console.error("Media error: " + JSON.stringify(params)); + var error = params.error; + if (error) { + this.ee.emitEvent('error-media', [{ + error: error + }]); + } + else { + console.warn("Received undefined media error. Params:", params); + } + }; + /* + * forced means the user was evicted, no need to send the 'leaveRoom' request + */ + SessionInternal.prototype.leave = function (forced, jsonRpcClient) { + forced = !!forced; + console.info("Leaving Session (forced=" + forced + ")"); + if (this.connected && !forced) { + this.openVidu.sendRequest('leaveRoom', function (error, response) { + if (error) { + console.error(error); + } + jsonRpcClient.close(); + }); + } + else { + jsonRpcClient.close(); + } + this.connected = false; + if (this.participants) { + for (var pid in this.participants) { + this.participants[pid].dispose(); + delete this.participants[pid]; + } + } + }; + SessionInternal.prototype.disconnect = function (stream) { + var connection = stream.getParticipant(); + if (!connection) { + console.error("Stream to disconnect has no participant", stream); + return; + } + delete this.participants[connection.connectionId]; + connection.dispose(); + if (connection === this.localParticipant) { + console.info("Unpublishing my media (I'm " + connection.connectionId + ")"); + delete this.localParticipant; + this.openVidu.sendRequest('unpublishVideo', function (error, response) { + if (error) { + console.error(error); + } + else { + console.info("Media unpublished correctly"); + } + }); + } + else { + this.unsubscribe(stream); + } + }; + SessionInternal.prototype.unpublish = function (publisher) { + var _this = this; + var stream = publisher.stream; + if (!stream.connection) { + console.error("The associated Connection object of this Publisher is null", stream); + return; + } + else if (stream.connection !== this.localParticipant) { + console.error("The associated Connection object of this Publisher is not your local Connection." + + "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method", stream); + return; + } + else { + stream.dispose(); + console.info("Unpublishing local media (" + stream.connection.connectionId + ")"); + this.openVidu.sendRequest('unpublishVideo', function (error, response) { + if (error) { + console.error(error); + } + else { + console.info("Media unpublished correctly"); + } + }); + stream.isReadyToPublish = false; + stream.isScreenRequestedReady = false; + delete stream.connection.getStreams()[stream.streamId]; + publisher.ee.emitEvent('streamDestroyed', [{ + stream: publisher.stream, + preventDefault: function () { _this.ee.removeEvent('stream-destroyed-default'); } + }]); + publisher.ee.emitEvent('stream-destroyed-default', [{ + stream: publisher.stream + }]); + } + }; + SessionInternal.prototype.getRemoteStreams = function () { + return this.remoteStreams; + }; + SessionInternal.prototype.addParticipantSpeaking = function (participantId) { + this.publishersSpeaking.push(participantId); + this.ee.emitEvent('publisherStartSpeaking', [{ + participantId: participantId + }]); + }; + SessionInternal.prototype.removeParticipantSpeaking = function (participantId) { + var pos = -1; + for (var i = 0; i < this.publishersSpeaking.length; i++) { + if (this.publishersSpeaking[i] == participantId) { + pos = i; + break; + } + } + if (pos != -1) { + this.publishersSpeaking.splice(pos, 1); + this.ee.emitEvent('publisherStopSpeaking', [{ + participantId: participantId + }]); + } + }; + SessionInternal.prototype.stringClientMetadata = function (metadata) { + if (!(typeof metadata === 'string')) { + return JSON.stringify(metadata); + } + else { + return metadata; + } + }; + SessionInternal.prototype.randomToken = function () { + return Math.random().toString(36).slice(2) + Math.random().toString(36).slice(2); + }; + return SessionInternal; +}()); +exports.SessionInternal = SessionInternal; + +},{"./Connection":56,"wolfy87-eventemitter":38}],61:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var OpenViduError_1 = require("./OpenViduError"); +var WebRtcStats_1 = require("./WebRtcStats"); +var EventEmitter = require("wolfy87-eventemitter"); +var kurentoUtils = require("../KurentoUtils/kurento-utils-js"); +var adapter = require("webrtc-adapter"); +if (window) { + window["adapter"] = adapter; +} +function jq(id) { + return id.replace(/(@|:|\.|\[|\]|,)/g, "\\$1"); +} +function show(id) { + document.getElementById(jq(id)).style.display = 'block'; +} +function hide(id) { + document.getElementById(jq(id)).style.display = 'none'; +} +var Stream = /** @class */ (function () { + function Stream(openVidu, local, room, options) { + var _this = this; + this.openVidu = openVidu; + this.local = local; + this.room = room; + this.ee = new EventEmitter(); + this.showMyRemote = false; + this.localMirrored = false; + this.chanId = 0; + this.dataChannelOpened = false; + this.isReadyToPublish = false; + this.isPublisherPublished = false; + this.isVideoELementCreated = false; + this.accessIsAllowed = false; + this.accessIsDenied = false; + this.isScreenRequestedReady = false; + this.isScreenRequested = false; + if (options !== 'screen-options') { + // Outbound stream (not screen share) or Inbound stream + if ('id' in options) { + this.inboundOptions = options; + } + else { + this.outboundOptions = options; + } + this.streamId = (options.id != null) ? options.id : ((options.sendVideo) ? "CAMERA" : "MICRO"); + this.typeOfVideo = (options.typeOfVideo != null) ? options.typeOfVideo : ''; + if ('recvAudio' in options) { + // Set Connection for an Inbound stream (for Outbound streams will be set on Session.Publish(Publisher)) + this.connection = options.connection; + } + } + else { + // Outbound stream for screen share + this.isScreenRequested = true; + this.typeOfVideo = 'SCREEN'; + } + this.addEventListener('mediastream-updated', function () { + if (_this.video) + _this.video.srcObject = _this.mediaStream; + console.debug("Video srcObject [" + _this.mediaStream + "] added to stream [" + _this.streamId + "]"); + }); + } + Stream.prototype.emitStreamReadyEvent = function () { + this.ee.emitEvent('stream-ready'); + }; + Stream.prototype.removeVideo = function (parentElement) { + if (this.video) { + if (typeof parentElement === "string") { + document.getElementById(parentElement).removeChild(this.video); + this.ee.emitEvent('video-removed'); + } + else if (parentElement instanceof Element) { + parentElement.removeChild(this.video); + this.ee.emitEvent('video-removed'); + } + else if (!parentElement) { + if (document.getElementById(this.parentId)) { + document.getElementById(this.parentId).removeChild(this.video); + this.ee.emitEvent('video-removed'); + } + } + delete this.video; + } + }; + Stream.prototype.getVideoElement = function () { + return this.video; + }; + Stream.prototype.setVideoElement = function (video) { + if (!!video) + this.video = video; + }; + Stream.prototype.getParentId = function () { + return this.parentId; + }; + Stream.prototype.getRecvVideo = function () { + return this.inboundOptions.recvVideo; + }; + Stream.prototype.getRecvAudio = function () { + return this.inboundOptions.recvAudio; + }; + Stream.prototype.getSendVideo = function () { + return this.outboundOptions.sendVideo; + }; + Stream.prototype.getSendAudio = function () { + return this.outboundOptions.sendAudio; + }; + Stream.prototype.subscribeToMyRemote = function () { + this.showMyRemote = true; + }; + Stream.prototype.displayMyRemote = function () { + return this.showMyRemote; + }; + Stream.prototype.mirrorLocalStream = function (wr) { + this.showMyRemote = true; + this.localMirrored = true; + if (wr) { + this.mediaStream = wr; + this.ee.emitEvent('mediastream-updated'); + } + }; + Stream.prototype.isLocalMirrored = function () { + return this.localMirrored; + }; + Stream.prototype.getChannelName = function () { + return this.streamId + '_' + this.chanId++; + }; + Stream.prototype.isDataChannelEnabled = function () { + return this.outboundOptions.dataChannel; + }; + Stream.prototype.isDataChannelOpened = function () { + return this.dataChannelOpened; + }; + Stream.prototype.onDataChannelOpen = function (event) { + console.debug('Data channel is opened'); + this.dataChannelOpened = true; + }; + Stream.prototype.onDataChannelClosed = function (event) { + console.debug('Data channel is closed'); + this.dataChannelOpened = false; + }; + Stream.prototype.sendData = function (data) { + if (this.wp === undefined) { + throw new Error('WebRTC peer has not been created yet'); + } + if (!this.dataChannelOpened) { + throw new Error('Data channel is not opened'); + } + console.info("Sending through data channel: " + data); + this.wp.send(data); + }; + Stream.prototype.getMediaStream = function () { + return this.mediaStream; + }; + Stream.prototype.getWebRtcPeer = function () { + return this.wp; + }; + Stream.prototype.getRTCPeerConnection = function () { + return this.wp.peerConnection; + }; + Stream.prototype.addEventListener = function (eventName, listener) { + this.ee.addListener(eventName, listener); + }; + Stream.prototype.addOnceEventListener = function (eventName, listener) { + this.ee.addOnceListener(eventName, listener); + }; + Stream.prototype.removeListener = function (eventName) { + this.ee.removeAllListeners(eventName); + }; + Stream.prototype.showSpinner = function (spinnerParentId) { + var progress = document.createElement('div'); + progress.id = 'progress-' + this.streamId; + progress.style.background = "center transparent url('img/spinner.gif') no-repeat"; + var spinnerParent = document.getElementById(spinnerParentId); + if (spinnerParent) { + spinnerParent.appendChild(progress); + } + }; + Stream.prototype.hideSpinner = function (spinnerId) { + spinnerId = (spinnerId === undefined) ? this.streamId : spinnerId; + hide('progress-' + spinnerId); + }; + Stream.prototype.playOnlyVideo = function (parentElement, thumbnailId) { + var _this = this; + if (!!parentElement) { + this.video = document.createElement('video'); + this.video.id = (this.local ? 'local-' : 'remote-') + 'video-' + this.streamId; + this.video.autoplay = true; + this.video.controls = false; + this.ee.emitEvent('mediastream-updated'); + if (this.local && !this.displayMyRemote()) { + this.video.muted = true; + this.video.oncanplay = function () { + console.info("Local 'Stream' with id [" + _this.streamId + "] video is now playing"); + _this.ee.emitEvent('video-is-playing', [{ + element: _this.video + }]); + }; + } + else { + this.video.title = this.streamId; + } + if (typeof parentElement === "string") { + this.parentId = parentElement; + var parentElementDom = document.getElementById(parentElement); + if (parentElementDom) { + this.video = parentElementDom.appendChild(this.video); + this.ee.emitEvent('video-element-created-by-stream', [{ + element: this.video + }]); + this.isVideoELementCreated = true; + } + } + else { + this.parentId = parentElement.id; + this.video = parentElement.appendChild(this.video); + } + this.isReadyToPublish = true; + return this.video; + } + return null; + }; + Stream.prototype.playThumbnail = function (thumbnailId) { + var container = document.createElement('div'); + container.className = "participant"; + container.id = this.streamId; + var thumbnail = document.getElementById(thumbnailId); + if (thumbnail) { + thumbnail.appendChild(container); + } + var name = document.createElement('div'); + container.appendChild(name); + var userName = this.streamId.replace('_webcam', ''); + if (userName.length >= 16) { + userName = userName.substring(0, 16) + "..."; + } + name.appendChild(document.createTextNode(userName)); + name.id = "name-" + this.streamId; + name.className = "name"; + name.title = this.streamId; + this.showSpinner(thumbnailId); + return this.playOnlyVideo(container, thumbnailId); + }; + Stream.prototype.getParticipant = function () { + return this.connection; + }; + Stream.prototype.requestCameraAccess = function (callback) { + var _this = this; + var constraints = this.outboundOptions.mediaConstraints; + /*let constraints2 = { + audio: true, + video: { + width: { + ideal: 1280 + }, + frameRate: { + ideal: 15 + } + } + };*/ + this.userMediaHasVideo(function (hasVideo) { + if (!hasVideo) { + if (_this.outboundOptions.sendVideo) { + callback(new OpenViduError_1.OpenViduError("NO_VIDEO_DEVICE" /* NO_VIDEO_DEVICE */, 'You have requested camera access but there is no video input device available. Trying to connect with an audio input device only'), _this); + } + if (!_this.outboundOptions.sendAudio) { + callback(new OpenViduError_1.OpenViduError("NO_INPUT_DEVICE" /* NO_INPUT_DEVICE */, 'You must init Publisher object with audio or video streams enabled'), undefined); + } + else { + constraints.video = false; + _this.outboundOptions.sendVideo = false; + _this.requestCameraAccesAux(constraints, callback); + } + } + else { + _this.requestCameraAccesAux(constraints, callback); + } + }); + }; + Stream.prototype.requestCameraAccesAux = function (constraints, callback) { + var _this = this; + console.log(constraints); + navigator.mediaDevices.getUserMedia(constraints) + .then(function (userStream) { + _this.cameraAccessSuccess(userStream, callback); + }) + .catch(function (error) { + _this.accessIsDenied = true; + _this.accessIsAllowed = false; + var errorName; + var errorMessage = error.toString(); + ; + if (!_this.isScreenRequested) { + errorName = _this.outboundOptions.sendVideo ? "CAMERA_ACCESS_DENIED" /* CAMERA_ACCESS_DENIED */ : "MICROPHONE_ACCESS_DENIED" /* MICROPHONE_ACCESS_DENIED */; + } + else { + errorName = "SCREEN_CAPTURE_DENIED" /* SCREEN_CAPTURE_DENIED */; // This code is only reachable for Firefox + } + callback(new OpenViduError_1.OpenViduError(errorName, errorMessage), undefined); + }); + }; + Stream.prototype.cameraAccessSuccess = function (userStream, callback) { + this.accessIsAllowed = true; + this.accessIsDenied = false; + this.ee.emitEvent('access-allowed-by-publisher'); + if (userStream.getAudioTracks()[0] != null) { + userStream.getAudioTracks()[0].enabled = this.outboundOptions.activeAudio; + } + if (userStream.getVideoTracks()[0] != null) { + userStream.getVideoTracks()[0].enabled = this.outboundOptions.activeVideo; + } + this.mediaStream = userStream; + this.ee.emitEvent('mediastream-updated'); + callback(undefined, this); + }; + Stream.prototype.userMediaHasVideo = function (callback) { + // If the user is going to publish its screen there's a video source + if (this.isScreenRequested) { + callback(true); + return; + } + else { + // List all input devices and serach for a video kind + navigator.mediaDevices.enumerateDevices().then(function (mediaDevices) { + var videoInput = mediaDevices.filter(function (deviceInfo) { + return deviceInfo.kind === 'videoinput'; + })[0]; + callback(videoInput != null); + }); + } + }; + Stream.prototype.publishVideoCallback = function (error, sdpOfferParam, wp) { + var _this = this; + if (error) { + return console.error("(publish) SDP offer error: " + + JSON.stringify(error)); + } + console.debug("Sending SDP offer to publish as " + + this.streamId, sdpOfferParam); + this.openVidu.sendRequest("publishVideo", { + sdpOffer: sdpOfferParam, + doLoopback: this.displayMyRemote() || false, + audioActive: this.outboundOptions.sendAudio, + videoActive: this.outboundOptions.sendVideo, + typeOfVideo: ((this.outboundOptions.sendVideo) ? ((this.isScreenRequested) ? 'SCREEN' : 'CAMERA') : '') + }, function (error, response) { + if (error) { + console.error("Error on publishVideo: " + JSON.stringify(error)); + } + else { + _this.processSdpAnswer(response.sdpAnswer); + console.info("'Publisher' succesfully published to session"); + } + }); + }; + Stream.prototype.startVideoCallback = function (error, sdpOfferParam, wp) { + var _this = this; + if (error) { + return console.error("(subscribe) SDP offer error: " + + JSON.stringify(error)); + } + console.debug("Sending SDP offer to subscribe to " + + this.streamId, sdpOfferParam); + this.openVidu.sendRequest("receiveVideoFrom", { + sender: this.streamId, + sdpOffer: sdpOfferParam + }, function (error, response) { + if (error) { + console.error("Error on recvVideoFrom: " + JSON.stringify(error)); + } + else { + _this.processSdpAnswer(response.sdpAnswer); + } + }); + }; + Stream.prototype.initWebRtcPeer = function (sdpOfferCallback) { + var _this = this; + if (this.local) { + var userMediaConstraints = { + audio: this.outboundOptions.sendAudio, + video: this.outboundOptions.sendVideo + }; + var options = { + videoStream: this.mediaStream, + mediaConstraints: userMediaConstraints, + onicecandidate: this.connection.sendIceCandidate.bind(this.connection), + }; + if (this.outboundOptions.dataChannel) { + options.dataChannelConfig = { + id: this.getChannelName(), + onopen: this.onDataChannelOpen, + onclose: this.onDataChannelClosed + }; + options.dataChannels = true; + } + if (this.displayMyRemote()) { + this.wp = kurentoUtils.WebRtcPeer.WebRtcPeerSendrecv(options, function (error) { + if (error) { + return console.error(error); + } + _this.wp.generateOffer(sdpOfferCallback.bind(_this)); + }); + } + else { + this.wp = kurentoUtils.WebRtcPeer.WebRtcPeerSendonly(options, function (error) { + if (error) { + return console.error(error); + } + _this.wp.generateOffer(sdpOfferCallback.bind(_this)); + }); + } + this.isPublisherPublished = true; + this.ee.emitEvent('stream-created-by-publisher'); + } + else { + var offerConstraints = { + audio: this.inboundOptions.recvAudio, + video: this.inboundOptions.recvVideo + }; + console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer", offerConstraints); + var options = { + onicecandidate: this.connection.sendIceCandidate.bind(this.connection), + mediaConstraints: offerConstraints + }; + this.wp = kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly(options, function (error) { + if (error) { + return console.error(error); + } + _this.wp.generateOffer(sdpOfferCallback.bind(_this)); + }); + } + console.debug("Waiting for SDP offer to be generated (" + + (this.local ? "local" : "remote") + " 'Stream': " + this.streamId + ")"); + }; + Stream.prototype.publish = function () { + var _this = this; + // FIXME: Throw error when stream is not local + if (this.isReadyToPublish) { + this.initWebRtcPeer(this.publishVideoCallback); + } + else { + this.ee.once('stream-ready', function (streamEvent) { + _this.publish(); + }); + } + // FIXME: Now we have coupled connecting to a room and adding a + // stream to this room. But in the new API, there are two steps. + // This is the second step. For now, it do nothing. + }; + Stream.prototype.subscribe = function () { + // FIXME: In the current implementation all participants are subscribed + // automatically to all other participants. We use this method only to + // negotiate SDP + this.initWebRtcPeer(this.startVideoCallback); + }; + Stream.prototype.processSdpAnswer = function (sdpAnswer) { + var _this = this; + var answer = new RTCSessionDescription({ + type: 'answer', + sdp: sdpAnswer, + }); + console.debug(this.streamId + ": set peer connection with recvd SDP answer", sdpAnswer); + var participantId = this.streamId; + var pc = this.wp.peerConnection; + pc.setRemoteDescription(answer, function () { + // Avoids to subscribe to your own stream remotely + // except when showMyRemote is true + if (!_this.local || _this.displayMyRemote()) { + _this.mediaStream = pc.getRemoteStreams()[0]; + console.debug("Peer remote stream", _this.mediaStream); + if (_this.mediaStream != undefined) { + _this.ee.emitEvent('mediastream-updated'); + if (_this.mediaStream.getAudioTracks()[0] != null) { + _this.speechEvent = kurentoUtils.WebRtcPeer.hark(_this.mediaStream, { threshold: _this.room.thresholdSpeaker }); + _this.speechEvent.on('speaking', function () { + //this.room.addParticipantSpeaking(participantId); + _this.room.emitEvent('publisherStartSpeaking', [{ + connection: _this.connection, + streamId: _this.streamId + }]); + }); + _this.speechEvent.on('stopped_speaking', function () { + //this.room.removeParticipantSpeaking(participantId); + _this.room.emitEvent('publisherStopSpeaking', [{ + connection: _this.connection, + streamId: _this.streamId + }]); + }); + } + } + if (!!_this.video) { + // let thumbnailId = this.video.thumb; + _this.video.oncanplay = function () { + if (_this.local && _this.displayMyRemote()) { + console.info("Your own remote 'Stream' with id [" + _this.streamId + "] video is now playing"); + _this.ee.emitEvent('remote-video-is-playing', [{ + element: _this.video + }]); + } + else if (!_this.local && !_this.displayMyRemote()) { + console.info("Remote 'Stream' with id [" + _this.streamId + "] video is now playing"); + _this.ee.emitEvent('video-is-playing', [{ + element: _this.video + }]); + } + //show(thumbnailId); + //this.hideSpinner(this.streamId); + }; + } + _this.room.emitEvent('stream-subscribed', [{ + stream: _this + }]); + } + _this.initWebRtcStats(); + }, function (error) { + console.error(_this.streamId + ": Error setting SDP to the peer connection: " + + JSON.stringify(error)); + }); + }; + Stream.prototype.unpublish = function () { + if (this.wp) { + this.wp.dispose(); + } + else { + if (this.mediaStream) { + this.mediaStream.getAudioTracks().forEach(function (track) { + track.stop && track.stop(); + }); + this.mediaStream.getVideoTracks().forEach(function (track) { + track.stop && track.stop(); + }); + } + } + if (this.speechEvent) { + this.speechEvent.stop(); + } + console.info(this.streamId + ": Stream '" + this.streamId + "' unpublished"); + }; + Stream.prototype.dispose = function () { + function disposeElement(element) { + if (element && element.parentNode) { + element.parentNode.removeChild(element); + } + } + disposeElement("progress-" + this.streamId); + if (this.wp) { + this.wp.dispose(); + } + else { + if (this.mediaStream) { + this.mediaStream.getAudioTracks().forEach(function (track) { + track.stop && track.stop(); + }); + this.mediaStream.getVideoTracks().forEach(function (track) { + track.stop && track.stop(); + }); + } + } + if (this.speechEvent) { + this.speechEvent.stop(); + } + this.stopWebRtcStats(); + console.info((this.local ? "Local " : "Remote ") + "'Stream' with id [" + this.streamId + "]' has been succesfully disposed"); + }; + Stream.prototype.configureScreenOptions = function (options) { + this.outboundOptions = options; + this.streamId = "SCREEN"; + }; + Stream.prototype.initWebRtcStats = function () { + this.webRtcStats = new WebRtcStats_1.WebRtcStats(this); + this.webRtcStats.initWebRtcStats(); + }; + Stream.prototype.stopWebRtcStats = function () { + if (this.webRtcStats != null && this.webRtcStats.isEnabled()) { + this.webRtcStats.stopWebRtcStats(); + } + }; + return Stream; +}()); +exports.Stream = Stream; + +},{"../KurentoUtils/kurento-utils-js":50,"./OpenViduError":58,"./WebRtcStats":62,"webrtc-adapter":26,"wolfy87-eventemitter":38}],62:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var DetectRTC = require("../KurentoUtils/DetectRTC"); +var WebRtcStats = /** @class */ (function () { + function WebRtcStats(stream) { + this.stream = stream; + this.webRtcStatsEnabled = false; + this.statsInterval = 1; + this.stats = { + "inbound": { + "audio": { + "bytesReceived": 0, + "packetsReceived": 0, + "packetsLost": 0 + }, + "video": { + "bytesReceived": 0, + "packetsReceived": 0, + "packetsLost": 0, + "framesDecoded": 0, + "nackCount": 0 + } + }, + "outbound": { + "audio": { + "bytesSent": 0, + "packetsSent": 0, + }, + "video": { + "bytesSent": 0, + "packetsSent": 0, + "framesEncoded": 0, + "nackCount": 0 + } + } + }; + } + WebRtcStats.prototype.isEnabled = function () { + return this.webRtcStatsEnabled; + }; + WebRtcStats.prototype.initWebRtcStats = function () { + var _this = this; + var elastestInstrumentation = localStorage.getItem('elastest-instrumentation'); + if (elastestInstrumentation) { + // ElasTest instrumentation object found in local storage + console.warn("WebRtc stats enabled for stream " + this.stream.streamId + " of connection " + this.stream.connection.connectionId); + this.webRtcStatsEnabled = true; + var instrumentation_1 = JSON.parse(elastestInstrumentation); + this.statsInterval = instrumentation_1.webrtc.interval; // Interval in seconds + console.warn("localStorage item: " + JSON.stringify(instrumentation_1)); + this.webRtcStatsIntervalId = setInterval(function () { + _this.sendStatsToHttpEndpoint(instrumentation_1); + }, this.statsInterval * 1000); + return; + } + console.debug("WebRtc stats not enabled"); + }; + WebRtcStats.prototype.stopWebRtcStats = function () { + if (this.webRtcStatsEnabled) { + clearInterval(this.webRtcStatsIntervalId); + console.warn("WebRtc stats stopped for disposed stream " + this.stream.streamId + " of connection " + this.stream.connection.connectionId); + } + }; + WebRtcStats.prototype.sendStatsToHttpEndpoint = function (instrumentation) { + var _this = this; + var sendPost = function (json) { + var http = new XMLHttpRequest(); + var url = instrumentation.webrtc.httpEndpoint; + http.open("POST", url, true); + http.setRequestHeader("Content-type", "application/json"); + http.onreadystatechange = function () { + if (http.readyState == 4 && http.status == 200) { + console.log("WebRtc stats succesfully sent to " + url + " for stream " + _this.stream.streamId + " of connection " + _this.stream.connection.connectionId); + } + }; + http.send(json); + }; + var f = function (stats) { + if (DetectRTC.browser.name === 'Firefox') { + stats.forEach(function (stat) { + var json = {}; + if ((stat.type === 'inbound-rtp') && + ( + // Avoid firefox empty outbound-rtp statistics + stat.nackCount != null && + stat.isRemote === false && + stat.id.startsWith('inbound') && + stat.remoteId.startsWith('inbound'))) { + var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; + var jitter = stat.jitter * 1000; + var metrics = { + "bytesReceived": (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, + "jitter": jitter, + "packetsReceived": (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, + "packetsLost": (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval + }; + var units = { + "bytesReceived": "bytes", + "jitter": "ms", + "packetsReceived": "packets", + "packetsLost": "packets" + }; + if (stat.mediaType === 'video') { + metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; + metrics['nackCount'] = (stat.nackCount - _this.stats.inbound.video.nackCount) / _this.statsInterval; + units['framesDecoded'] = "frames"; + units['nackCount'] = "packets"; + _this.stats.inbound.video.framesDecoded = stat.framesDecoded; + _this.stats.inbound.video.nackCount = stat.nackCount; + } + _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; + _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; + _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; + json = { + "@timestamp": new Date(stat.timestamp).toISOString(), + "exec": instrumentation.exec, + "component": instrumentation.component, + "stream": "webRtc", + "type": metricId, + "stream_type": "composed_metrics", + "units": units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + else if ((stat.type === 'outbound-rtp') && + ( + // Avoid firefox empty inbound-rtp statistics + stat.isRemote === false && + stat.id.toLowerCase().includes('outbound'))) { + var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; + var metrics = { + "bytesSent": (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, + "packetsSent": (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval + }; + var units = { + "bytesSent": "bytes", + "packetsSent": "packets" + }; + if (stat.mediaType === 'video') { + metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; + units['framesEncoded'] = "frames"; + _this.stats.outbound.video.framesEncoded = stat.framesEncoded; + } + _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; + _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; + json = { + "@timestamp": new Date(stat.timestamp).toISOString(), + "exec": instrumentation.exec, + "component": instrumentation.component, + "stream": "webRtc", + "type": metricId, + "stream_type": "composed_metrics", + "units": units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + }); + } + else if (DetectRTC.browser.name === 'Chrome') { + for (var _i = 0, _a = Object.keys(stats); _i < _a.length; _i++) { + var key = _a[_i]; + var stat = stats[key]; + if (stat.type === 'ssrc') { + var json = {}; + if ('bytesReceived' in stat && ((stat.mediaType === 'audio' && 'audioOutputLevel' in stat) || + (stat.mediaType === 'video' && 'qpSum' in stat))) { + // inbound-rtp + var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; + var metrics = { + "bytesReceived": (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, + "jitter": stat.googJitterBufferMs, + "packetsReceived": (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, + "packetsLost": (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval + }; + var units = { + "bytesReceived": "bytes", + "jitter": "ms", + "packetsReceived": "packets", + "packetsLost": "packets" + }; + if (stat.mediaType === 'video') { + metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; + metrics['nackCount'] = (stat.googNacksSent - _this.stats.inbound.video.nackCount) / _this.statsInterval; + units['framesDecoded'] = "frames"; + units['nackCount'] = "packets"; + _this.stats.inbound.video.framesDecoded = stat.framesDecoded; + _this.stats.inbound.video.nackCount = stat.googNacksSent; + } + _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; + _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; + _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; + json = { + "@timestamp": new Date(stat.timestamp).toISOString(), + "exec": instrumentation.exec, + "component": instrumentation.component, + "stream": "webRtc", + "type": metricId, + "stream_type": "composed_metrics", + "units": units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + else if ('bytesSent' in stat) { + // outbound-rtp + var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; + var metrics = { + "bytesSent": (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, + "packetsSent": (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval + }; + var units = { + "bytesSent": "bytes", + "packetsSent": "packets" + }; + if (stat.mediaType === 'video') { + metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; + units['framesEncoded'] = "frames"; + _this.stats.outbound.video.framesEncoded = stat.framesEncoded; + } + _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; + _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; + json = { + "@timestamp": new Date(stat.timestamp).toISOString(), + "exec": instrumentation.exec, + "component": instrumentation.component, + "stream": "webRtc", + "type": metricId, + "stream_type": "composed_metrics", + "units": units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + } + } + } + }; + this.getStatsAgnostic(this.stream.getRTCPeerConnection(), null, f, function (error) { console.log(error); }); + }; + WebRtcStats.prototype.standardizeReport = function (response) { + if (DetectRTC.browser.name === 'Firefox') { + return response; + } + var standardReport = {}; + response.result().forEach(function (report) { + var standardStats = { + id: report.id, + timestamp: report.timestamp, + type: report.type + }; + report.names().forEach(function (name) { + standardStats[name] = report.stat(name); + }); + standardReport[standardStats.id] = standardStats; + }); + return standardReport; + }; + WebRtcStats.prototype.getStatsAgnostic = function (pc, selector, successCb, failureCb) { + var _this = this; + if (DetectRTC.browser.name === 'Firefox') { + // getStats takes args in different order in Chrome and Firefox + return pc.getStats(selector, function (response) { + var report = _this.standardizeReport(response); + successCb(report); + }, failureCb); + } + else if (DetectRTC.browser.name === 'Chrome') { + // In Chrome, the first two arguments are reversed + return pc.getStats(function (response) { + var report = _this.standardizeReport(response); + successCb(report); + }, selector, failureCb); + } + }; + return WebRtcStats; +}()); +exports.WebRtcStats = WebRtcStats; + +},{"../KurentoUtils/DetectRTC":39}],63:[function(require,module,exports){ +// Last time updated at Feb 16, 2017, 08:32:23 +// Latest file can be found here: https://cdn.webrtc-experiment.com/getScreenId.js +// Muaz Khan - www.MuazKhan.com +// MIT License - www.WebRTC-Experiment.com/licence +// Documentation - https://github.com/muaz-khan/getScreenId. +// ______________ +// getScreenId.js +/* +getScreenId(function (error, sourceId, screen_constraints) { + // error == null || 'permission-denied' || 'not-installed' || 'installed-disabled' || 'not-chrome' + // sourceId == null || 'string' || 'firefox' + + if(sourceId == 'firefox') { + navigator.mozGetUserMedia(screen_constraints, onSuccess, onFailure); + } + else navigator.webkitGetUserMedia(screen_constraints, onSuccess, onFailure); +}); +*/ +window.getScreenId = function (callback) { + // for Firefox: + // sourceId == 'firefox' + // screen_constraints = {...} + if (!!navigator.mozGetUserMedia) { + callback(null, 'firefox', { + video: { + mozMediaSource: 'window', + mediaSource: 'window' + } + }); + 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)); + } + if (event.data.chromeExtensionStatus) { + callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus)); + } + // this event listener is no more needed + window.removeEventListener('message', onIFrameCallback); + } + setTimeout(postGetSourceIdMessage, 100); +}; +function getScreenConstraints(error, sourceId) { + 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 (sourceId) { + screen_constraints.video.mandatory.chromeMediaSourceId = sourceId; + } + return screen_constraints; +} +function postGetSourceIdMessage() { + if (!iframe) { + loadIFrame(postGetSourceIdMessage); + return; + } + if (!iframe.isLoaded) { + setTimeout(postGetSourceIdMessage, 100); + return; + } + iframe.contentWindow.postMessage({ + captureSourceId: true + }, '*'); +} +var iframe; +// this function is used in RTCMultiConnection v3 +window.getScreenConstraints = function (callback) { + loadIFrame(function () { + getScreenId(function (error, sourceId, screen_constraints) { + 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://www.webrtc-experiment.com/getSourceId/'; // https://wwww.yourdomain.com/getScreenId.html + iframe.style.display = 'none'; + (document.body || document.documentElement).appendChild(iframe); +} +window.getChromeExtensionStatus = function (callback) { + // for Firefox: + 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); + } + // this event listener is no more needed + 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 = getScreenId; +exports.getChromeExtensionStatus = getChromeExtensionStatus; + +},{}]},{},[51]) +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL21lcmdlL21lcmdlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL25vcm1hbGljZS9pbmRleC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9wcm9jZXNzL2Jyb3dzZXIuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvcnRjcGVlcmNvbm5lY3Rpb24tc2hpbS9ydGNwZWVyY29ubmVjdGlvbi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNmb3JtL2xpYi9ncmFtbWFyLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL3NkcC10cmFuc2Zvcm0vbGliL2luZGV4LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL3NkcC10cmFuc2Zvcm0vbGliL3BhcnNlci5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNmb3JtL2xpYi93cml0ZXIuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvc2RwLXRyYW5zbGF0b3IvbGliL2FycmF5LWVxdWFscy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNsYXRvci9saWIvaW5kZXguanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvc2RwLXRyYW5zbGF0b3IvbGliL2ludGVyb3AuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvc2RwLXRyYW5zbGF0b3IvbGliL3RyYW5zZm9ybS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9zZHAvc2RwLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL3VhLXBhcnNlci1qcy9zcmMvdWEtcGFyc2VyLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL3V1aWQvaW5kZXguanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvdXVpZC9saWIvYnl0ZXNUb1V1aWQuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvdXVpZC9saWIvcm5nLWJyb3dzZXIuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvdXVpZC92MS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy91dWlkL3Y0LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL3dlYnJ0Yy1hZGFwdGVyL3NyYy9qcy9hZGFwdGVyX2NvcmUuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvd2VicnRjLWFkYXB0ZXIvc3JjL2pzL2FkYXB0ZXJfZmFjdG9yeS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy93ZWJydGMtYWRhcHRlci9zcmMvanMvY2hyb21lL2Nocm9tZV9zaGltLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL3dlYnJ0Yy1hZGFwdGVyL3NyYy9qcy9jaHJvbWUvZ2V0dXNlcm1lZGlhLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL3dlYnJ0Yy1hZGFwdGVyL3NyYy9qcy9jb21tb25fc2hpbS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy93ZWJydGMtYWRhcHRlci9zcmMvanMvZWRnZS9lZGdlX3NoaW0uanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvd2VicnRjLWFkYXB0ZXIvc3JjL2pzL2VkZ2UvZ2V0dXNlcm1lZGlhLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL3dlYnJ0Yy1hZGFwdGVyL3NyYy9qcy9maXJlZm94L2ZpcmVmb3hfc2hpbS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy93ZWJydGMtYWRhcHRlci9zcmMvanMvZmlyZWZveC9nZXR1c2VybWVkaWEuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvd2VicnRjLWFkYXB0ZXIvc3JjL2pzL3NhZmFyaS9zYWZhcmlfc2hpbS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy93ZWJydGMtYWRhcHRlci9zcmMvanMvdXRpbHMuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvd2lsZGVtaXR0ZXIvd2lsZGVtaXR0ZXIuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvd29sZnk4Ny1ldmVudGVtaXR0ZXIvRXZlbnRFbWl0dGVyLmpzIiwiLi4vS3VyZW50b1V0aWxzL0RldGVjdFJUQy5qcyIsIi4uL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvTWFwcGVyLmpzIiwiLi4vS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2luZGV4LmpzIiwiLi4vS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2pzb25ycGNjbGllbnQuanMiLCIuLi9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvdHJhbnNwb3J0cy9pbmRleC5qcyIsIi4uL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy90cmFuc3BvcnRzL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24uanMiLCIuLi9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2luZGV4LmpzIiwiLi4vS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL0pzb25SUEMuanMiLCIuLi9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvWG1sUlBDLmpzIiwiLi4vS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL2luZGV4LmpzIiwiLi4vS3VyZW50b1V0aWxzL2t1cmVudG8tdXRpbHMtanMvV2ViUnRjUGVlci5qcyIsIi4uL0t1cmVudG9VdGlscy9rdXJlbnRvLXV0aWxzLWpzL2luZGV4LmpzIiwiTWFpbi50cyIsIk9wZW5WaWR1LnRzIiwiUHVibGlzaGVyLnRzIiwiU2Vzc2lvbi50cyIsIlN1YnNjcmliZXIudHMiLCIuLi9PcGVuVmlkdUludGVybmFsL0Nvbm5lY3Rpb24udHMiLCIuLi9PcGVuVmlkdUludGVybmFsL0xvY2FsUmVjb3JkZXIudHMiLCIuLi9PcGVuVmlkdUludGVybmFsL09wZW5WaWR1RXJyb3IudHMiLCIuLi9PcGVuVmlkdUludGVybmFsL09wZW5WaWR1SW50ZXJuYWwudHMiLCIuLi9PcGVuVmlkdUludGVybmFsL1Nlc3Npb25JbnRlcm5hbC50cyIsIi4uL09wZW5WaWR1SW50ZXJuYWwvU3RyZWFtLnRzIiwiLi4vT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNTdGF0cy50cyIsIi4uL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQkE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4dURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbjNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BxQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoakNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ2pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQzdCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDYkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3p1QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaFBBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbFJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6TkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM1NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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RUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksWUFBWSxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMxQyxNQUFNLENBQUMsSUFBSSxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUE7SUFDbEQsQ0FBQztJQUVELGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUE7QUFDckUsQ0FBQztBQUNELFFBQVEsQ0FBQyxrQkFBa0IsRUFBRSxVQUFVLENBQUMsQ0FBQTtBQUV4Qyw0QkFBNEIsT0FBTyxFQUFFLFFBQVE7SUFDM0MsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksWUFBWSxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMxQyxNQUFNLENBQUMsSUFBSSxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUE7SUFDbEQsQ0FBQztJQUVELGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUE7QUFDckUsQ0FBQztBQUNELFFBQVEsQ0FBQyxrQkFBa0IsRUFBRSxVQUFVLENBQUMsQ0FBQTtBQUV4Qyw0QkFBNEIsT0FBTyxFQUFFLFFBQVE7SUFDM0MsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksWUFBWSxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMxQyxNQUFNLENBQUMsSUFBSSxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUE7SUFDbEQsQ0FBQztJQUVELGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUE7QUFDckUsQ0FBQztBQUNELFFBQVEsQ0FBQyxrQkFBa0IsRUFBRSxVQUFVLENBQUMsQ0FBQTtBQUV4QyxtQkFBbUIsTUFBTSxFQUFFLE9BQU87SUFDaEMs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LG1CQUFtQixDQUFDLFNBQVMsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO0lBQzVELENBQUM7SUFFRCxVQUFVLENBQUMsbUNBQW1DLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDekQsQ0FBQyxDQUFDO0FBRUY7SUFDSSxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDVixVQUFVLENBQUMsbUNBQW1DLENBQUMsQ0FBQztRQUNoRCxNQUFNLENBQUM7SUFDWCxDQUFDO0lBRUQsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUNuQixVQUFVLENBQUMsbUNBQW1DLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDckQsTUFBTSxDQUFDO0lBQ1gsQ0FBQztJQUVELE1BQU0sQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDO1FBQzdCLHdCQUF3QixFQUFFLElBQUk7S0FDakMsRUFBRSxHQUFHLENBQUMsQ0FBQztBQUNaLENBQUM7QUFFRCxPQUFPLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztBQUNsQyxPQUFPLENBQUMsd0JBQXdCLEdBQUcsd0JBQXdCLENBQUMiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpe2Z1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfXJldHVybiBlfSkoKSIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG5mdW5jdGlvbiBFdmVudEVtaXR0ZXIoKSB7XG4gIHRoaXMuX2V2ZW50cyA9IHRoaXMuX2V2ZW50cyB8fCB7fTtcbiAgdGhpcy5fbWF4TGlzdGVuZXJzID0gdGhpcy5fbWF4TGlzdGVuZXJzIHx8IHVuZGVmaW5lZDtcbn1cbm1vZHVsZS5leHBvcnRzID0gRXZlbnRFbWl0dGVyO1xuXG4vLyBCYWNrd2FyZHMtY29tcGF0IHdpdGggbm9kZSAwLjEwLnhcbkV2ZW50RW1pdHRlci5FdmVudEVtaXR0ZXIgPSBFdmVudEVtaXR0ZXI7XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuX2V2ZW50cyA9IHVuZGVmaW5lZDtcbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuX21heExpc3RlbmVycyA9IHVuZGVmaW5lZDtcblxuLy8gQnkgZGVmYXVsdCBFdmVudEVtaXR0ZXJzIHdpbGwgcHJpbnQgYSB3YXJuaW5nIGlmIG1vcmUgdGhhbiAxMCBsaXN0ZW5lcnMgYXJlXG4vLyBhZGRlZCB0byBpdC4gVGhpcyBpcyBhIHVzZWZ1bCBkZWZhdWx0IHdoaWNoIGhlbHBzIGZpbmRpbmcgbWVtb3J5IGxlYWtzLlxuRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnMgPSAxMDtcblxuLy8gT2J2aW91c2x5IG5vdCBhbGwgRW1pdHRlcnMgc2hvdWxkIGJlIGxpbWl0ZWQgdG8gMTAuIFRoaXMgZnVuY3Rpb24gYWxsb3dzXG4vLyB0aGF0IHRvIGJlIGluY3JlYXNlZC4gU2V0IHRvIHplcm8gZm9yIHVubGltaXRlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuc2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24obikge1xuICBpZiAoIWlzTnVtYmVyKG4pIHx8IG4gPCAwIHx8IGlzTmFOKG4pKVxuICAgIHRocm93IFR5cGVFcnJvcignbiBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gIHRoaXMuX21heExpc3RlbmVycyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5lbWl0ID0gZnVuY3Rpb24odHlwZSkge1xuICB2YXIgZXIsIGhhbmRsZXIsIGxlbiwgYXJncywgaSwgbGlzdGVuZXJzO1xuXG4gIGlmICghdGhpcy5fZXZlbnRzKVxuICAgIHRoaXMuX2V2ZW50cyA9IHt9O1xuXG4gIC8vIElmIHRoZXJlIGlzIG5vICdlcnJvcicgZXZlbnQgbGlzdGVuZXIgdGhlbiB0aHJvdy5cbiAgaWYgKHR5cGUgPT09ICdlcnJvcicpIHtcbiAgICBpZiAoIXRoaXMuX2V2ZW50cy5lcnJvciB8fFxuICAgICAgICAoaXNPYmplY3QodGhpcy5fZXZlbnRzLmVycm9yKSAmJiAhdGhpcy5fZXZlbnRzLmVycm9yLmxlbmd0aCkpIHtcbiAgICAgIGVyID0gYXJndW1lbnRzWzFdO1xuICAgICAgaWYgKGVyIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBBdCBsZWFzdCBnaXZlIHNvbWUga2luZCBvZiBjb250ZXh0IHRvIHRoZSB1c2VyXG4gICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoJ1VuY2F1Z2h0LCB1bnNwZWNpZmllZCBcImVycm9yXCIgZXZlbnQuICgnICsgZXIgKyAnKScpO1xuICAgICAgICBlcnIuY29udGV4dCA9IGVyO1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaGFuZGxlciA9IHRoaXMuX2V2ZW50c1t0eXBlXTtcblxuICBpZiAoaXNVbmRlZmluZWQoaGFuZGxlcikpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIGlmIChpc0Z1bmN0aW9uKGhhbmRsZXIpKSB7XG4gICAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICAvLyBmYXN0IGNhc2VzXG4gICAgICBjYXNlIDE6XG4gICAgICAgIGhhbmRsZXIuY2FsbCh0aGlzKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDI6XG4gICAgICAgIGhhbmRsZXIuY2FsbCh0aGlzLCBhcmd1bWVudHNbMV0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMzpcbiAgICAgICAgaGFuZGxlci5jYWxsKHRoaXMsIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICAvLyBzbG93ZXJcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICBoYW5kbGVyLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChpc09iamVjdChoYW5kbGVyKSkge1xuICAgIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgIGxpc3RlbmVycyA9IGhhbmRsZXIuc2xpY2UoKTtcbiAgICBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoO1xuICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKylcbiAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBhcmdzKTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBtO1xuXG4gIGlmICghaXNGdW5jdGlvbihsaXN0ZW5lcikpXG4gICAgdGhyb3cgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcblxuICBpZiAoIXRoaXMuX2V2ZW50cylcbiAgICB0aGlzLl9ldmVudHMgPSB7fTtcblxuICAvLyBUbyBhdm9pZCByZWN1cnNpb24gaW4gdGhlIGNhc2UgdGhhdCB0eXBlID09PSBcIm5ld0xpc3RlbmVyXCIhIEJlZm9yZVxuICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gIGlmICh0aGlzLl9ldmVudHMubmV3TGlzdGVuZXIpXG4gICAgdGhpcy5lbWl0KCduZXdMaXN0ZW5lcicsIHR5cGUsXG4gICAgICAgICAgICAgIGlzRnVuY3Rpb24obGlzdGVuZXIubGlzdGVuZXIpID9cbiAgICAgICAgICAgICAgbGlzdGVuZXIubGlzdGVuZXIgOiBsaXN0ZW5lcik7XG5cbiAgaWYgKCF0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgdGhpcy5fZXZlbnRzW3R5cGVdID0gbGlzdGVuZXI7XG4gIGVsc2UgaWYgKGlzT2JqZWN0KHRoaXMuX2V2ZW50c1t0eXBlXSkpXG4gICAgLy8gSWYgd2UndmUgYWxyZWFkeSBnb3QgYW4gYXJyYXksIGp1c3QgYXBwZW5kLlxuICAgIHRoaXMuX2V2ZW50c1t0eXBlXS5wdXNoKGxpc3RlbmVyKTtcbiAgZWxzZVxuICAgIC8vIEFkZGluZyB0aGUgc2Vjb25kIGVsZW1lbnQsIG5lZWQgdG8gY2hhbmdlIHRvIGFycmF5LlxuICAgIHRoaXMuX2V2ZW50c1t0eXBlXSA9IFt0aGlzLl9ldmVudHNbdHlwZV0sIGxpc3RlbmVyXTtcblxuICAvLyBDaGVjayBmb3IgbGlzdGVuZXIgbGVha1xuICBpZiAoaXNPYmplY3QodGhpcy5fZXZlbnRzW3R5cGVdKSAmJiAhdGhpcy5fZXZlbnRzW3R5cGVdLndhcm5lZCkge1xuICAgIGlmICghaXNVbmRlZmluZWQodGhpcy5fbWF4TGlzdGVuZXJzKSkge1xuICAgICAgbSA9IHRoaXMuX21heExpc3RlbmVycztcbiAgICB9IGVsc2Uge1xuICAgICAgbSA9IEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzO1xuICAgIH1cblxuICAgIGlmIChtICYmIG0gPiAwICYmIHRoaXMuX2V2ZW50c1t0eXBlXS5sZW5ndGggPiBtKSB7XG4gICAgICB0aGlzLl9ldmVudHNbdHlwZV0ud2FybmVkID0gdHJ1ZTtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJyhub2RlKSB3YXJuaW5nOiBwb3NzaWJsZSBFdmVudEVtaXR0ZXIgbWVtb3J5ICcgK1xuICAgICAgICAgICAgICAgICAgICAnbGVhayBkZXRlY3RlZC4gJWQgbGlzdGVuZXJzIGFkZGVkLiAnICtcbiAgICAgICAgICAgICAgICAgICAgJ1VzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvIGluY3JlYXNlIGxpbWl0LicsXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2V2ZW50c1t0eXBlXS5sZW5ndGgpO1xuICAgICAgaWYgKHR5cGVvZiBjb25zb2xlLnRyYWNlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIC8vIG5vdCBzdXBwb3J0ZWQgaW4gSUUgMTBcbiAgICAgICAgY29uc29sZS50cmFjZSgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5vbiA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGUuYWRkTGlzdGVuZXI7XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub25jZSA9IGZ1bmN0aW9uKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGlmICghaXNGdW5jdGlvbihsaXN0ZW5lcikpXG4gICAgdGhyb3cgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcblxuICB2YXIgZmlyZWQgPSBmYWxzZTtcblxuICBmdW5jdGlvbiBnKCkge1xuICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIodHlwZSwgZyk7XG5cbiAgICBpZiAoIWZpcmVkKSB7XG4gICAgICBmaXJlZCA9IHRydWU7XG4gICAgICBsaXN0ZW5lci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgfVxuXG4gIGcubGlzdGVuZXIgPSBsaXN0ZW5lcjtcbiAgdGhpcy5vbih0eXBlLCBnKTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cbi8vIGVtaXRzIGEgJ3JlbW92ZUxpc3RlbmVyJyBldmVudCBpZmYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnJlbW92ZUxpc3RlbmVyID0gZnVuY3Rpb24odHlwZSwgbGlzdGVuZXIpIHtcbiAgdmFyIGxpc3QsIHBvc2l0aW9uLCBsZW5ndGgsIGk7XG5cbiAgaWYgKCFpc0Z1bmN0aW9uKGxpc3RlbmVyKSlcbiAgICB0aHJvdyBUeXBlRXJyb3IoJ2xpc3RlbmVyIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuXG4gIGlmICghdGhpcy5fZXZlbnRzIHx8ICF0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgcmV0dXJuIHRoaXM7XG5cbiAgbGlzdCA9IHRoaXMuX2V2ZW50c1t0eXBlXTtcbiAgbGVuZ3RoID0gbGlzdC5sZW5ndGg7XG4gIHBvc2l0aW9uID0gLTE7XG5cbiAgaWYgKGxpc3QgPT09IGxpc3RlbmVyIHx8XG4gICAgICAoaXNGdW5jdGlvbihsaXN0Lmxpc3RlbmVyKSAmJiBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikpIHtcbiAgICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuICAgIGlmICh0aGlzLl9ldmVudHMucmVtb3ZlTGlzdGVuZXIpXG4gICAgICB0aGlzLmVtaXQoJ3JlbW92ZUxpc3RlbmVyJywgdHlwZSwgbGlzdGVuZXIpO1xuXG4gIH0gZWxzZSBpZiAoaXNPYmplY3QobGlzdCkpIHtcbiAgICBmb3IgKGkgPSBsZW5ndGg7IGktLSA+IDA7KSB7XG4gICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHxcbiAgICAgICAgICAobGlzdFtpXS5saXN0ZW5lciAmJiBsaXN0W2ldLmxpc3RlbmVyID09PSBsaXN0ZW5lcikpIHtcbiAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAocG9zaXRpb24gPCAwKVxuICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpIHtcbiAgICAgIGxpc3QubGVuZ3RoID0gMDtcbiAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHNbdHlwZV07XG4gICAgfSBlbHNlIHtcbiAgICAgIGxpc3Quc3BsaWNlKHBvc2l0aW9uLCAxKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgdGhpcy5lbWl0KCdyZW1vdmVMaXN0ZW5lcicsIHR5cGUsIGxpc3RlbmVyKTtcbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBmdW5jdGlvbih0eXBlKSB7XG4gIHZhciBrZXksIGxpc3RlbmVycztcblxuICBpZiAoIXRoaXMuX2V2ZW50cylcbiAgICByZXR1cm4gdGhpcztcblxuICAvLyBub3QgbGlzdGVuaW5nIGZvciByZW1vdmVMaXN0ZW5lciwgbm8gbmVlZCB0byBlbWl0XG4gIGlmICghdGhpcy5fZXZlbnRzLnJlbW92ZUxpc3RlbmVyKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApXG4gICAgICB0aGlzLl9ldmVudHMgPSB7fTtcbiAgICBlbHNlIGlmICh0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLy8gZW1pdCByZW1vdmVMaXN0ZW5lciBmb3IgYWxsIGxpc3RlbmVycyBvbiBhbGwgZXZlbnRzXG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgZm9yIChrZXkgaW4gdGhpcy5fZXZlbnRzKSB7XG4gICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKGtleSk7XG4gICAgfVxuICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgIHRoaXMuX2V2ZW50cyA9IHt9O1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgbGlzdGVuZXJzID0gdGhpcy5fZXZlbnRzW3R5cGVdO1xuXG4gIGlmIChpc0Z1bmN0aW9uKGxpc3RlbmVycykpIHtcbiAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVycyk7XG4gIH0gZWxzZSBpZiAobGlzdGVuZXJzKSB7XG4gICAgLy8gTElGTyBvcmRlclxuICAgIHdoaWxlIChsaXN0ZW5lcnMubGVuZ3RoKVxuICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnNbbGlzdGVuZXJzLmxlbmd0aCAtIDFdKTtcbiAgfVxuICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuXG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5saXN0ZW5lcnMgPSBmdW5jdGlvbih0eXBlKSB7XG4gIHZhciByZXQ7XG4gIGlmICghdGhpcy5fZXZlbnRzIHx8ICF0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgcmV0ID0gW107XG4gIGVsc2UgaWYgKGlzRnVuY3Rpb24odGhpcy5fZXZlbnRzW3R5cGVdKSlcbiAgICByZXQgPSBbdGhpcy5fZXZlbnRzW3R5cGVdXTtcbiAgZWxzZVxuICAgIHJldCA9IHRoaXMuX2V2ZW50c1t0eXBlXS5zbGljZSgpO1xuICByZXR1cm4gcmV0O1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5saXN0ZW5lckNvdW50ID0gZnVuY3Rpb24odHlwZSkge1xuICBpZiAodGhpcy5fZXZlbnRzKSB7XG4gICAgdmFyIGV2bGlzdGVuZXIgPSB0aGlzLl9ldmVudHNbdHlwZV07XG5cbiAgICBpZiAoaXNGdW5jdGlvbihldmxpc3RlbmVyKSlcbiAgICAgIHJldHVybiAxO1xuICAgIGVsc2UgaWYgKGV2bGlzdGVuZXIpXG4gICAgICByZXR1cm4gZXZsaXN0ZW5lci5sZW5ndGg7XG4gIH1cbiAgcmV0dXJuIDA7XG59O1xuXG5FdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKGVtaXR0ZXIsIHR5cGUpIHtcbiAgcmV0dXJuIGVtaXR0ZXIubGlzdGVuZXJDb3VudCh0eXBlKTtcbn07XG5cbmZ1bmN0aW9uIGlzRnVuY3Rpb24oYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnZnVuY3Rpb24nO1xufVxuXG5mdW5jdGlvbiBpc051bWJlcihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc09iamVjdChhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdvYmplY3QnICYmIGFyZyAhPT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNVbmRlZmluZWQoYXJnKSB7XG4gIHJldHVybiBhcmcgPT09IHZvaWQgMDtcbn1cbiIsIi8qIGpzaGludCBub2RlOiB0cnVlICovXG4ndXNlIHN0cmljdCc7XG5cbnZhciBub3JtYWxpY2UgPSByZXF1aXJlKCdub3JtYWxpY2UnKTtcblxuLyoqXG4gICMgZnJlZWljZVxuXG4gIFRoZSBgZnJlZWljZWAgbW9kdWxlIGlzIGEgc2ltcGxlIHdheSBvZiBnZXR0aW5nIHJhbmRvbSBTVFVOIG9yIFRVUk4gc2VydmVyXG4gIGZvciB5b3VyIFdlYlJUQyBhcHBsaWNhdGlvbi4gIFRoZSBsaXN0IG9mIHNlcnZlcnMgKGp1c3QgU1RVTiBhdCB0aGlzIHN0YWdlKVxuICB3ZXJlIHNvdXJjZWQgZnJvbSB0aGlzIFtnaXN0XShodHRwczovL2dpc3QuZ2l0aHViLmNvbS96eml1bmkvMzc0MTkzMykuXG5cbiAgIyMgRXhhbXBsZSBVc2VcblxuICBUaGUgZm9sbG93aW5nIGRlbW9uc3RyYXRlcyBob3cgeW91IGNhbiB1c2UgYGZyZWVpY2VgIHdpdGhcbiAgW3J0Yy1xdWlja2Nvbm5lY3RdKGh0dHBzOi8vZ2l0aHViLmNvbS9ydGMtaW8vcnRjLXF1aWNrY29ubmVjdCk6XG5cbiAgPDw8IGV4YW1wbGVzL3F1aWNrY29ubmVjdC5qc1xuXG4gIEFzIHRoZSBgZnJlZWljZWAgbW9kdWxlIGdlbmVyYXRlcyBpY2Ugc2VydmVycyBpbiBhIGxpc3QgY29tcGxpYW50IHdpdGggdGhlXG4gIFdlYlJUQyBzcGVjIHlvdSB3aWxsIGJlIGFibGUgdG8gdXNlIGl0IHdpdGggcmF3IGBSVENQZWVyQ29ubmVjdGlvbmBcbiAgY29uc3RydWN0b3JzIGFuZCBvdGhlciBXZWJSVEMgbGlicmFyaWVzLlxuXG4gICMjIEhleSwgZG9uJ3QgdXNlIG15IFNUVU4vVFVSTiBzZXJ2ZXIhXG5cbiAgSWYgZm9yIHNvbWUgcmVhc29uIHlvdXIgZnJlZSBTVFVOIG9yIFRVUk4gc2VydmVyIGVuZHMgdXAgaW4gdGhlXG4gIGxpc3Qgb2Ygc2VydmVycyAoW3N0dW5dKGh0dHBzOi8vZ2l0aHViLmNvbS9EYW1vbk9laGxtYW4vZnJlZWljZS9ibG9iL21hc3Rlci9zdHVuLmpzb24pIG9yXG4gIFt0dXJuXShodHRwczovL2dpdGh1Yi5jb20vRGFtb25PZWhsbWFuL2ZyZWVpY2UvYmxvYi9tYXN0ZXIvdHVybi5qc29uKSlcbiAgdGhhdCBpcyB1c2VkIGluIHRoaXMgbW9kdWxlLCB5b3UgY2FuIGZlZWxcbiAgZnJlZSB0byBvcGVuIGFuIGlzc3VlIG9uIHRoaXMgcmVwb3NpdG9yeSBhbmQgdGhvc2Ugc2VydmVycyB3aWxsIGJlIHJlbW92ZWRcbiAgd2l0aGluIDI0IGhvdXJzIChvciBzb29uZXIpLiAgVGhpcyBpcyB0aGUgcXVpY2tlc3QgYW5kIHByb2JhYmx5IHRoZSBtb3N0XG4gIHBvbGl0ZSB3YXkgdG8gaGF2ZSBzb21ldGhpbmcgcmVtb3ZlZCAoYW5kIHByb3ZpZGVzIHVzIHNvbWUgdmlzaWJpbGl0eVxuICBpZiBzb21lb25lIG9wZW5zIGEgcHVsbCByZXF1ZXN0IHJlcXVlc3RpbmcgdGhhdCBhIHNlcnZlciBpcyBhZGRlZCkuXG5cbiAgIyMgUGxlYXNlIGFkZCBteSBzZXJ2ZXIhXG5cbiAgSWYgeW91IGhhdmUgYSBzZXJ2ZXIgdGhhdCB5b3Ugd2lzaCB0byBhZGQgdG8gdGhlIGxpc3QsIHRoYXQncyBhd2Vzb21lISBJJ21cbiAgc3VyZSBJIHNwZWFrIG9uIGJlaGFsZiBvZiBhIHdob2xlIHBpbGUgb2YgV2ViUlRDIGRldmVsb3BlcnMgd2hvIHNheSB0aGFua3MuXG4gIFRvIGdldCBpdCBpbnRvIHRoZSBsaXN0LCBmZWVsIGZyZWUgdG8gZWl0aGVyIG9wZW4gYSBwdWxsIHJlcXVlc3Qgb3IgaWYgeW91XG4gIGZpbmQgdGhhdCBwcm9jZXNzIGEgYml0IGRhdW50aW5nIHRoZW4ganVzdCBjcmVhdGUgYW4gaXNzdWUgcmVxdWVzdGluZ1xuICB0aGUgYWRkaXRpb24gb2YgdGhlIHNlcnZlciAobWFrZSBzdXJlIHlvdSBwcm92aWRlIGFsbCB0aGUgZGV0YWlscywgYW5kIGlmXG4gIHlvdSBoYXZlIGEgVGVybXMgb2YgU2VydmljZSB0aGVuIGluY2x1ZGluZyB0aGF0IGluIHRoZSBQUi9pc3N1ZSB3b3VsZCBiZVxuICBhd2Vzb21lKS5cblxuICAjIyBJIGtub3cgb2YgYSBmcmVlIHNlcnZlciwgY2FuIEkgYWRkIGl0P1xuXG4gIFN1cmUsIGlmIHlvdSBkbyB5b3VyIGhvbWV3b3JrIGFuZCBtYWtlIHN1cmUgaXQgaXMgb2sgdG8gdXNlIChJJ20gY3VycmVudGx5XG4gIGluIHRoZSBwcm9jZXNzIG9mIHJldmlld2luZyB0aGUgdGVybXMgb2YgdGhvc2UgU1RVTiBzZXJ2ZXJzIGluY2x1ZGVkIGZyb21cbiAgdGhlIG9yaWdpbmFsIGxpc3QpLiAgSWYgaXQncyBvayB0byBnbywgdGhlbiBwbGVhc2Ugc2VlIHRoZSBwcmV2aW91cyBlbnRyeVxuICBmb3IgaG93IHRvIGFkZCBpdC5cblxuICAjIyBDdXJyZW50IExpc3Qgb2YgU2VydmVyc1xuXG4gICogY3VycmVudCBhcyBhdCB0aGUgdGltZSBvZiBsYXN0IGBSRUFETUUubWRgIGZpbGUgZ2VuZXJhdGlvblxuXG4gICMjIyBTVFVOXG5cbiAgPDw8IHN0dW4uanNvblxuXG4gICMjIyBUVVJOXG5cbiAgPDw8IHR1cm4uanNvblxuXG4qKi9cblxudmFyIGZyZWVpY2UgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKG9wdHMpIHtcbiAgLy8gaWYgYSBsaXN0IG9mIHNlcnZlcnMgaGFzIGJlZW4gcHJvdmlkZWQsIHRoZW4gdXNlIGl0IGluc3RlYWQgb2YgZGVmYXVsdHNcbiAgdmFyIHNlcnZlcnMgPSB7XG4gICAgc3R1bjogKG9wdHMgfHwge30pLnN0dW4gfHwgcmVxdWlyZSgnLi9zdHVuLmpzb24nKSxcbiAgICB0dXJuOiAob3B0cyB8fCB7fSkudHVybiB8fCByZXF1aXJlKCcuL3R1cm4uanNvbicpXG4gIH07XG5cbiAgdmFyIHN0dW5Db3VudCA9IChvcHRzIHx8IHt9KS5zdHVuQ291bnQgfHwgMjtcbiAgdmFyIHR1cm5Db3VudCA9IChvcHRzIHx8IHt9KS50dXJuQ291bnQgfHwgMDtcbiAgdmFyIHNlbGVjdGVkO1xuXG4gIGZ1bmN0aW9uIGdldFNlcnZlcnModHlwZSwgY291bnQpIHtcbiAgICB2YXIgb3V0ID0gW107XG4gICAgdmFyIGlucHV0ID0gW10uY29uY2F0KHNlcnZlcnNbdHlwZV0pO1xuICAgIHZhciBpZHg7XG5cbiAgICB3aGlsZSAoaW5wdXQubGVuZ3RoICYmIG91dC5sZW5ndGggPCBjb3VudCkge1xuICAgICAgaWR4ID0gKE1hdGgucmFuZG9tKCkgKiBpbnB1dC5sZW5ndGgpIHwgMDtcbiAgICAgIG91dCA9IG91dC5jb25jYXQoaW5wdXQuc3BsaWNlKGlkeCwgMSkpO1xuICAgIH1cblxuICAgIHJldHVybiBvdXQubWFwKGZ1bmN0aW9uKHVybCkge1xuICAgICAgICAvL0lmIGl0J3MgYSBub3QgYSBzdHJpbmcsIGRvbid0IHRyeSB0byBcIm5vcm1hbGljZVwiIGl0IG90aGVyd2lzZSB1c2luZyB0eXBlOnVybCB3aWxsIHNjcmV3IGl0IHVwXG4gICAgICAgIGlmICgodHlwZW9mIHVybCAhPT0gJ3N0cmluZycpICYmICghICh1cmwgaW5zdGFuY2VvZiBTdHJpbmcpKSkge1xuICAgICAgICAgICAgcmV0dXJuIHVybDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBub3JtYWxpY2UodHlwZSArICc6JyArIHVybCk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8vIGFkZCBzdHVuIHNlcnZlcnNcbiAgc2VsZWN0ZWQgPSBbXS5jb25jYXQoZ2V0U2VydmVycygnc3R1bicsIHN0dW5Db3VudCkpO1xuXG4gIGlmICh0dXJuQ291bnQpIHtcbiAgICBzZWxlY3RlZCA9IHNlbGVjdGVkLmNvbmNhdChnZXRTZXJ2ZXJzKCd0dXJuJywgdHVybkNvdW50KSk7XG4gIH1cblxuICByZXR1cm4gc2VsZWN0ZWQ7XG59O1xuIiwibW9kdWxlLmV4cG9ydHM9W1xuICBcInN0dW4ubC5nb29nbGUuY29tOjE5MzAyXCIsXG4gIFwic3R1bjEubC5nb29nbGUuY29tOjE5MzAyXCIsXG4gIFwic3R1bjIubC5nb29nbGUuY29tOjE5MzAyXCIsXG4gIFwic3R1bjMubC5nb29nbGUuY29tOjE5MzAyXCIsXG4gIFwic3R1bjQubC5nb29nbGUuY29tOjE5MzAyXCIsXG4gIFwic3R1bi5la2lnYS5uZXRcIixcbiAgXCJzdHVuLmlkZWFzaXAuY29tXCIsXG4gIFwic3R1bi5zY2hsdW5kLmRlXCIsXG4gIFwic3R1bi5zdHVucHJvdG9jb2wub3JnOjM0NzhcIixcbiAgXCJzdHVuLnZvaXBhcm91bmQuY29tXCIsXG4gIFwic3R1bi52b2lwYnVzdGVyLmNvbVwiLFxuICBcInN0dW4udm9pcHN0dW50LmNvbVwiLFxuICBcInN0dW4udm94Z3JhdGlhLm9yZ1wiLFxuICBcInN0dW4uc2VydmljZXMubW96aWxsYS5jb21cIlxuXVxuIiwibW9kdWxlLmV4cG9ydHM9W11cbiIsInZhciBXaWxkRW1pdHRlciA9IHJlcXVpcmUoJ3dpbGRlbWl0dGVyJyk7XG5cbmZ1bmN0aW9uIGdldE1heFZvbHVtZSAoYW5hbHlzZXIsIGZmdEJpbnMpIHtcbiAgdmFyIG1heFZvbHVtZSA9IC1JbmZpbml0eTtcbiAgYW5hbHlzZXIuZ2V0RmxvYXRGcmVxdWVuY3lEYXRhKGZmdEJpbnMpO1xuXG4gIGZvcih2YXIgaT00LCBpaT1mZnRCaW5zLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICBpZiAoZmZ0Qmluc1tpXSA+IG1heFZvbHVtZSAmJiBmZnRCaW5zW2ldIDwgMCkge1xuICAgICAgbWF4Vm9sdW1lID0gZmZ0Qmluc1tpXTtcbiAgICB9XG4gIH07XG5cbiAgcmV0dXJuIG1heFZvbHVtZTtcbn1cblxuXG52YXIgYXVkaW9Db250ZXh0VHlwZTtcbmlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICBhdWRpb0NvbnRleHRUeXBlID0gd2luZG93LkF1ZGlvQ29udGV4dCB8fCB3aW5kb3cud2Via2l0QXVkaW9Db250ZXh0O1xufVxuLy8gdXNlIGEgc2luZ2xlIGF1ZGlvIGNvbnRleHQgZHVlIHRvIGhhcmR3YXJlIGxpbWl0c1xudmFyIGF1ZGlvQ29udGV4dCA9IG51bGw7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHN0cmVhbSwgb3B0aW9ucykge1xuICB2YXIgaGFya2VyID0gbmV3IFdpbGRFbWl0dGVyKCk7XG5cblxuICAvLyBtYWtlIGl0IG5vdCBicmVhayBpbiBub24tc3VwcG9ydGVkIGJyb3dzZXJzXG4gIGlmICghYXVkaW9Db250ZXh0VHlwZSkgcmV0dXJuIGhhcmtlcjtcblxuICAvL0NvbmZpZ1xuICB2YXIgb3B0aW9ucyA9IG9wdGlvbnMgfHwge30sXG4gICAgICBzbW9vdGhpbmcgPSAob3B0aW9ucy5zbW9vdGhpbmcgfHwgMC4xKSxcbiAgICAgIGludGVydmFsID0gKG9wdGlvbnMuaW50ZXJ2YWwgfHwgNTApLFxuICAgICAgdGhyZXNob2xkID0gb3B0aW9ucy50aHJlc2hvbGQsXG4gICAgICBwbGF5ID0gb3B0aW9ucy5wbGF5LFxuICAgICAgaGlzdG9yeSA9IG9wdGlvbnMuaGlzdG9yeSB8fCAxMCxcbiAgICAgIHJ1bm5pbmcgPSB0cnVlO1xuXG4gIC8vU2V0dXAgQXVkaW8gQ29udGV4dFxuICBpZiAoIWF1ZGlvQ29udGV4dCkge1xuICAgIGF1ZGlvQ29udGV4dCA9IG5ldyBhdWRpb0NvbnRleHRUeXBlKCk7XG4gIH1cbiAgdmFyIHNvdXJjZU5vZGUsIGZmdEJpbnMsIGFuYWx5c2VyO1xuXG4gIGFuYWx5c2VyID0gYXVkaW9Db250ZXh0LmNyZWF0ZUFuYWx5c2VyKCk7XG4gIGFuYWx5c2VyLmZmdFNpemUgPSA1MTI7XG4gIGFuYWx5c2VyLnNtb290aGluZ1RpbWVDb25zdGFudCA9IHNtb290aGluZztcbiAgZmZ0QmlucyA9IG5ldyBGbG9hdDMyQXJyYXkoYW5hbHlzZXIuZnJlcXVlbmN5QmluQ291bnQpO1xuXG4gIGlmIChzdHJlYW0uanF1ZXJ5KSBzdHJlYW0gPSBzdHJlYW1bMF07XG4gIGlmIChzdHJlYW0gaW5zdGFuY2VvZiBIVE1MQXVkaW9FbGVtZW50IHx8IHN0cmVhbSBpbnN0YW5jZW9mIEhUTUxWaWRlb0VsZW1lbnQpIHtcbiAgICAvL0F1ZGlvIFRhZ1xuICAgIHNvdXJjZU5vZGUgPSBhdWRpb0NvbnRleHQuY3JlYXRlTWVkaWFFbGVtZW50U291cmNlKHN0cmVhbSk7XG4gICAgaWYgKHR5cGVvZiBwbGF5ID09PSAndW5kZWZpbmVkJykgcGxheSA9IHRydWU7XG4gICAgdGhyZXNob2xkID0gdGhyZXNob2xkIHx8IC01MDtcbiAgfSBlbHNlIHtcbiAgICAvL1dlYlJUQyBTdHJlYW1cbiAgICBzb3VyY2VOb2RlID0gYXVkaW9Db250ZXh0LmNyZWF0ZU1lZGlhU3RyZWFtU291cmNlKHN0cmVhbSk7XG4gICAgdGhyZXNob2xkID0gdGhyZXNob2xkIHx8IC01MDtcbiAgfVxuXG4gIHNvdXJjZU5vZGUuY29ubmVjdChhbmFseXNlcik7XG4gIGlmIChwbGF5KSBhbmFseXNlci5jb25uZWN0KGF1ZGlvQ29udGV4dC5kZXN0aW5hdGlvbik7XG5cbiAgaGFya2VyLnNwZWFraW5nID0gZmFsc2U7XG5cbiAgaGFya2VyLnNldFRocmVzaG9sZCA9IGZ1bmN0aW9uKHQpIHtcbiAgICB0aHJlc2hvbGQgPSB0O1xuICB9O1xuXG4gIGhhcmtlci5zZXRJbnRlcnZhbCA9IGZ1bmN0aW9uKGkpIHtcbiAgICBpbnRlcnZhbCA9IGk7XG4gIH07XG5cbiAgaGFya2VyLnN0b3AgPSBmdW5jdGlvbigpIHtcbiAgICBydW5uaW5nID0gZmFsc2U7XG4gICAgaGFya2VyLmVtaXQoJ3ZvbHVtZV9jaGFuZ2UnLCAtMTAwLCB0aHJlc2hvbGQpO1xuICAgIGlmIChoYXJrZXIuc3BlYWtpbmcpIHtcbiAgICAgIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuICAgICAgaGFya2VyLmVtaXQoJ3N0b3BwZWRfc3BlYWtpbmcnKTtcbiAgICB9XG4gICAgYW5hbHlzZXIuZGlzY29ubmVjdCgpO1xuICAgIHNvdXJjZU5vZGUuZGlzY29ubmVjdCgpO1xuICB9O1xuICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5ID0gW107XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgaGlzdG9yeTsgaSsrKSB7XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnB1c2goMCk7XG4gIH1cblxuICAvLyBQb2xsIHRoZSBhbmFseXNlciBub2RlIHRvIGRldGVybWluZSBpZiBzcGVha2luZ1xuICAvLyBhbmQgZW1pdCBldmVudHMgaWYgY2hhbmdlZFxuICB2YXIgbG9vcGVyID0gZnVuY3Rpb24oKSB7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcblxuICAgICAgLy9jaGVjayBpZiBzdG9wIGhhcyBiZWVuIGNhbGxlZFxuICAgICAgaWYoIXJ1bm5pbmcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB2YXIgY3VycmVudFZvbHVtZSA9IGdldE1heFZvbHVtZShhbmFseXNlciwgZmZ0Qmlucyk7XG5cbiAgICAgIGhhcmtlci5lbWl0KCd2b2x1bWVfY2hhbmdlJywgY3VycmVudFZvbHVtZSwgdGhyZXNob2xkKTtcblxuICAgICAgdmFyIGhpc3RvcnkgPSAwO1xuICAgICAgaWYgKGN1cnJlbnRWb2x1bWUgPiB0aHJlc2hvbGQgJiYgIWhhcmtlci5zcGVha2luZykge1xuICAgICAgICAvLyB0cmlnZ2VyIHF1aWNrbHksIHNob3J0IGhpc3RvcnlcbiAgICAgICAgZm9yICh2YXIgaSA9IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoIC0gMzsgaSA8IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBoaXN0b3J5ICs9IGhhcmtlci5zcGVha2luZ0hpc3RvcnlbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpc3RvcnkgPj0gMikge1xuICAgICAgICAgIGhhcmtlci5zcGVha2luZyA9IHRydWU7XG4gICAgICAgICAgaGFya2VyLmVtaXQoJ3NwZWFraW5nJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoY3VycmVudFZvbHVtZSA8IHRocmVzaG9sZCAmJiBoYXJrZXIuc3BlYWtpbmcpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaGlzdG9yeSArPSBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5W2ldO1xuICAgICAgICB9XG4gICAgICAgIGlmIChoaXN0b3J5ID09IDApIHtcbiAgICAgICAgICBoYXJrZXIuc3BlYWtpbmcgPSBmYWxzZTtcbiAgICAgICAgICBoYXJrZXIuZW1pdCgnc3RvcHBlZF9zcGVha2luZycpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnNoaWZ0KCk7XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnB1c2goMCArIChjdXJyZW50Vm9sdW1lID4gdGhyZXNob2xkKSk7XG5cbiAgICAgIGxvb3BlcigpO1xuICAgIH0sIGludGVydmFsKTtcbiAgfTtcbiAgbG9vcGVyKCk7XG5cblxuICByZXR1cm4gaGFya2VyO1xufVxuIiwiaWYgKHR5cGVvZiBPYmplY3QuY3JlYXRlID09PSAnZnVuY3Rpb24nKSB7XG4gIC8vIGltcGxlbWVudGF0aW9uIGZyb20gc3RhbmRhcmQgbm9kZS5qcyAndXRpbCcgbW9kdWxlXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICBjdG9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDdG9yLnByb3RvdHlwZSwge1xuICAgICAgY29uc3RydWN0b3I6IHtcbiAgICAgICAgdmFsdWU6IGN0b3IsXG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICB9XG4gICAgfSk7XG4gIH07XG59IGVsc2Uge1xuICAvLyBvbGQgc2Nob29sIHNoaW0gZm9yIG9sZCBicm93c2Vyc1xuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGluaGVyaXRzKGN0b3IsIHN1cGVyQ3Rvcikge1xuICAgIGN0b3Iuc3VwZXJfID0gc3VwZXJDdG9yXG4gICAgdmFyIFRlbXBDdG9yID0gZnVuY3Rpb24gKCkge31cbiAgICBUZW1wQ3Rvci5wcm90b3R5cGUgPSBzdXBlckN0b3IucHJvdG90eXBlXG4gICAgY3Rvci5wcm90b3R5cGUgPSBuZXcgVGVtcEN0b3IoKVxuICAgIGN0b3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gY3RvclxuICB9XG59XG4iLCIvKiFcclxuICogQG5hbWUgSmF2YVNjcmlwdC9Ob2RlSlMgTWVyZ2UgdjEuMi4wXHJcbiAqIEBhdXRob3IgeWVpa29zXHJcbiAqIEByZXBvc2l0b3J5IGh0dHBzOi8vZ2l0aHViLmNvbS95ZWlrb3MvanMubWVyZ2VcclxuXHJcbiAqIENvcHlyaWdodCAyMDE0IHllaWtvcyAtIE1JVCBsaWNlbnNlXHJcbiAqIGh0dHBzOi8vcmF3LmdpdGh1Yi5jb20veWVpa29zL2pzLm1lcmdlL21hc3Rlci9MSUNFTlNFXHJcbiAqL1xyXG5cclxuOyhmdW5jdGlvbihpc05vZGUpIHtcclxuXHJcblx0LyoqXHJcblx0ICogTWVyZ2Ugb25lIG9yIG1vcmUgb2JqZWN0cyBcclxuXHQgKiBAcGFyYW0gYm9vbD8gY2xvbmVcclxuXHQgKiBAcGFyYW0gbWl4ZWQsLi4uIGFyZ3VtZW50c1xyXG5cdCAqIEByZXR1cm4gb2JqZWN0XHJcblx0ICovXHJcblxyXG5cdHZhciBQdWJsaWMgPSBmdW5jdGlvbihjbG9uZSkge1xyXG5cclxuXHRcdHJldHVybiBtZXJnZShjbG9uZSA9PT0gdHJ1ZSwgZmFsc2UsIGFyZ3VtZW50cyk7XHJcblxyXG5cdH0sIHB1YmxpY05hbWUgPSAnbWVyZ2UnO1xyXG5cclxuXHQvKipcclxuXHQgKiBNZXJnZSB0d28gb3IgbW9yZSBvYmplY3RzIHJlY3Vyc2l2ZWx5IFxyXG5cdCAqIEBwYXJhbSBib29sPyBjbG9uZVxyXG5cdCAqIEBwYXJhbSBtaXhlZCwuLi4gYXJndW1lbnRzXHJcblx0ICogQHJldHVybiBvYmplY3RcclxuXHQgKi9cclxuXHJcblx0UHVibGljLnJlY3Vyc2l2ZSA9IGZ1bmN0aW9uKGNsb25lKSB7XHJcblxyXG5cdFx0cmV0dXJuIG1lcmdlKGNsb25lID09PSB0cnVlLCB0cnVlLCBhcmd1bWVudHMpO1xyXG5cclxuXHR9O1xyXG5cclxuXHQvKipcclxuXHQgKiBDbG9uZSB0aGUgaW5wdXQgcmVtb3ZpbmcgYW55IHJlZmVyZW5jZVxyXG5cdCAqIEBwYXJhbSBtaXhlZCBpbnB1dFxyXG5cdCAqIEByZXR1cm4gbWl4ZWRcclxuXHQgKi9cclxuXHJcblx0UHVibGljLmNsb25lID0gZnVuY3Rpb24oaW5wdXQpIHtcclxuXHJcblx0XHR2YXIgb3V0cHV0ID0gaW5wdXQsXHJcblx0XHRcdHR5cGUgPSB0eXBlT2YoaW5wdXQpLFxyXG5cdFx0XHRpbmRleCwgc2l6ZTtcclxuXHJcblx0XHRpZiAodHlwZSA9PT0gJ2FycmF5Jykge1xyXG5cclxuXHRcdFx0b3V0cHV0ID0gW107XHJcblx0XHRcdHNpemUgPSBpbnB1dC5sZW5ndGg7XHJcblxyXG5cdFx0XHRmb3IgKGluZGV4PTA7aW5kZXg8c2l6ZTsrK2luZGV4KVxyXG5cclxuXHRcdFx0XHRvdXRwdXRbaW5kZXhdID0gUHVibGljLmNsb25lKGlucHV0W2luZGV4XSk7XHJcblxyXG5cdFx0fSBlbHNlIGlmICh0eXBlID09PSAnb2JqZWN0Jykge1xyXG5cclxuXHRcdFx0b3V0cHV0ID0ge307XHJcblxyXG5cdFx0XHRmb3IgKGluZGV4IGluIGlucHV0KVxyXG5cclxuXHRcdFx0XHRvdXRwdXRbaW5kZXhdID0gUHVibGljLmNsb25lKGlucHV0W2luZGV4XSk7XHJcblxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBvdXRwdXQ7XHJcblxyXG5cdH07XHJcblxyXG5cdC8qKlxyXG5cdCAqIE1lcmdlIHR3byBvYmplY3RzIHJlY3Vyc2l2ZWx5XHJcblx0ICogQHBhcmFtIG1peGVkIGlucHV0XHJcblx0ICogQHBhcmFtIG1peGVkIGV4dGVuZFxyXG5cdCAqIEByZXR1cm4gbWl4ZWRcclxuXHQgKi9cclxuXHJcblx0ZnVuY3Rpb24gbWVyZ2VfcmVjdXJzaXZlKGJhc2UsIGV4dGVuZCkge1xyXG5cclxuXHRcdGlmICh0eXBlT2YoYmFzZSkgIT09ICdvYmplY3QnKVxyXG5cclxuXHRcdFx0cmV0dXJuIGV4dGVuZDtcclxuXHJcblx0XHRmb3IgKHZhciBrZXkgaW4gZXh0ZW5kKSB7XHJcblxyXG5cdFx0XHRpZiAodHlwZU9mKGJhc2Vba2V5XSkgPT09ICdvYmplY3QnICYmIHR5cGVPZihleHRlbmRba2V5XSkgPT09ICdvYmplY3QnKSB7XHJcblxyXG5cdFx0XHRcdGJhc2Vba2V5XSA9IG1lcmdlX3JlY3Vyc2l2ZShiYXNlW2tleV0sIGV4dGVuZFtrZXldKTtcclxuXHJcblx0XHRcdH0gZWxzZSB7XHJcblxyXG5cdFx0XHRcdGJhc2Vba2V5XSA9IGV4dGVuZFtrZXldO1xyXG5cclxuXHRcdFx0fVxyXG5cclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gYmFzZTtcclxuXHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBNZXJnZSB0d28gb3IgbW9yZSBvYmplY3RzXHJcblx0ICogQHBhcmFtIGJvb2wgY2xvbmVcclxuXHQgKiBAcGFyYW0gYm9vbCByZWN1cnNpdmVcclxuXHQgKiBAcGFyYW0gYXJyYXkgYXJndlxyXG5cdCAqIEByZXR1cm4gb2JqZWN0XHJcblx0ICovXHJcblxyXG5cdGZ1bmN0aW9uIG1lcmdlKGNsb25lLCByZWN1cnNpdmUsIGFyZ3YpIHtcclxuXHJcblx0XHR2YXIgcmVzdWx0ID0gYXJndlswXSxcclxuXHRcdFx0c2l6ZSA9IGFyZ3YubGVuZ3RoO1xyXG5cclxuXHRcdGlmIChjbG9uZSB8fCB0eXBlT2YocmVzdWx0KSAhPT0gJ29iamVjdCcpXHJcblxyXG5cdFx0XHRyZXN1bHQgPSB7fTtcclxuXHJcblx0XHRmb3IgKHZhciBpbmRleD0wO2luZGV4PHNpemU7KytpbmRleCkge1xyXG5cclxuXHRcdFx0dmFyIGl0ZW0gPSBhcmd2W2luZGV4XSxcclxuXHJcblx0XHRcdFx0dHlwZSA9IHR5cGVPZihpdGVtKTtcclxuXHJcblx0XHRcdGlmICh0eXBlICE9PSAnb2JqZWN0JykgY29udGludWU7XHJcblxyXG5cdFx0XHRmb3IgKHZhciBrZXkgaW4gaXRlbSkge1xyXG5cclxuXHRcdFx0XHR2YXIgc2l0ZW0gPSBjbG9uZSA/IFB1YmxpYy5jbG9uZShpdGVtW2tleV0pIDogaXRlbVtrZXldO1xyXG5cclxuXHRcdFx0XHRpZiAocmVjdXJzaXZlKSB7XHJcblxyXG5cdFx0XHRcdFx0cmVzdWx0W2tleV0gPSBtZXJnZV9yZWN1cnNpdmUocmVzdWx0W2tleV0sIHNpdGVtKTtcclxuXHJcblx0XHRcdFx0fSBlbHNlIHtcclxuXHJcblx0XHRcdFx0XHRyZXN1bHRba2V5XSA9IHNpdGVtO1xyXG5cclxuXHRcdFx0XHR9XHJcblxyXG5cdFx0XHR9XHJcblxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiByZXN1bHQ7XHJcblxyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogR2V0IHR5cGUgb2YgdmFyaWFibGVcclxuXHQgKiBAcGFyYW0gbWl4ZWQgaW5wdXRcclxuXHQgKiBAcmV0dXJuIHN0cmluZ1xyXG5cdCAqXHJcblx0ICogQHNlZSBodHRwOi8vanNwZXJmLmNvbS90eXBlb2Z2YXJcclxuXHQgKi9cclxuXHJcblx0ZnVuY3Rpb24gdHlwZU9mKGlucHV0KSB7XHJcblxyXG5cdFx0cmV0dXJuICh7fSkudG9TdHJpbmcuY2FsbChpbnB1dCkuc2xpY2UoOCwgLTEpLnRvTG93ZXJDYXNlKCk7XHJcblxyXG5cdH1cclxuXHJcblx0aWYgKGlzTm9kZSkge1xyXG5cclxuXHRcdG1vZHVsZS5leHBvcnRzID0gUHVibGljO1xyXG5cclxuXHR9IGVsc2Uge1xyXG5cclxuXHRcdHdpbmRvd1twdWJsaWNOYW1lXSA9IFB1YmxpYztcclxuXHJcblx0fVxyXG5cclxufSkodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgbW9kdWxlICYmIHR5cGVvZiBtb2R1bGUuZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMpOyIsIi8qKlxuICAjIG5vcm1hbGljZVxuXG4gIE5vcm1hbGl6ZSBhbiBpY2Ugc2VydmVyIGNvbmZpZ3VyYXRpb24gb2JqZWN0IChvciBwbGFpbiBvbGQgc3RyaW5nKSBpbnRvIGEgZm9ybWF0XG4gIHRoYXQgaXMgdXNhYmxlIGluIGFsbCBicm93c2VycyBzdXBwb3J0aW5nIFdlYlJUQy4gIFByaW1hcmlseSB0aGlzIG1vZHVsZSBpcyBkZXNpZ25lZFxuICB0byBoZWxwIHdpdGggdGhlIHRyYW5zaXRpb24gb2YgdGhlIGB1cmxgIGF0dHJpYnV0ZSBvZiB0aGUgY29uZmlndXJhdGlvbiBvYmplY3QgdG9cbiAgdGhlIGB1cmxzYCBhdHRyaWJ1dGUuXG5cbiAgIyMgRXhhbXBsZSBVc2FnZVxuXG4gIDw8PCBleGFtcGxlcy9zaW1wbGUuanNcblxuKiovXG5cbnZhciBwcm90b2NvbHMgPSBbXG4gICdzdHVuOicsXG4gICd0dXJuOidcbl07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaW5wdXQpIHtcbiAgdmFyIHVybCA9IChpbnB1dCB8fCB7fSkudXJsIHx8IGlucHV0O1xuICB2YXIgcHJvdG9jb2w7XG4gIHZhciBwYXJ0cztcbiAgdmFyIG91dHB1dCA9IHt9O1xuXG4gIC8vIGlmIHdlIGRvbid0IGhhdmUgYSBzdHJpbmcgdXJsLCB0aGVuIGFsbG93IHRoZSBpbnB1dCB0byBwYXNzdGhyb3VnaFxuICBpZiAodHlwZW9mIHVybCAhPSAnc3RyaW5nJyAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICByZXR1cm4gaW5wdXQ7XG4gIH1cblxuICAvLyB0cmltIHRoZSB1cmwgc3RyaW5nLCBhbmQgY29udmVydCB0byBhbiBhcnJheVxuICB1cmwgPSB1cmwudHJpbSgpO1xuXG4gIC8vIGlmIHRoZSBwcm90b2NvbCBpcyBub3Qga25vd24sIHRoZW4gcGFzc3Rocm91Z2hcbiAgcHJvdG9jb2wgPSBwcm90b2NvbHNbcHJvdG9jb2xzLmluZGV4T2YodXJsLnNsaWNlKDAsIDUpKV07XG4gIGlmICghIHByb3RvY29sKSB7XG4gICAgcmV0dXJuIGlucHV0O1xuICB9XG5cbiAgLy8gbm93IGxldCdzIGF0dGFjayB0aGUgcmVtYWluaW5nIHVybCBwYXJ0c1xuICB1cmwgPSB1cmwuc2xpY2UoNSk7XG4gIHBhcnRzID0gdXJsLnNwbGl0KCdAJyk7XG5cbiAgb3V0cHV0LnVzZXJuYW1lID0gaW5wdXQudXNlcm5hbWU7XG4gIG91dHB1dC5jcmVkZW50aWFsID0gaW5wdXQuY3JlZGVudGlhbDtcbiAgLy8gaWYgd2UgaGF2ZSBhbiBhdXRoZW50aWNhdGlvbiBwYXJ0LCB0aGVuIHNldCB0aGUgY3JlZGVudGlhbHNcbiAgaWYgKHBhcnRzLmxlbmd0aCA+IDEpIHtcbiAgICB1cmwgPSBwYXJ0c1sxXTtcbiAgICBwYXJ0cyA9IHBhcnRzWzBdLnNwbGl0KCc6Jyk7XG5cbiAgICAvLyBhZGQgdGhlIG91dHB1dCBjcmVkZW50aWFsIGFuZCB1c2VybmFtZVxuICAgIG91dHB1dC51c2VybmFtZSA9IHBhcnRzWzBdO1xuICAgIG91dHB1dC5jcmVkZW50aWFsID0gKGlucHV0IHx8IHt9KS5jcmVkZW50aWFsIHx8IHBhcnRzWzFdIHx8ICcnO1xuICB9XG5cbiAgb3V0cHV0LnVybCA9IHByb3RvY29sICsgdXJsO1xuICBvdXRwdXQudXJscyA9IFsgb3V0cHV0LnVybCBdO1xuXG4gIHJldHVybiBvdXRwdXQ7XG59O1xuIiwiLy8gc2hpbSBmb3IgdXNpbmcgcHJvY2VzcyBpbiBicm93c2VyXG52YXIgcHJvY2VzcyA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbi8vIGNhY2hlZCBmcm9tIHdoYXRldmVyIGdsb2JhbCBpcyBwcmVzZW50IHNvIHRoYXQgdGVzdCBydW5uZXJzIHRoYXQgc3R1YiBpdFxuLy8gZG9uJ3QgYnJlYWsgdGhpbmdzLiAgQnV0IHdlIG5lZWQgdG8gd3JhcCBpdCBpbiBhIHRyeSBjYXRjaCBpbiBjYXNlIGl0IGlzXG4vLyB3cmFwcGVkIGluIHN0cmljdCBtb2RlIGNvZGUgd2hpY2ggZG9lc24ndCBkZWZpbmUgYW55IGdsb2JhbHMuICBJdCdzIGluc2lkZSBhXG4vLyBmdW5jdGlvbiBiZWNhdXNlIHRyeS9jYXRjaGVzIGRlb3B0aW1pemUgaW4gY2VydGFpbiBlbmdpbmVzLlxuXG52YXIgY2FjaGVkU2V0VGltZW91dDtcbnZhciBjYWNoZWRDbGVhclRpbWVvdXQ7XG5cbmZ1bmN0aW9uIGRlZmF1bHRTZXRUaW1vdXQoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzZXRUaW1lb3V0IGhhcyBub3QgYmVlbiBkZWZpbmVkJyk7XG59XG5mdW5jdGlvbiBkZWZhdWx0Q2xlYXJUaW1lb3V0ICgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NsZWFyVGltZW91dCBoYXMgbm90IGJlZW4gZGVmaW5lZCcpO1xufVxuKGZ1bmN0aW9uICgpIHtcbiAgICB0cnkge1xuICAgICAgICBpZiAodHlwZW9mIHNldFRpbWVvdXQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGNhY2hlZFNldFRpbWVvdXQgPSBzZXRUaW1lb3V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IGRlZmF1bHRTZXRUaW1vdXQ7XG4gICAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNhY2hlZFNldFRpbWVvdXQgPSBkZWZhdWx0U2V0VGltb3V0O1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICBpZiAodHlwZW9mIGNsZWFyVGltZW91dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gY2xlYXJUaW1lb3V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gZGVmYXVsdENsZWFyVGltZW91dDtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gZGVmYXVsdENsZWFyVGltZW91dDtcbiAgICB9XG59ICgpKVxuZnVuY3Rpb24gcnVuVGltZW91dChmdW4pIHtcbiAgICBpZiAoY2FjaGVkU2V0VGltZW91dCA9PT0gc2V0VGltZW91dCkge1xuICAgICAgICAvL25vcm1hbCBlbnZpcm9tZW50cyBpbiBzYW5lIHNpdHVhdGlvbnNcbiAgICAgICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9XG4gICAgLy8gaWYgc2V0VGltZW91dCB3YXNuJ3QgYXZhaWxhYmxlIGJ1dCB3YXMgbGF0dGVyIGRlZmluZWRcbiAgICBpZiAoKGNhY2hlZFNldFRpbWVvdXQgPT09IGRlZmF1bHRTZXRUaW1vdXQgfHwgIWNhY2hlZFNldFRpbWVvdXQpICYmIHNldFRpbWVvdXQpIHtcbiAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IHNldFRpbWVvdXQ7XG4gICAgICAgIHJldHVybiBzZXRUaW1lb3V0KGZ1biwgMCk7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIC8vIHdoZW4gd2hlbiBzb21lYm9keSBoYXMgc2NyZXdlZCB3aXRoIHNldFRpbWVvdXQgYnV0IG5vIEkuRS4gbWFkZG5lc3NcbiAgICAgICAgcmV0dXJuIGNhY2hlZFNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9IGNhdGNoKGUpe1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gV2hlbiB3ZSBhcmUgaW4gSS5FLiBidXQgdGhlIHNjcmlwdCBoYXMgYmVlbiBldmFsZWQgc28gSS5FLiBkb2Vzbid0IHRydXN0IHRoZSBnbG9iYWwgb2JqZWN0IHdoZW4gY2FsbGVkIG5vcm1hbGx5XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dC5jYWxsKG51bGwsIGZ1biwgMCk7XG4gICAgICAgIH0gY2F0Y2goZSl7XG4gICAgICAgICAgICAvLyBzYW1lIGFzIGFib3ZlIGJ1dCB3aGVuIGl0J3MgYSB2ZXJzaW9uIG9mIEkuRS4gdGhhdCBtdXN0IGhhdmUgdGhlIGdsb2JhbCBvYmplY3QgZm9yICd0aGlzJywgaG9wZnVsbHkgb3VyIGNvbnRleHQgY29ycmVjdCBvdGhlcndpc2UgaXQgd2lsbCB0aHJvdyBhIGdsb2JhbCBlcnJvclxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZFNldFRpbWVvdXQuY2FsbCh0aGlzLCBmdW4sIDApO1xuICAgICAgICB9XG4gICAgfVxuXG5cbn1cbmZ1bmN0aW9uIHJ1bkNsZWFyVGltZW91dChtYXJrZXIpIHtcbiAgICBpZiAoY2FjaGVkQ2xlYXJUaW1lb3V0ID09PSBjbGVhclRpbWVvdXQpIHtcbiAgICAgICAgLy9ub3JtYWwgZW52aXJvbWVudHMgaW4gc2FuZSBzaXR1YXRpb25zXG4gICAgICAgIHJldHVybiBjbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9XG4gICAgLy8gaWYgY2xlYXJUaW1lb3V0IHdhc24ndCBhdmFpbGFibGUgYnV0IHdhcyBsYXR0ZXIgZGVmaW5lZFxuICAgIGlmICgoY2FjaGVkQ2xlYXJUaW1lb3V0ID09PSBkZWZhdWx0Q2xlYXJUaW1lb3V0IHx8ICFjYWNoZWRDbGVhclRpbWVvdXQpICYmIGNsZWFyVGltZW91dCkge1xuICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBjbGVhclRpbWVvdXQ7XG4gICAgICAgIHJldHVybiBjbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgLy8gd2hlbiB3aGVuIHNvbWVib2R5IGhhcyBzY3Jld2VkIHdpdGggc2V0VGltZW91dCBidXQgbm8gSS5FLiBtYWRkbmVzc1xuICAgICAgICByZXR1cm4gY2FjaGVkQ2xlYXJUaW1lb3V0KG1hcmtlcik7XG4gICAgfSBjYXRjaCAoZSl7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBpbiBJLkUuIGJ1dCB0aGUgc2NyaXB0IGhhcyBiZWVuIGV2YWxlZCBzbyBJLkUuIGRvZXNuJ3QgIHRydXN0IHRoZSBnbG9iYWwgb2JqZWN0IHdoZW4gY2FsbGVkIG5vcm1hbGx5XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkQ2xlYXJUaW1lb3V0LmNhbGwobnVsbCwgbWFya2VyKTtcbiAgICAgICAgfSBjYXRjaCAoZSl7XG4gICAgICAgICAgICAvLyBzYW1lIGFzIGFib3ZlIGJ1dCB3aGVuIGl0J3MgYSB2ZXJzaW9uIG9mIEkuRS4gdGhhdCBtdXN0IGhhdmUgdGhlIGdsb2JhbCBvYmplY3QgZm9yICd0aGlzJywgaG9wZnVsbHkgb3VyIGNvbnRleHQgY29ycmVjdCBvdGhlcndpc2UgaXQgd2lsbCB0aHJvdyBhIGdsb2JhbCBlcnJvci5cbiAgICAgICAgICAgIC8vIFNvbWUgdmVyc2lvbnMgb2YgSS5FLiBoYXZlIGRpZmZlcmVudCBydWxlcyBmb3IgY2xlYXJUaW1lb3V0IHZzIHNldFRpbWVvdXRcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQuY2FsbCh0aGlzLCBtYXJrZXIpO1xuICAgICAgICB9XG4gICAgfVxuXG5cblxufVxudmFyIHF1ZXVlID0gW107XG52YXIgZHJhaW5pbmcgPSBmYWxzZTtcbnZhciBjdXJyZW50UXVldWU7XG52YXIgcXVldWVJbmRleCA9IC0xO1xuXG5mdW5jdGlvbiBjbGVhblVwTmV4dFRpY2soKSB7XG4gICAgaWYgKCFkcmFpbmluZyB8fCAhY3VycmVudFF1ZXVlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbiAgICBpZiAoY3VycmVudFF1ZXVlLmxlbmd0aCkge1xuICAgICAgICBxdWV1ZSA9IGN1cnJlbnRRdWV1ZS5jb25jYXQocXVldWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHF1ZXVlSW5kZXggPSAtMTtcbiAgICB9XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCkge1xuICAgICAgICBkcmFpblF1ZXVlKCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkcmFpblF1ZXVlKCkge1xuICAgIGlmIChkcmFpbmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciB0aW1lb3V0ID0gcnVuVGltZW91dChjbGVhblVwTmV4dFRpY2spO1xuICAgIGRyYWluaW5nID0gdHJ1ZTtcblxuICAgIHZhciBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgd2hpbGUobGVuKSB7XG4gICAgICAgIGN1cnJlbnRRdWV1ZSA9IHF1ZXVlO1xuICAgICAgICBxdWV1ZSA9IFtdO1xuICAgICAgICB3aGlsZSAoKytxdWV1ZUluZGV4IDwgbGVuKSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudFF1ZXVlKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudFF1ZXVlW3F1ZXVlSW5kZXhdLnJ1bigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHF1ZXVlSW5kZXggPSAtMTtcbiAgICAgICAgbGVuID0gcXVldWUubGVuZ3RoO1xuICAgIH1cbiAgICBjdXJyZW50UXVldWUgPSBudWxsO1xuICAgIGRyYWluaW5nID0gZmFsc2U7XG4gICAgcnVuQ2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xufVxuXG5wcm9jZXNzLm5leHRUaWNrID0gZnVuY3Rpb24gKGZ1bikge1xuICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGggLSAxKTtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgICB9XG4gICAgfVxuICAgIHF1ZXVlLnB1c2gobmV3IEl0ZW0oZnVuLCBhcmdzKSk7XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCA9PT0gMSAmJiAhZHJhaW5pbmcpIHtcbiAgICAgICAgcnVuVGltZW91dChkcmFpblF1ZXVlKTtcbiAgICB9XG59O1xuXG4vLyB2OCBsaWtlcyBwcmVkaWN0aWJsZSBvYmplY3RzXG5mdW5jdGlvbiBJdGVtKGZ1biwgYXJyYXkpIHtcbiAgICB0aGlzLmZ1biA9IGZ1bjtcbiAgICB0aGlzLmFycmF5ID0gYXJyYXk7XG59XG5JdGVtLnByb3RvdHlwZS5ydW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5mdW4uYXBwbHkobnVsbCwgdGhpcy5hcnJheSk7XG59O1xucHJvY2Vzcy50aXRsZSA9ICdicm93c2VyJztcbnByb2Nlc3MuYnJvd3NlciA9IHRydWU7XG5wcm9jZXNzLmVudiA9IHt9O1xucHJvY2Vzcy5hcmd2ID0gW107XG5wcm9jZXNzLnZlcnNpb24gPSAnJzsgLy8gZW1wdHkgc3RyaW5nIHRvIGF2b2lkIHJlZ2V4cCBpc3N1ZXNcbnByb2Nlc3MudmVyc2lvbnMgPSB7fTtcblxuZnVuY3Rpb24gbm9vcCgpIHt9XG5cbnByb2Nlc3Mub24gPSBub29wO1xucHJvY2Vzcy5hZGRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLm9uY2UgPSBub29wO1xucHJvY2Vzcy5vZmYgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUFsbExpc3RlbmVycyA9IG5vb3A7XG5wcm9jZXNzLmVtaXQgPSBub29wO1xucHJvY2Vzcy5wcmVwZW5kTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5wcmVwZW5kT25jZUxpc3RlbmVyID0gbm9vcDtcblxucHJvY2Vzcy5saXN0ZW5lcnMgPSBmdW5jdGlvbiAobmFtZSkgeyByZXR1cm4gW10gfVxuXG5wcm9jZXNzLmJpbmRpbmcgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5iaW5kaW5nIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5cbnByb2Nlc3MuY3dkID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gJy8nIH07XG5wcm9jZXNzLmNoZGlyID0gZnVuY3Rpb24gKGRpcikge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5jaGRpciBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xucHJvY2Vzcy51bWFzayA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gMDsgfTtcbiIsIi8qXG4gKiAgQ29weXJpZ2h0IChjKSAyMDE3IFRoZSBXZWJSVEMgcHJvamVjdCBhdXRob3JzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqICBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhIEJTRC1zdHlsZSBsaWNlbnNlXG4gKiAgdGhhdCBjYW4gYmUgZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBvZiB0aGUgc291cmNlXG4gKiAgdHJlZS5cbiAqL1xuIC8qIGVzbGludC1lbnYgbm9kZSAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgU0RQVXRpbHMgPSByZXF1aXJlKCdzZHAnKTtcblxuZnVuY3Rpb24gd3JpdGVNZWRpYVNlY3Rpb24odHJhbnNjZWl2ZXIsIGNhcHMsIHR5cGUsIHN0cmVhbSwgZHRsc1JvbGUpIHtcbiAgdmFyIHNkcCA9IFNEUFV0aWxzLndyaXRlUnRwRGVzY3JpcHRpb24odHJhbnNjZWl2ZXIua2luZCwgY2Fwcyk7XG5cbiAgLy8gTWFwIElDRSBwYXJhbWV0ZXJzICh1ZnJhZywgcHdkKSB0byBTRFAuXG4gIHNkcCArPSBTRFBVdGlscy53cml0ZUljZVBhcmFtZXRlcnMoXG4gICAgICB0cmFuc2NlaXZlci5pY2VHYXRoZXJlci5nZXRMb2NhbFBhcmFtZXRlcnMoKSk7XG5cbiAgLy8gTWFwIERUTFMgcGFyYW1ldGVycyB0byBTRFAuXG4gIHNkcCArPSBTRFBVdGlscy53cml0ZUR0bHNQYXJhbWV0ZXJzKFxuICAgICAgdHJhbnNjZWl2ZXIuZHRsc1RyYW5zcG9ydC5nZXRMb2NhbFBhcmFtZXRlcnMoKSxcbiAgICAgIHR5cGUgPT09ICdvZmZlcicgPyAnYWN0cGFzcycgOiBkdGxzUm9sZSB8fCAnYWN0aXZlJyk7XG5cbiAgc2RwICs9ICdhPW1pZDonICsgdHJhbnNjZWl2ZXIubWlkICsgJ1xcclxcbic7XG5cbiAgaWYgKHRyYW5zY2VpdmVyLnJ0cFNlbmRlciAmJiB0cmFuc2NlaXZlci5ydHBSZWNlaXZlcikge1xuICAgIHNkcCArPSAnYT1zZW5kcmVjdlxcclxcbic7XG4gIH0gZWxzZSBpZiAodHJhbnNjZWl2ZXIucnRwU2VuZGVyKSB7XG4gICAgc2RwICs9ICdhPXNlbmRvbmx5XFxyXFxuJztcbiAgfSBlbHNlIGlmICh0cmFuc2NlaXZlci5ydHBSZWNlaXZlcikge1xuICAgIHNkcCArPSAnYT1yZWN2b25seVxcclxcbic7XG4gIH0gZWxzZSB7XG4gICAgc2RwICs9ICdhPWluYWN0aXZlXFxyXFxuJztcbiAgfVxuXG4gIGlmICh0cmFuc2NlaXZlci5ydHBTZW5kZXIpIHtcbiAgICB2YXIgdHJhY2tJZCA9IHRyYW5zY2VpdmVyLnJ0cFNlbmRlci5faW5pdGlhbFRyYWNrSWQgfHxcbiAgICAgICAgdHJhbnNjZWl2ZXIucnRwU2VuZGVyLnRyYWNrLmlkO1xuICAgIHRyYW5zY2VpdmVyLnJ0cFNlbmRlci5faW5pdGlhbFRyYWNrSWQgPSB0cmFja0lkO1xuICAgIC8vIHNwZWMuXG4gICAgdmFyIG1zaWQgPSAnbXNpZDonICsgKHN0cmVhbSA/IHN0cmVhbS5pZCA6ICctJykgKyAnICcgK1xuICAgICAgICB0cmFja0lkICsgJ1xcclxcbic7XG4gICAgc2RwICs9ICdhPScgKyBtc2lkO1xuICAgIC8vIGZvciBDaHJvbWUuIExlZ2FjeSBzaG91bGQgbm8gbG9uZ2VyIGJlIHJlcXVpcmVkLlxuICAgIHNkcCArPSAnYT1zc3JjOicgKyB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzWzBdLnNzcmMgK1xuICAgICAgICAnICcgKyBtc2lkO1xuXG4gICAgLy8gUlRYXG4gICAgaWYgKHRyYW5zY2VpdmVyLnNlbmRFbmNvZGluZ1BhcmFtZXRlcnNbMF0ucnR4KSB7XG4gICAgICBzZHAgKz0gJ2E9c3NyYzonICsgdHJhbnNjZWl2ZXIuc2VuZEVuY29kaW5nUGFyYW1ldGVyc1swXS5ydHguc3NyYyArXG4gICAgICAgICAgJyAnICsgbXNpZDtcbiAgICAgIHNkcCArPSAnYT1zc3JjLWdyb3VwOkZJRCAnICtcbiAgICAgICAgICB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzWzBdLnNzcmMgKyAnICcgK1xuICAgICAgICAgIHRyYW5zY2VpdmVyLnNlbmRFbmNvZGluZ1BhcmFtZXRlcnNbMF0ucnR4LnNzcmMgK1xuICAgICAgICAgICdcXHJcXG4nO1xuICAgIH1cbiAgfVxuICAvLyBGSVhNRTogdGhpcyBzaG91bGQgYmUgd3JpdHRlbiBieSB3cml0ZVJ0cERlc2NyaXB0aW9uLlxuICBzZHAgKz0gJ2E9c3NyYzonICsgdHJhbnNjZWl2ZXIuc2VuZEVuY29kaW5nUGFyYW1ldGVyc1swXS5zc3JjICtcbiAgICAgICcgY25hbWU6JyArIFNEUFV0aWxzLmxvY2FsQ05hbWUgKyAnXFxyXFxuJztcbiAgaWYgKHRyYW5zY2VpdmVyLnJ0cFNlbmRlciAmJiB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzWzBdLnJ0eCkge1xuICAgIHNkcCArPSAnYT1zc3JjOicgKyB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzWzBdLnJ0eC5zc3JjICtcbiAgICAgICAgJyBjbmFtZTonICsgU0RQVXRpbHMubG9jYWxDTmFtZSArICdcXHJcXG4nO1xuICB9XG4gIHJldHVybiBzZHA7XG59XG5cbi8vIEVkZ2UgZG9lcyBub3QgbGlrZVxuLy8gMSkgc3R1bjogZmlsdGVyZWQgYWZ0ZXIgMTQzOTMgdW5sZXNzID90cmFuc3BvcnQ9dWRwIGlzIHByZXNlbnRcbi8vIDIpIHR1cm46IHRoYXQgZG9lcyBub3QgaGF2ZSBhbGwgb2YgdHVybjpob3N0OnBvcnQ/dHJhbnNwb3J0PXVkcFxuLy8gMykgdHVybjogd2l0aCBpcHY2IGFkZHJlc3Nlc1xuLy8gNCkgdHVybjogb2NjdXJyaW5nIG11bGlwbGUgdGltZXNcbmZ1bmN0aW9uIGZpbHRlckljZVNlcnZlcnMoaWNlU2VydmVycywgZWRnZVZlcnNpb24pIHtcbiAgdmFyIGhhc1R1cm4gPSBmYWxzZTtcbiAgaWNlU2VydmVycyA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoaWNlU2VydmVycykpO1xuICByZXR1cm4gaWNlU2VydmVycy5maWx0ZXIoZnVuY3Rpb24oc2VydmVyKSB7XG4gICAgaWYgKHNlcnZlciAmJiAoc2VydmVyLnVybHMgfHwgc2VydmVyLnVybCkpIHtcbiAgICAgIHZhciB1cmxzID0gc2VydmVyLnVybHMgfHwgc2VydmVyLnVybDtcbiAgICAgIGlmIChzZXJ2ZXIudXJsICYmICFzZXJ2ZXIudXJscykge1xuICAgICAgICBjb25zb2xlLndhcm4oJ1JUQ0ljZVNlcnZlci51cmwgaXMgZGVwcmVjYXRlZCEgVXNlIHVybHMgaW5zdGVhZC4nKTtcbiAgICAgIH1cbiAgICAgIHZhciBpc1N0cmluZyA9IHR5cGVvZiB1cmxzID09PSAnc3RyaW5nJztcbiAgICAgIGlmIChpc1N0cmluZykge1xuICAgICAgICB1cmxzID0gW3VybHNdO1xuICAgICAgfVxuICAgICAgdXJscyA9IHVybHMuZmlsdGVyKGZ1bmN0aW9uKHVybCkge1xuICAgICAgICB2YXIgdmFsaWRUdXJuID0gdXJsLmluZGV4T2YoJ3R1cm46JykgPT09IDAgJiZcbiAgICAgICAgICAgIHVybC5pbmRleE9mKCd0cmFuc3BvcnQ9dWRwJykgIT09IC0xICYmXG4gICAgICAgICAgICB1cmwuaW5kZXhPZigndHVybjpbJykgPT09IC0xICYmXG4gICAgICAgICAgICAhaGFzVHVybjtcblxuICAgICAgICBpZiAodmFsaWRUdXJuKSB7XG4gICAgICAgICAgaGFzVHVybiA9IHRydWU7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVybC5pbmRleE9mKCdzdHVuOicpID09PSAwICYmIGVkZ2VWZXJzaW9uID49IDE0MzkzICYmXG4gICAgICAgICAgICB1cmwuaW5kZXhPZignP3RyYW5zcG9ydD11ZHAnKSA9PT0gLTE7XG4gICAgICB9KTtcblxuICAgICAgZGVsZXRlIHNlcnZlci51cmw7XG4gICAgICBzZXJ2ZXIudXJscyA9IGlzU3RyaW5nID8gdXJsc1swXSA6IHVybHM7XG4gICAgICByZXR1cm4gISF1cmxzLmxlbmd0aDtcbiAgICB9XG4gIH0pO1xufVxuXG4vLyBEZXRlcm1pbmVzIHRoZSBpbnRlcnNlY3Rpb24gb2YgbG9jYWwgYW5kIHJlbW90ZSBjYXBhYmlsaXRpZXMuXG5mdW5jdGlvbiBnZXRDb21tb25DYXBhYmlsaXRpZXMobG9jYWxDYXBhYmlsaXRpZXMsIHJlbW90ZUNhcGFiaWxpdGllcykge1xuICB2YXIgY29tbW9uQ2FwYWJpbGl0aWVzID0ge1xuICAgIGNvZGVjczogW10sXG4gICAgaGVhZGVyRXh0ZW5zaW9uczogW10sXG4gICAgZmVjTWVjaGFuaXNtczogW11cbiAgfTtcblxuICB2YXIgZmluZENvZGVjQnlQYXlsb2FkVHlwZSA9IGZ1bmN0aW9uKHB0LCBjb2RlY3MpIHtcbiAgICBwdCA9IHBhcnNlSW50KHB0LCAxMCk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb2RlY3MubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChjb2RlY3NbaV0ucGF5bG9hZFR5cGUgPT09IHB0IHx8XG4gICAgICAgICAgY29kZWNzW2ldLnByZWZlcnJlZFBheWxvYWRUeXBlID09PSBwdCkge1xuICAgICAgICByZXR1cm4gY29kZWNzW2ldO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICB2YXIgcnR4Q2FwYWJpbGl0eU1hdGNoZXMgPSBmdW5jdGlvbihsUnR4LCByUnR4LCBsQ29kZWNzLCByQ29kZWNzKSB7XG4gICAgdmFyIGxDb2RlYyA9IGZpbmRDb2RlY0J5UGF5bG9hZFR5cGUobFJ0eC5wYXJhbWV0ZXJzLmFwdCwgbENvZGVjcyk7XG4gICAgdmFyIHJDb2RlYyA9IGZpbmRDb2RlY0J5UGF5bG9hZFR5cGUoclJ0eC5wYXJhbWV0ZXJzLmFwdCwgckNvZGVjcyk7XG4gICAgcmV0dXJuIGxDb2RlYyAmJiByQ29kZWMgJiZcbiAgICAgICAgbENvZGVjLm5hbWUudG9Mb3dlckNhc2UoKSA9PT0gckNvZGVjLm5hbWUudG9Mb3dlckNhc2UoKTtcbiAgfTtcblxuICBsb2NhbENhcGFiaWxpdGllcy5jb2RlY3MuZm9yRWFjaChmdW5jdGlvbihsQ29kZWMpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlbW90ZUNhcGFiaWxpdGllcy5jb2RlY3MubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciByQ29kZWMgPSByZW1vdGVDYXBhYmlsaXRpZXMuY29kZWNzW2ldO1xuICAgICAgaWYgKGxDb2RlYy5uYW1lLnRvTG93ZXJDYXNlKCkgPT09IHJDb2RlYy5uYW1lLnRvTG93ZXJDYXNlKCkgJiZcbiAgICAgICAgICBsQ29kZWMuY2xvY2tSYXRlID09PSByQ29kZWMuY2xvY2tSYXRlKSB7XG4gICAgICAgIGlmIChsQ29kZWMubmFtZS50b0xvd2VyQ2FzZSgpID09PSAncnR4JyAmJlxuICAgICAgICAgICAgbENvZGVjLnBhcmFtZXRlcnMgJiYgckNvZGVjLnBhcmFtZXRlcnMuYXB0KSB7XG4gICAgICAgICAgLy8gZm9yIFJUWCB3ZSBuZWVkIHRvIGZpbmQgdGhlIGxvY2FsIHJ0eCB0aGF0IGhhcyBhIGFwdFxuICAgICAgICAgIC8vIHdoaWNoIHBvaW50cyB0byB0aGUgc2FtZSBsb2NhbCBjb2RlYyBhcyB0aGUgcmVtb3RlIG9uZS5cbiAgICAgICAgICBpZiAoIXJ0eENhcGFiaWxpdHlNYXRjaGVzKGxDb2RlYywgckNvZGVjLFxuICAgICAgICAgICAgICBsb2NhbENhcGFiaWxpdGllcy5jb2RlY3MsIHJlbW90ZUNhcGFiaWxpdGllcy5jb2RlY3MpKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgckNvZGVjID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShyQ29kZWMpKTsgLy8gZGVlcGNvcHlcbiAgICAgICAgLy8gbnVtYmVyIG9mIGNoYW5uZWxzIGlzIHRoZSBoaWdoZXN0IGNvbW1vbiBudW1iZXIgb2YgY2hhbm5lbHNcbiAgICAgICAgckNvZGVjLm51bUNoYW5uZWxzID0gTWF0aC5taW4obENvZGVjLm51bUNoYW5uZWxzLFxuICAgICAgICAgICAgckNvZGVjLm51bUNoYW5uZWxzKTtcbiAgICAgICAgLy8gcHVzaCByQ29kZWMgc28gd2UgcmVwbHkgd2l0aCBvZmZlcmVyIHBheWxvYWQgdHlwZVxuICAgICAgICBjb21tb25DYXBhYmlsaXRpZXMuY29kZWNzLnB1c2gockNvZGVjKTtcblxuICAgICAgICAvLyBkZXRlcm1pbmUgY29tbW9uIGZlZWRiYWNrIG1lY2hhbmlzbXNcbiAgICAgICAgckNvZGVjLnJ0Y3BGZWVkYmFjayA9IHJDb2RlYy5ydGNwRmVlZGJhY2suZmlsdGVyKGZ1bmN0aW9uKGZiKSB7XG4gICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBsQ29kZWMucnRjcEZlZWRiYWNrLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBpZiAobENvZGVjLnJ0Y3BGZWVkYmFja1tqXS50eXBlID09PSBmYi50eXBlICYmXG4gICAgICAgICAgICAgICAgbENvZGVjLnJ0Y3BGZWVkYmFja1tqXS5wYXJhbWV0ZXIgPT09IGZiLnBhcmFtZXRlcikge1xuICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9KTtcbiAgICAgICAgLy8gRklYTUU6IGFsc28gbmVlZCB0byBkZXRlcm1pbmUgLnBhcmFtZXRlcnNcbiAgICAgICAgLy8gIHNlZSBodHRwczovL2dpdGh1Yi5jb20vb3BlbnBlZXIvb3J0Yy9pc3N1ZXMvNTY5XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgfSk7XG5cbiAgbG9jYWxDYXBhYmlsaXRpZXMuaGVhZGVyRXh0ZW5zaW9ucy5mb3JFYWNoKGZ1bmN0aW9uKGxIZWFkZXJFeHRlbnNpb24pIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlbW90ZUNhcGFiaWxpdGllcy5oZWFkZXJFeHRlbnNpb25zLmxlbmd0aDtcbiAgICAgICAgIGkrKykge1xuICAgICAgdmFyIHJIZWFkZXJFeHRlbnNpb24gPSByZW1vdGVDYXBhYmlsaXRpZXMuaGVhZGVyRXh0ZW5zaW9uc1tpXTtcbiAgICAgIGlmIChsSGVhZGVyRXh0ZW5zaW9uLnVyaSA9PT0gckhlYWRlckV4dGVuc2lvbi51cmkpIHtcbiAgICAgICAgY29tbW9uQ2FwYWJpbGl0aWVzLmhlYWRlckV4dGVuc2lvbnMucHVzaChySGVhZGVyRXh0ZW5zaW9uKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9KTtcblxuICAvLyBGSVhNRTogZmVjTWVjaGFuaXNtc1xuICByZXR1cm4gY29tbW9uQ2FwYWJpbGl0aWVzO1xufVxuXG4vLyBpcyBhY3Rpb249c2V0TG9jYWxEZXNjcmlwdGlvbiB3aXRoIHR5cGUgYWxsb3dlZCBpbiBzaWduYWxpbmdTdGF0ZVxuZnVuY3Rpb24gaXNBY3Rpb25BbGxvd2VkSW5TaWduYWxpbmdTdGF0ZShhY3Rpb24sIHR5cGUsIHNpZ25hbGluZ1N0YXRlKSB7XG4gIHJldHVybiB7XG4gICAgb2ZmZXI6IHtcbiAgICAgIHNldExvY2FsRGVzY3JpcHRpb246IFsnc3RhYmxlJywgJ2hhdmUtbG9jYWwtb2ZmZXInXSxcbiAgICAgIHNldFJlbW90ZURlc2NyaXB0aW9uOiBbJ3N0YWJsZScsICdoYXZlLXJlbW90ZS1vZmZlciddXG4gICAgfSxcbiAgICBhbnN3ZXI6IHtcbiAgICAgIHNldExvY2FsRGVzY3JpcHRpb246IFsnaGF2ZS1yZW1vdGUtb2ZmZXInLCAnaGF2ZS1sb2NhbC1wcmFuc3dlciddLFxuICAgICAgc2V0UmVtb3RlRGVzY3JpcHRpb246IFsnaGF2ZS1sb2NhbC1vZmZlcicsICdoYXZlLXJlbW90ZS1wcmFuc3dlciddXG4gICAgfVxuICB9W3R5cGVdW2FjdGlvbl0uaW5kZXhPZihzaWduYWxpbmdTdGF0ZSkgIT09IC0xO1xufVxuXG5mdW5jdGlvbiBtYXliZUFkZENhbmRpZGF0ZShpY2VUcmFuc3BvcnQsIGNhbmRpZGF0ZSkge1xuICAvLyBFZGdlJ3MgaW50ZXJuYWwgcmVwcmVzZW50YXRpb24gYWRkcyBzb21lIGZpZWxkcyB0aGVyZWZvcmVcbiAgLy8gbm90IGFsbCBmaWVsZNGVIGFyZSB0YWtlbiBpbnRvIGFjY291bnQuXG4gIHZhciBhbHJlYWR5QWRkZWQgPSBpY2VUcmFuc3BvcnQuZ2V0UmVtb3RlQ2FuZGlkYXRlcygpXG4gICAgICAuZmluZChmdW5jdGlvbihyZW1vdGVDYW5kaWRhdGUpIHtcbiAgICAgICAgcmV0dXJuIGNhbmRpZGF0ZS5mb3VuZGF0aW9uID09PSByZW1vdGVDYW5kaWRhdGUuZm91bmRhdGlvbiAmJlxuICAgICAgICAgICAgY2FuZGlkYXRlLmlwID09PSByZW1vdGVDYW5kaWRhdGUuaXAgJiZcbiAgICAgICAgICAgIGNhbmRpZGF0ZS5wb3J0ID09PSByZW1vdGVDYW5kaWRhdGUucG9ydCAmJlxuICAgICAgICAgICAgY2FuZGlkYXRlLnByaW9yaXR5ID09PSByZW1vdGVDYW5kaWRhdGUucHJpb3JpdHkgJiZcbiAgICAgICAgICAgIGNhbmRpZGF0ZS5wcm90b2NvbCA9PT0gcmVtb3RlQ2FuZGlkYXRlLnByb3RvY29sICYmXG4gICAgICAgICAgICBjYW5kaWRhdGUudHlwZSA9PT0gcmVtb3RlQ2FuZGlkYXRlLnR5cGU7XG4gICAgICB9KTtcbiAgaWYgKCFhbHJlYWR5QWRkZWQpIHtcbiAgICBpY2VUcmFuc3BvcnQuYWRkUmVtb3RlQ2FuZGlkYXRlKGNhbmRpZGF0ZSk7XG4gIH1cbiAgcmV0dXJuICFhbHJlYWR5QWRkZWQ7XG59XG5cblxuZnVuY3Rpb24gbWFrZUVycm9yKG5hbWUsIGRlc2NyaXB0aW9uKSB7XG4gIHZhciBlID0gbmV3IEVycm9yKGRlc2NyaXB0aW9uKTtcbiAgZS5uYW1lID0gbmFtZTtcbiAgLy8gbGVnYWN5IGVycm9yIGNvZGVzIGZyb20gaHR0cHM6Ly9oZXljYW0uZ2l0aHViLmlvL3dlYmlkbC8jaWRsLURPTUV4Y2VwdGlvbi1lcnJvci1uYW1lc1xuICBlLmNvZGUgPSB7XG4gICAgTm90U3VwcG9ydGVkRXJyb3I6IDksXG4gICAgSW52YWxpZFN0YXRlRXJyb3I6IDExLFxuICAgIEludmFsaWRBY2Nlc3NFcnJvcjogMTUsXG4gICAgVHlwZUVycm9yOiB1bmRlZmluZWQsXG4gICAgT3BlcmF0aW9uRXJyb3I6IHVuZGVmaW5lZFxuICB9W25hbWVdO1xuICByZXR1cm4gZTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbih3aW5kb3csIGVkZ2VWZXJzaW9uKSB7XG4gIC8vIGh0dHBzOi8vdzNjLmdpdGh1Yi5pby9tZWRpYWNhcHR1cmUtbWFpbi8jbWVkaWFzdHJlYW1cbiAgLy8gSGVscGVyIGZ1bmN0aW9uIHRvIGFkZCB0aGUgdHJhY2sgdG8gdGhlIHN0cmVhbSBhbmRcbiAgLy8gZGlzcGF0Y2ggdGhlIGV2ZW50IG91cnNlbHZlcy5cbiAgZnVuY3Rpb24gYWRkVHJhY2tUb1N0cmVhbUFuZEZpcmVFdmVudCh0cmFjaywgc3RyZWFtKSB7XG4gICAgc3RyZWFtLmFkZFRyYWNrKHRyYWNrKTtcbiAgICBzdHJlYW0uZGlzcGF0Y2hFdmVudChuZXcgd2luZG93Lk1lZGlhU3RyZWFtVHJhY2tFdmVudCgnYWRkdHJhY2snLFxuICAgICAgICB7dHJhY2s6IHRyYWNrfSkpO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVtb3ZlVHJhY2tGcm9tU3RyZWFtQW5kRmlyZUV2ZW50KHRyYWNrLCBzdHJlYW0pIHtcbiAgICBzdHJlYW0ucmVtb3ZlVHJhY2sodHJhY2spO1xuICAgIHN0cmVhbS5kaXNwYXRjaEV2ZW50KG5ldyB3aW5kb3cuTWVkaWFTdHJlYW1UcmFja0V2ZW50KCdyZW1vdmV0cmFjaycsXG4gICAgICAgIHt0cmFjazogdHJhY2t9KSk7XG4gIH1cblxuICBmdW5jdGlvbiBmaXJlQWRkVHJhY2socGMsIHRyYWNrLCByZWNlaXZlciwgc3RyZWFtcykge1xuICAgIHZhciB0cmFja0V2ZW50ID0gbmV3IEV2ZW50KCd0cmFjaycpO1xuICAgIHRyYWNrRXZlbnQudHJhY2sgPSB0cmFjaztcbiAgICB0cmFja0V2ZW50LnJlY2VpdmVyID0gcmVjZWl2ZXI7XG4gICAgdHJhY2tFdmVudC50cmFuc2NlaXZlciA9IHtyZWNlaXZlcjogcmVjZWl2ZXJ9O1xuICAgIHRyYWNrRXZlbnQuc3RyZWFtcyA9IHN0cmVhbXM7XG4gICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICBwYy5fZGlzcGF0Y2hFdmVudCgndHJhY2snLCB0cmFja0V2ZW50KTtcbiAgICB9KTtcbiAgfVxuXG4gIHZhciBSVENQZWVyQ29ubmVjdGlvbiA9IGZ1bmN0aW9uKGNvbmZpZykge1xuICAgIHZhciBwYyA9IHRoaXM7XG5cbiAgICB2YXIgX2V2ZW50VGFyZ2V0ID0gZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpO1xuICAgIFsnYWRkRXZlbnRMaXN0ZW5lcicsICdyZW1vdmVFdmVudExpc3RlbmVyJywgJ2Rpc3BhdGNoRXZlbnQnXVxuICAgICAgICAuZm9yRWFjaChmdW5jdGlvbihtZXRob2QpIHtcbiAgICAgICAgICBwY1ttZXRob2RdID0gX2V2ZW50VGFyZ2V0W21ldGhvZF0uYmluZChfZXZlbnRUYXJnZXQpO1xuICAgICAgICB9KTtcblxuICAgIHRoaXMuY2FuVHJpY2tsZUljZUNhbmRpZGF0ZXMgPSBudWxsO1xuXG4gICAgdGhpcy5uZWVkTmVnb3RpYXRpb24gPSBmYWxzZTtcblxuICAgIHRoaXMubG9jYWxTdHJlYW1zID0gW107XG4gICAgdGhpcy5yZW1vdGVTdHJlYW1zID0gW107XG5cbiAgICB0aGlzLmxvY2FsRGVzY3JpcHRpb24gPSBudWxsO1xuICAgIHRoaXMucmVtb3RlRGVzY3JpcHRpb24gPSBudWxsO1xuXG4gICAgdGhpcy5zaWduYWxpbmdTdGF0ZSA9ICdzdGFibGUnO1xuICAgIHRoaXMuaWNlQ29ubmVjdGlvblN0YXRlID0gJ25ldyc7XG4gICAgdGhpcy5jb25uZWN0aW9uU3RhdGUgPSAnbmV3JztcbiAgICB0aGlzLmljZUdhdGhlcmluZ1N0YXRlID0gJ25ldyc7XG5cbiAgICBjb25maWcgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGNvbmZpZyB8fCB7fSkpO1xuXG4gICAgdGhpcy51c2luZ0J1bmRsZSA9IGNvbmZpZy5idW5kbGVQb2xpY3kgPT09ICdtYXgtYnVuZGxlJztcbiAgICBpZiAoY29uZmlnLnJ0Y3BNdXhQb2xpY3kgPT09ICduZWdvdGlhdGUnKSB7XG4gICAgICB0aHJvdyhtYWtlRXJyb3IoJ05vdFN1cHBvcnRlZEVycm9yJyxcbiAgICAgICAgICAncnRjcE11eFBvbGljeSBcXCduZWdvdGlhdGVcXCcgaXMgbm90IHN1cHBvcnRlZCcpKTtcbiAgICB9IGVsc2UgaWYgKCFjb25maWcucnRjcE11eFBvbGljeSkge1xuICAgICAgY29uZmlnLnJ0Y3BNdXhQb2xpY3kgPSAncmVxdWlyZSc7XG4gICAgfVxuXG4gICAgc3dpdGNoIChjb25maWcuaWNlVHJhbnNwb3J0UG9saWN5KSB7XG4gICAgICBjYXNlICdhbGwnOlxuICAgICAgY2FzZSAncmVsYXknOlxuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGNvbmZpZy5pY2VUcmFuc3BvcnRQb2xpY3kgPSAnYWxsJztcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgc3dpdGNoIChjb25maWcuYnVuZGxlUG9saWN5KSB7XG4gICAgICBjYXNlICdiYWxhbmNlZCc6XG4gICAgICBjYXNlICdtYXgtY29tcGF0JzpcbiAgICAgIGNhc2UgJ21heC1idW5kbGUnOlxuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGNvbmZpZy5idW5kbGVQb2xpY3kgPSAnYmFsYW5jZWQnO1xuICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICBjb25maWcuaWNlU2VydmVycyA9IGZpbHRlckljZVNlcnZlcnMoY29uZmlnLmljZVNlcnZlcnMgfHwgW10sIGVkZ2VWZXJzaW9uKTtcblxuICAgIHRoaXMuX2ljZUdhdGhlcmVycyA9IFtdO1xuICAgIGlmIChjb25maWcuaWNlQ2FuZGlkYXRlUG9vbFNpemUpIHtcbiAgICAgIGZvciAodmFyIGkgPSBjb25maWcuaWNlQ2FuZGlkYXRlUG9vbFNpemU7IGkgPiAwOyBpLS0pIHtcbiAgICAgICAgdGhpcy5faWNlR2F0aGVyZXJzLnB1c2gobmV3IHdpbmRvdy5SVENJY2VHYXRoZXJlcih7XG4gICAgICAgICAgaWNlU2VydmVyczogY29uZmlnLmljZVNlcnZlcnMsXG4gICAgICAgICAgZ2F0aGVyUG9saWN5OiBjb25maWcuaWNlVHJhbnNwb3J0UG9saWN5XG4gICAgICAgIH0pKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29uZmlnLmljZUNhbmRpZGF0ZVBvb2xTaXplID0gMDtcbiAgICB9XG5cbiAgICB0aGlzLl9jb25maWcgPSBjb25maWc7XG5cbiAgICAvLyBwZXItdHJhY2sgaWNlR2F0aGVycywgaWNlVHJhbnNwb3J0cywgZHRsc1RyYW5zcG9ydHMsIHJ0cFNlbmRlcnMsIC4uLlxuICAgIC8vIGV2ZXJ5dGhpbmcgdGhhdCBpcyBuZWVkZWQgdG8gZGVzY3JpYmUgYSBTRFAgbS1saW5lLlxuICAgIHRoaXMudHJhbnNjZWl2ZXJzID0gW107XG5cbiAgICB0aGlzLl9zZHBTZXNzaW9uSWQgPSBTRFBVdGlscy5nZW5lcmF0ZVNlc3Npb25JZCgpO1xuICAgIHRoaXMuX3NkcFNlc3Npb25WZXJzaW9uID0gMDtcblxuICAgIHRoaXMuX2R0bHNSb2xlID0gdW5kZWZpbmVkOyAvLyByb2xlIGZvciBhPXNldHVwIHRvIHVzZSBpbiBhbnN3ZXJzLlxuXG4gICAgdGhpcy5faXNDbG9zZWQgPSBmYWxzZTtcbiAgfTtcblxuICAvLyBzZXQgdXAgZXZlbnQgaGFuZGxlcnMgb24gcHJvdG90eXBlXG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5vbmljZWNhbmRpZGF0ZSA9IG51bGw7XG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5vbmFkZHN0cmVhbSA9IG51bGw7XG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5vbnRyYWNrID0gbnVsbDtcbiAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLm9ucmVtb3Zlc3RyZWFtID0gbnVsbDtcbiAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLm9uc2lnbmFsaW5nc3RhdGVjaGFuZ2UgPSBudWxsO1xuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUub25pY2Vjb25uZWN0aW9uc3RhdGVjaGFuZ2UgPSBudWxsO1xuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUub25jb25uZWN0aW9uc3RhdGVjaGFuZ2UgPSBudWxsO1xuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUub25pY2VnYXRoZXJpbmdzdGF0ZWNoYW5nZSA9IG51bGw7XG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5vbm5lZ290aWF0aW9ubmVlZGVkID0gbnVsbDtcbiAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLm9uZGF0YWNoYW5uZWwgPSBudWxsO1xuXG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5fZGlzcGF0Y2hFdmVudCA9IGZ1bmN0aW9uKG5hbWUsIGV2ZW50KSB7XG4gICAgaWYgKHRoaXMuX2lzQ2xvc2VkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgaWYgKHR5cGVvZiB0aGlzWydvbicgKyBuYW1lXSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgdGhpc1snb24nICsgbmFtZV0oZXZlbnQpO1xuICAgIH1cbiAgfTtcblxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuX2VtaXRHYXRoZXJpbmdTdGF0ZUNoYW5nZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBldmVudCA9IG5ldyBFdmVudCgnaWNlZ2F0aGVyaW5nc3RhdGVjaGFuZ2UnKTtcbiAgICB0aGlzLl9kaXNwYXRjaEV2ZW50KCdpY2VnYXRoZXJpbmdzdGF0ZWNoYW5nZScsIGV2ZW50KTtcbiAgfTtcblxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuZ2V0Q29uZmlndXJhdGlvbiA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLl9jb25maWc7XG4gIH07XG5cbiAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmdldExvY2FsU3RyZWFtcyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmxvY2FsU3RyZWFtcztcbiAgfTtcblxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuZ2V0UmVtb3RlU3RyZWFtcyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLnJlbW90ZVN0cmVhbXM7XG4gIH07XG5cbiAgLy8gaW50ZXJuYWwgaGVscGVyIHRvIGNyZWF0ZSBhIHRyYW5zY2VpdmVyIG9iamVjdC5cbiAgLy8gKHdoaWNoIGlzIG5vdCB5ZXQgdGhlIHNhbWUgYXMgdGhlIFdlYlJUQyAxLjAgdHJhbnNjZWl2ZXIpXG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5fY3JlYXRlVHJhbnNjZWl2ZXIgPSBmdW5jdGlvbihraW5kLCBkb05vdEFkZCkge1xuICAgIHZhciBoYXNCdW5kbGVUcmFuc3BvcnQgPSB0aGlzLnRyYW5zY2VpdmVycy5sZW5ndGggPiAwO1xuICAgIHZhciB0cmFuc2NlaXZlciA9IHtcbiAgICAgIHRyYWNrOiBudWxsLFxuICAgICAgaWNlR2F0aGVyZXI6IG51bGwsXG4gICAgICBpY2VUcmFuc3BvcnQ6IG51bGwsXG4gICAgICBkdGxzVHJhbnNwb3J0OiBudWxsLFxuICAgICAgbG9jYWxDYXBhYmlsaXRpZXM6IG51bGwsXG4gICAgICByZW1vdGVDYXBhYmlsaXRpZXM6IG51bGwsXG4gICAgICBydHBTZW5kZXI6IG51bGwsXG4gICAgICBydHBSZWNlaXZlcjogbnVsbCxcbiAgICAgIGtpbmQ6IGtpbmQsXG4gICAgICBtaWQ6IG51bGwsXG4gICAgICBzZW5kRW5jb2RpbmdQYXJhbWV0ZXJzOiBudWxsLFxuICAgICAgcmVjdkVuY29kaW5nUGFyYW1ldGVyczogbnVsbCxcbiAgICAgIHN0cmVhbTogbnVsbCxcbiAgICAgIGFzc29jaWF0ZWRSZW1vdGVNZWRpYVN0cmVhbXM6IFtdLFxuICAgICAgd2FudFJlY2VpdmU6IHRydWVcbiAgICB9O1xuICAgIGlmICh0aGlzLnVzaW5nQnVuZGxlICYmIGhhc0J1bmRsZVRyYW5zcG9ydCkge1xuICAgICAgdHJhbnNjZWl2ZXIuaWNlVHJhbnNwb3J0ID0gdGhpcy50cmFuc2NlaXZlcnNbMF0uaWNlVHJhbnNwb3J0O1xuICAgICAgdHJhbnNjZWl2ZXIuZHRsc1RyYW5zcG9ydCA9IHRoaXMudHJhbnNjZWl2ZXJzWzBdLmR0bHNUcmFuc3BvcnQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciB0cmFuc3BvcnRzID0gdGhpcy5fY3JlYXRlSWNlQW5kRHRsc1RyYW5zcG9ydHMoKTtcbiAgICAgIHRyYW5zY2VpdmVyLmljZVRyYW5zcG9ydCA9IHRyYW5zcG9ydHMuaWNlVHJhbnNwb3J0O1xuICAgICAgdHJhbnNjZWl2ZXIuZHRsc1RyYW5zcG9ydCA9IHRyYW5zcG9ydHMuZHRsc1RyYW5zcG9ydDtcbiAgICB9XG4gICAgaWYgKCFkb05vdEFkZCkge1xuICAgICAgdGhpcy50cmFuc2NlaXZlcnMucHVzaCh0cmFuc2NlaXZlcik7XG4gICAgfVxuICAgIHJldHVybiB0cmFuc2NlaXZlcjtcbiAgfTtcblxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuYWRkVHJhY2sgPSBmdW5jdGlvbih0cmFjaywgc3RyZWFtKSB7XG4gICAgaWYgKHRoaXMuX2lzQ2xvc2VkKSB7XG4gICAgICB0aHJvdyBtYWtlRXJyb3IoJ0ludmFsaWRTdGF0ZUVycm9yJyxcbiAgICAgICAgICAnQXR0ZW1wdGVkIHRvIGNhbGwgYWRkVHJhY2sgb24gYSBjbG9zZWQgcGVlcmNvbm5lY3Rpb24uJyk7XG4gICAgfVxuXG4gICAgdmFyIGFscmVhZHlFeGlzdHMgPSB0aGlzLnRyYW5zY2VpdmVycy5maW5kKGZ1bmN0aW9uKHMpIHtcbiAgICAgIHJldHVybiBzLnRyYWNrID09PSB0cmFjaztcbiAgICB9KTtcblxuICAgIGlmIChhbHJlYWR5RXhpc3RzKSB7XG4gICAgICB0aHJvdyBtYWtlRXJyb3IoJ0ludmFsaWRBY2Nlc3NFcnJvcicsICdUcmFjayBhbHJlYWR5IGV4aXN0cy4nKTtcbiAgICB9XG5cbiAgICB2YXIgdHJhbnNjZWl2ZXI7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnRyYW5zY2VpdmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKCF0aGlzLnRyYW5zY2VpdmVyc1tpXS50cmFjayAmJlxuICAgICAgICAgIHRoaXMudHJhbnNjZWl2ZXJzW2ldLmtpbmQgPT09IHRyYWNrLmtpbmQpIHtcbiAgICAgICAgdHJhbnNjZWl2ZXIgPSB0aGlzLnRyYW5zY2VpdmVyc1tpXTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCF0cmFuc2NlaXZlcikge1xuICAgICAgdHJhbnNjZWl2ZXIgPSB0aGlzLl9jcmVhdGVUcmFuc2NlaXZlcih0cmFjay5raW5kKTtcbiAgICB9XG5cbiAgICB0aGlzLl9tYXliZUZpcmVOZWdvdGlhdGlvbk5lZWRlZCgpO1xuXG4gICAgaWYgKHRoaXMubG9jYWxTdHJlYW1zLmluZGV4T2Yoc3RyZWFtKSA9PT0gLTEpIHtcbiAgICAgIHRoaXMubG9jYWxTdHJlYW1zLnB1c2goc3RyZWFtKTtcbiAgICB9XG5cbiAgICB0cmFuc2NlaXZlci50cmFjayA9IHRyYWNrO1xuICAgIHRyYW5zY2VpdmVyLnN0cmVhbSA9IHN0cmVhbTtcbiAgICB0cmFuc2NlaXZlci5ydHBTZW5kZXIgPSBuZXcgd2luZG93LlJUQ1J0cFNlbmRlcih0cmFjayxcbiAgICAgICAgdHJhbnNjZWl2ZXIuZHRsc1RyYW5zcG9ydCk7XG4gICAgcmV0dXJuIHRyYW5zY2VpdmVyLnJ0cFNlbmRlcjtcbiAgfTtcblxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuYWRkU3RyZWFtID0gZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgdmFyIHBjID0gdGhpcztcbiAgICBpZiAoZWRnZVZlcnNpb24gPj0gMTUwMjUpIHtcbiAgICAgIHN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKGZ1bmN0aW9uKHRyYWNrKSB7XG4gICAgICAgIHBjLmFkZFRyYWNrKHRyYWNrLCBzdHJlYW0pO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIENsb25lIGlzIG5lY2Vzc2FyeSBmb3IgbG9jYWwgZGVtb3MgbW9zdGx5LCBhdHRhY2hpbmcgZGlyZWN0bHlcbiAgICAgIC8vIHRvIHR3byBkaWZmZXJlbnQgc2VuZGVycyBkb2VzIG5vdCB3b3JrIChidWlsZCAxMDU0NykuXG4gICAgICAvLyBGaXhlZCBpbiAxNTAyNSAob3IgZWFybGllcilcbiAgICAgIHZhciBjbG9uZWRTdHJlYW0gPSBzdHJlYW0uY2xvbmUoKTtcbiAgICAgIHN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKGZ1bmN0aW9uKHRyYWNrLCBpZHgpIHtcbiAgICAgICAgdmFyIGNsb25lZFRyYWNrID0gY2xvbmVkU3RyZWFtLmdldFRyYWNrcygpW2lkeF07XG4gICAgICAgIHRyYWNrLmFkZEV2ZW50TGlzdGVuZXIoJ2VuYWJsZWQnLCBmdW5jdGlvbihldmVudCkge1xuICAgICAgICAgIGNsb25lZFRyYWNrLmVuYWJsZWQgPSBldmVudC5lbmFibGVkO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgICAgY2xvbmVkU3RyZWFtLmdldFRyYWNrcygpLmZvckVhY2goZnVuY3Rpb24odHJhY2spIHtcbiAgICAgICAgcGMuYWRkVHJhY2sodHJhY2ssIGNsb25lZFN0cmVhbSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH07XG5cbiAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnJlbW92ZVRyYWNrID0gZnVuY3Rpb24oc2VuZGVyKSB7XG4gICAgaWYgKHRoaXMuX2lzQ2xvc2VkKSB7XG4gICAgICB0aHJvdyBtYWtlRXJyb3IoJ0ludmFsaWRTdGF0ZUVycm9yJyxcbiAgICAgICAgICAnQXR0ZW1wdGVkIHRvIGNhbGwgcmVtb3ZlVHJhY2sgb24gYSBjbG9zZWQgcGVlcmNvbm5lY3Rpb24uJyk7XG4gICAgfVxuXG4gICAgaWYgKCEoc2VuZGVyIGluc3RhbmNlb2Ygd2luZG93LlJUQ1J0cFNlbmRlcikpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50IDEgb2YgUlRDUGVlckNvbm5lY3Rpb24ucmVtb3ZlVHJhY2sgJyArXG4gICAgICAgICAgJ2RvZXMgbm90IGltcGxlbWVudCBpbnRlcmZhY2UgUlRDUnRwU2VuZGVyLicpO1xuICAgIH1cblxuICAgIHZhciB0cmFuc2NlaXZlciA9IHRoaXMudHJhbnNjZWl2ZXJzLmZpbmQoZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIHQucnRwU2VuZGVyID09PSBzZW5kZXI7XG4gICAgfSk7XG5cbiAgICBpZiAoIXRyYW5zY2VpdmVyKSB7XG4gICAgICB0aHJvdyBtYWtlRXJyb3IoJ0ludmFsaWRBY2Nlc3NFcnJvcicsXG4gICAgICAgICAgJ1NlbmRlciB3YXMgbm90IGNyZWF0ZWQgYnkgdGhpcyBjb25uZWN0aW9uLicpO1xuICAgIH1cbiAgICB2YXIgc3RyZWFtID0gdHJhbnNjZWl2ZXIuc3RyZWFtO1xuXG4gICAgdHJhbnNjZWl2ZXIucnRwU2VuZGVyLnN0b3AoKTtcbiAgICB0cmFuc2NlaXZlci5ydHBTZW5kZXIgPSBudWxsO1xuICAgIHRyYW5zY2VpdmVyLnRyYWNrID0gbnVsbDtcbiAgICB0cmFuc2NlaXZlci5zdHJlYW0gPSBudWxsO1xuXG4gICAgLy8gcmVtb3ZlIHRoZSBzdHJlYW0gZnJvbSB0aGUgc2V0IG9mIGxvY2FsIHN0cmVhbXNcbiAgICB2YXIgbG9jYWxTdHJlYW1zID0gdGhpcy50cmFuc2NlaXZlcnMubWFwKGZ1bmN0aW9uKHQpIHtcbiAgICAgIHJldHVybiB0LnN0cmVhbTtcbiAgICB9KTtcbiAgICBpZiAobG9jYWxTdHJlYW1zLmluZGV4T2Yoc3RyZWFtKSA9PT0gLTEgJiZcbiAgICAgICAgdGhpcy5sb2NhbFN0cmVhbXMuaW5kZXhPZihzdHJlYW0pID4gLTEpIHtcbiAgICAgIHRoaXMubG9jYWxTdHJlYW1zLnNwbGljZSh0aGlzLmxvY2FsU3RyZWFtcy5pbmRleE9mKHN0cmVhbSksIDEpO1xuICAgIH1cblxuICAgIHRoaXMuX21heWJlRmlyZU5lZ290aWF0aW9uTmVlZGVkKCk7XG4gIH07XG5cbiAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnJlbW92ZVN0cmVhbSA9IGZ1bmN0aW9uKHN0cmVhbSkge1xuICAgIHZhciBwYyA9IHRoaXM7XG4gICAgc3RyZWFtLmdldFRyYWNrcygpLmZvckVhY2goZnVuY3Rpb24odHJhY2spIHtcbiAgICAgIHZhciBzZW5kZXIgPSBwYy5nZXRTZW5kZXJzKCkuZmluZChmdW5jdGlvbihzKSB7XG4gICAgICAgIHJldHVybiBzLnRyYWNrID09PSB0cmFjaztcbiAgICAgIH0pO1xuICAgICAgaWYgKHNlbmRlcikge1xuICAgICAgICBwYy5yZW1vdmVUcmFjayhzZW5kZXIpO1xuICAgICAgfVxuICAgIH0pO1xuICB9O1xuXG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5nZXRTZW5kZXJzID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMudHJhbnNjZWl2ZXJzLmZpbHRlcihmdW5jdGlvbih0cmFuc2NlaXZlcikge1xuICAgICAgcmV0dXJuICEhdHJhbnNjZWl2ZXIucnRwU2VuZGVyO1xuICAgIH0pXG4gICAgLm1hcChmdW5jdGlvbih0cmFuc2NlaXZlcikge1xuICAgICAgcmV0dXJuIHRyYW5zY2VpdmVyLnJ0cFNlbmRlcjtcbiAgICB9KTtcbiAgfTtcblxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuZ2V0UmVjZWl2ZXJzID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMudHJhbnNjZWl2ZXJzLmZpbHRlcihmdW5jdGlvbih0cmFuc2NlaXZlcikge1xuICAgICAgcmV0dXJuICEhdHJhbnNjZWl2ZXIucnRwUmVjZWl2ZXI7XG4gICAgfSlcbiAgICAubWFwKGZ1bmN0aW9uKHRyYW5zY2VpdmVyKSB7XG4gICAgICByZXR1cm4gdHJhbnNjZWl2ZXIucnRwUmVjZWl2ZXI7XG4gICAgfSk7XG4gIH07XG5cblxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuX2NyZWF0ZUljZUdhdGhlcmVyID0gZnVuY3Rpb24oc2RwTUxpbmVJbmRleCxcbiAgICAgIHVzaW5nQnVuZGxlKSB7XG4gICAgdmFyIHBjID0gdGhpcztcbiAgICBpZiAodXNpbmdCdW5kbGUgJiYgc2RwTUxpbmVJbmRleCA+IDApIHtcbiAgICAgIHJldHVybiB0aGlzLnRyYW5zY2VpdmVyc1swXS5pY2VHYXRoZXJlcjtcbiAgICB9IGVsc2UgaWYgKHRoaXMuX2ljZUdhdGhlcmVycy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9pY2VHYXRoZXJlcnMuc2hpZnQoKTtcbiAgICB9XG4gICAgdmFyIGljZUdhdGhlcmVyID0gbmV3IHdpbmRvdy5SVENJY2VHYXRoZXJlcih7XG4gICAgICBpY2VTZXJ2ZXJzOiB0aGlzLl9jb25maWcuaWNlU2VydmVycyxcbiAgICAgIGdhdGhlclBvbGljeTogdGhpcy5fY29uZmlnLmljZVRyYW5zcG9ydFBvbGljeVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShpY2VHYXRoZXJlciwgJ3N0YXRlJyxcbiAgICAgICAge3ZhbHVlOiAnbmV3Jywgd3JpdGFibGU6IHRydWV9XG4gICAgKTtcblxuICAgIHRoaXMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLmJ1ZmZlcmVkQ2FuZGlkYXRlRXZlbnRzID0gW107XG4gICAgdGhpcy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF0uYnVmZmVyQ2FuZGlkYXRlcyA9IGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICB2YXIgZW5kID0gIWV2ZW50LmNhbmRpZGF0ZSB8fCBPYmplY3Qua2V5cyhldmVudC5jYW5kaWRhdGUpLmxlbmd0aCA9PT0gMDtcbiAgICAgIC8vIHBvbHlmaWxsIHNpbmNlIFJUQ0ljZUdhdGhlcmVyLnN0YXRlIGlzIG5vdCBpbXBsZW1lbnRlZCBpblxuICAgICAgLy8gRWRnZSAxMDU0NyB5ZXQuXG4gICAgICBpY2VHYXRoZXJlci5zdGF0ZSA9IGVuZCA/ICdjb21wbGV0ZWQnIDogJ2dhdGhlcmluZyc7XG4gICAgICBpZiAocGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLmJ1ZmZlcmVkQ2FuZGlkYXRlRXZlbnRzICE9PSBudWxsKSB7XG4gICAgICAgIHBjLnRyYW5zY2VpdmVyc1tzZHBNTGluZUluZGV4XS5idWZmZXJlZENhbmRpZGF0ZUV2ZW50cy5wdXNoKGV2ZW50KTtcbiAgICAgIH1cbiAgICB9O1xuICAgIGljZUdhdGhlcmVyLmFkZEV2ZW50TGlzdGVuZXIoJ2xvY2FsY2FuZGlkYXRlJyxcbiAgICAgIHRoaXMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLmJ1ZmZlckNhbmRpZGF0ZXMpO1xuICAgIHJldHVybiBpY2VHYXRoZXJlcjtcbiAgfTtcblxuICAvLyBzdGFydCBnYXRoZXJpbmcgZnJvbSBhbiBSVENJY2VHYXRoZXJlci5cbiAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLl9nYXRoZXIgPSBmdW5jdGlvbihtaWQsIHNkcE1MaW5lSW5kZXgpIHtcbiAgICB2YXIgcGMgPSB0aGlzO1xuICAgIHZhciBpY2VHYXRoZXJlciA9IHRoaXMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLmljZUdhdGhlcmVyO1xuICAgIGlmIChpY2VHYXRoZXJlci5vbmxvY2FsY2FuZGlkYXRlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciBidWZmZXJlZENhbmRpZGF0ZUV2ZW50cyA9XG4gICAgICB0aGlzLnRyYW5zY2VpdmVyc1tzZHBNTGluZUluZGV4XS5idWZmZXJlZENhbmRpZGF0ZUV2ZW50cztcbiAgICB0aGlzLnRyYW5zY2VpdmVyc1tzZHBNTGluZUluZGV4XS5idWZmZXJlZENhbmRpZGF0ZUV2ZW50cyA9IG51bGw7XG4gICAgaWNlR2F0aGVyZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcignbG9jYWxjYW5kaWRhdGUnLFxuICAgICAgdGhpcy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF0uYnVmZmVyQ2FuZGlkYXRlcyk7XG4gICAgaWNlR2F0aGVyZXIub25sb2NhbGNhbmRpZGF0ZSA9IGZ1bmN0aW9uKGV2dCkge1xuICAgICAgaWYgKHBjLnVzaW5nQnVuZGxlICYmIHNkcE1MaW5lSW5kZXggPiAwKSB7XG4gICAgICAgIC8vIGlmIHdlIGtub3cgdGhhdCB3ZSB1c2UgYnVuZGxlIHdlIGNhbiBkcm9wIGNhbmRpZGF0ZXMgd2l0aFxuICAgICAgICAvLyDRlWRwTUxpbmVJbmRleCA+IDAuIElmIHdlIGRvbid0IGRvIHRoaXMgdGhlbiBvdXIgc3RhdGUgZ2V0c1xuICAgICAgICAvLyBjb25mdXNlZCBzaW5jZSB3ZSBkaXNwb3NlIHRoZSBleHRyYSBpY2UgZ2F0aGVyZXIuXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHZhciBldmVudCA9IG5ldyBFdmVudCgnaWNlY2FuZGlkYXRlJyk7XG4gICAgICBldmVudC5jYW5kaWRhdGUgPSB7c2RwTWlkOiBtaWQsIHNkcE1MaW5lSW5kZXg6IHNkcE1MaW5lSW5kZXh9O1xuXG4gICAgICB2YXIgY2FuZCA9IGV2dC5jYW5kaWRhdGU7XG4gICAgICAvLyBFZGdlIGVtaXRzIGFuIGVtcHR5IG9iamVjdCBmb3IgUlRDSWNlQ2FuZGlkYXRlQ29tcGxldGXigKVcbiAgICAgIHZhciBlbmQgPSAhY2FuZCB8fCBPYmplY3Qua2V5cyhjYW5kKS5sZW5ndGggPT09IDA7XG4gICAgICBpZiAoZW5kKSB7XG4gICAgICAgIC8vIHBvbHlmaWxsIHNpbmNlIFJUQ0ljZUdhdGhlcmVyLnN0YXRlIGlzIG5vdCBpbXBsZW1lbnRlZCBpblxuICAgICAgICAvLyBFZGdlIDEwNTQ3IHlldC5cbiAgICAgICAgaWYgKGljZUdhdGhlcmVyLnN0YXRlID09PSAnbmV3JyB8fCBpY2VHYXRoZXJlci5zdGF0ZSA9PT0gJ2dhdGhlcmluZycpIHtcbiAgICAgICAgICBpY2VHYXRoZXJlci5zdGF0ZSA9ICdjb21wbGV0ZWQnO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoaWNlR2F0aGVyZXIuc3RhdGUgPT09ICduZXcnKSB7XG4gICAgICAgICAgaWNlR2F0aGVyZXIuc3RhdGUgPSAnZ2F0aGVyaW5nJztcbiAgICAgICAgfVxuICAgICAgICAvLyBSVENJY2VDYW5kaWRhdGUgZG9lc24ndCBoYXZlIGEgY29tcG9uZW50LCBuZWVkcyB0byBiZSBhZGRlZFxuICAgICAgICBjYW5kLmNvbXBvbmVudCA9IDE7XG4gICAgICAgIHZhciBzZXJpYWxpemVkQ2FuZGlkYXRlID0gU0RQVXRpbHMud3JpdGVDYW5kaWRhdGUoY2FuZCk7XG4gICAgICAgIGV2ZW50LmNhbmRpZGF0ZSA9IE9iamVjdC5hc3NpZ24oZXZlbnQuY2FuZGlkYXRlLFxuICAgICAgICAgICAgU0RQVXRpbHMucGFyc2VDYW5kaWRhdGUoc2VyaWFsaXplZENhbmRpZGF0ZSkpO1xuICAgICAgICBldmVudC5jYW5kaWRhdGUuY2FuZGlkYXRlID0gc2VyaWFsaXplZENhbmRpZGF0ZTtcbiAgICAgIH1cblxuICAgICAgLy8gdXBkYXRlIGxvY2FsIGRlc2NyaXB0aW9uLlxuICAgICAgdmFyIHNlY3Rpb25zID0gU0RQVXRpbHMuZ2V0TWVkaWFTZWN0aW9ucyhwYy5sb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICBpZiAoIWVuZCkge1xuICAgICAgICBzZWN0aW9uc1tldmVudC5jYW5kaWRhdGUuc2RwTUxpbmVJbmRleF0gKz1cbiAgICAgICAgICAgICdhPScgKyBldmVudC5jYW5kaWRhdGUuY2FuZGlkYXRlICsgJ1xcclxcbic7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZWN0aW9uc1tldmVudC5jYW5kaWRhdGUuc2RwTUxpbmVJbmRleF0gKz1cbiAgICAgICAgICAgICdhPWVuZC1vZi1jYW5kaWRhdGVzXFxyXFxuJztcbiAgICAgIH1cbiAgICAgIHBjLmxvY2FsRGVzY3JpcHRpb24uc2RwID1cbiAgICAgICAgICBTRFBVdGlscy5nZXREZXNjcmlwdGlvbihwYy5sb2NhbERlc2NyaXB0aW9uLnNkcCkgK1xuICAgICAgICAgIHNlY3Rpb25zLmpvaW4oJycpO1xuICAgICAgdmFyIGNvbXBsZXRlID0gcGMudHJhbnNjZWl2ZXJzLmV2ZXJ5KGZ1bmN0aW9uKHRyYW5zY2VpdmVyKSB7XG4gICAgICAgIHJldHVybiB0cmFuc2NlaXZlci5pY2VHYXRoZXJlciAmJlxuICAgICAgICAgICAgdHJhbnNjZWl2ZXIuaWNlR2F0aGVyZXIuc3RhdGUgPT09ICdjb21wbGV0ZWQnO1xuICAgICAgfSk7XG5cbiAgICAgIGlmIChwYy5pY2VHYXRoZXJpbmdTdGF0ZSAhPT0gJ2dhdGhlcmluZycpIHtcbiAgICAgICAgcGMuaWNlR2F0aGVyaW5nU3RhdGUgPSAnZ2F0aGVyaW5nJztcbiAgICAgICAgcGMuX2VtaXRHYXRoZXJpbmdTdGF0ZUNoYW5nZSgpO1xuICAgICAgfVxuXG4gICAgICAvLyBFbWl0IGNhbmRpZGF0ZS4gQWxzbyBlbWl0IG51bGwgY2FuZGlkYXRlIHdoZW4gYWxsIGdhdGhlcmVycyBhcmVcbiAgICAgIC8vIGNvbXBsZXRlLlxuICAgICAgaWYgKCFlbmQpIHtcbiAgICAgICAgcGMuX2Rpc3BhdGNoRXZlbnQoJ2ljZWNhbmRpZGF0ZScsIGV2ZW50KTtcbiAgICAgIH1cbiAgICAgIGlmIChjb21wbGV0ZSkge1xuICAgICAgICBwYy5fZGlzcGF0Y2hFdmVudCgnaWNlY2FuZGlkYXRlJywgbmV3IEV2ZW50KCdpY2VjYW5kaWRhdGUnKSk7XG4gICAgICAgIHBjLmljZUdhdGhlcmluZ1N0YXRlID0gJ2NvbXBsZXRlJztcbiAgICAgICAgcGMuX2VtaXRHYXRoZXJpbmdTdGF0ZUNoYW5nZSgpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICAvLyBlbWl0IGFscmVhZHkgZ2F0aGVyZWQgY2FuZGlkYXRlcy5cbiAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgIGJ1ZmZlcmVkQ2FuZGlkYXRlRXZlbnRzLmZvckVhY2goZnVuY3Rpb24oZSkge1xuICAgICAgICBpY2VHYXRoZXJlci5vbmxvY2FsY2FuZGlkYXRlKGUpO1xuICAgICAgfSk7XG4gICAgfSwgMCk7XG4gIH07XG5cbiAgLy8gQ3JlYXRlIElDRSB0cmFuc3BvcnQgYW5kIERUTFMgdHJhbnNwb3J0LlxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuX2NyZWF0ZUljZUFuZER0bHNUcmFuc3BvcnRzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHBjID0gdGhpcztcbiAgICB2YXIgaWNlVHJhbnNwb3J0ID0gbmV3IHdpbmRvdy5SVENJY2VUcmFuc3BvcnQobnVsbCk7XG4gICAgaWNlVHJhbnNwb3J0Lm9uaWNlc3RhdGVjaGFuZ2UgPSBmdW5jdGlvbigpIHtcbiAgICAgIHBjLl91cGRhdGVJY2VDb25uZWN0aW9uU3RhdGUoKTtcbiAgICAgIHBjLl91cGRhdGVDb25uZWN0aW9uU3RhdGUoKTtcbiAgICB9O1xuXG4gICAgdmFyIGR0bHNUcmFuc3BvcnQgPSBuZXcgd2luZG93LlJUQ0R0bHNUcmFuc3BvcnQoaWNlVHJhbnNwb3J0KTtcbiAgICBkdGxzVHJhbnNwb3J0Lm9uZHRsc3N0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG4gICAgICBwYy5fdXBkYXRlQ29ubmVjdGlvblN0YXRlKCk7XG4gICAgfTtcbiAgICBkdGxzVHJhbnNwb3J0Lm9uZXJyb3IgPSBmdW5jdGlvbigpIHtcbiAgICAgIC8vIG9uZXJyb3IgZG9lcyBub3Qgc2V0IHN0YXRlIHRvIGZhaWxlZCBieSBpdHNlbGYuXG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZHRsc1RyYW5zcG9ydCwgJ3N0YXRlJyxcbiAgICAgICAgICB7dmFsdWU6ICdmYWlsZWQnLCB3cml0YWJsZTogdHJ1ZX0pO1xuICAgICAgcGMuX3VwZGF0ZUNvbm5lY3Rpb25TdGF0ZSgpO1xuICAgIH07XG5cbiAgICByZXR1cm4ge1xuICAgICAgaWNlVHJhbnNwb3J0OiBpY2VUcmFuc3BvcnQsXG4gICAgICBkdGxzVHJhbnNwb3J0OiBkdGxzVHJhbnNwb3J0XG4gICAgfTtcbiAgfTtcblxuICAvLyBEZXN0cm95IElDRSBnYXRoZXJlciwgSUNFIHRyYW5zcG9ydCBhbmQgRFRMUyB0cmFuc3BvcnQuXG4gIC8vIFdpdGhvdXQgdHJpZ2dlcmluZyB0aGUgY2FsbGJhY2tzLlxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuX2Rpc3Bvc2VJY2VBbmREdGxzVHJhbnNwb3J0cyA9IGZ1bmN0aW9uKFxuICAgICAgc2RwTUxpbmVJbmRleCkge1xuICAgIHZhciBpY2VHYXRoZXJlciA9IHRoaXMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLmljZUdhdGhlcmVyO1xuICAgIGlmIChpY2VHYXRoZXJlcikge1xuICAgICAgZGVsZXRlIGljZUdhdGhlcmVyLm9ubG9jYWxjYW5kaWRhdGU7XG4gICAgICBkZWxldGUgdGhpcy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF0uaWNlR2F0aGVyZXI7XG4gICAgfVxuICAgIHZhciBpY2VUcmFuc3BvcnQgPSB0aGlzLnRyYW5zY2VpdmVyc1tzZHBNTGluZUluZGV4XS5pY2VUcmFuc3BvcnQ7XG4gICAgaWYgKGljZVRyYW5zcG9ydCkge1xuICAgICAgZGVsZXRlIGljZVRyYW5zcG9ydC5vbmljZXN0YXRlY2hhbmdlO1xuICAgICAgZGVsZXRlIHRoaXMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLmljZVRyYW5zcG9ydDtcbiAgICB9XG4gICAgdmFyIGR0bHNUcmFuc3BvcnQgPSB0aGlzLnRyYW5zY2VpdmVyc1tzZHBNTGluZUluZGV4XS5kdGxzVHJhbnNwb3J0O1xuICAgIGlmIChkdGxzVHJhbnNwb3J0KSB7XG4gICAgICBkZWxldGUgZHRsc1RyYW5zcG9ydC5vbmR0bHNzdGF0ZWNoYW5nZTtcbiAgICAgIGRlbGV0ZSBkdGxzVHJhbnNwb3J0Lm9uZXJyb3I7XG4gICAgICBkZWxldGUgdGhpcy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF0uZHRsc1RyYW5zcG9ydDtcbiAgICB9XG4gIH07XG5cbiAgLy8gU3RhcnQgdGhlIFJUUCBTZW5kZXIgYW5kIFJlY2VpdmVyIGZvciBhIHRyYW5zY2VpdmVyLlxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuX3RyYW5zY2VpdmUgPSBmdW5jdGlvbih0cmFuc2NlaXZlcixcbiAgICAgIHNlbmQsIHJlY3YpIHtcbiAgICB2YXIgcGFyYW1zID0gZ2V0Q29tbW9uQ2FwYWJpbGl0aWVzKHRyYW5zY2VpdmVyLmxvY2FsQ2FwYWJpbGl0aWVzLFxuICAgICAgICB0cmFuc2NlaXZlci5yZW1vdGVDYXBhYmlsaXRpZXMpO1xuICAgIGlmIChzZW5kICYmIHRyYW5zY2VpdmVyLnJ0cFNlbmRlcikge1xuICAgICAgcGFyYW1zLmVuY29kaW5ncyA9IHRyYW5zY2VpdmVyLnNlbmRFbmNvZGluZ1BhcmFtZXRlcnM7XG4gICAgICBwYXJhbXMucnRjcCA9IHtcbiAgICAgICAgY25hbWU6IFNEUFV0aWxzLmxvY2FsQ05hbWUsXG4gICAgICAgIGNvbXBvdW5kOiB0cmFuc2NlaXZlci5ydGNwUGFyYW1ldGVycy5jb21wb3VuZFxuICAgICAgfTtcbiAgICAgIGlmICh0cmFuc2NlaXZlci5yZWN2RW5jb2RpbmdQYXJhbWV0ZXJzLmxlbmd0aCkge1xuICAgICAgICBwYXJhbXMucnRjcC5zc3JjID0gdHJhbnNjZWl2ZXIucmVjdkVuY29kaW5nUGFyYW1ldGVyc1swXS5zc3JjO1xuICAgICAgfVxuICAgICAgdHJhbnNjZWl2ZXIucnRwU2VuZGVyLnNlbmQocGFyYW1zKTtcbiAgICB9XG4gICAgaWYgKHJlY3YgJiYgdHJhbnNjZWl2ZXIucnRwUmVjZWl2ZXIgJiYgcGFyYW1zLmNvZGVjcy5sZW5ndGggPiAwKSB7XG4gICAgICAvLyByZW1vdmUgUlRYIGZpZWxkIGluIEVkZ2UgMTQ5NDJcbiAgICAgIGlmICh0cmFuc2NlaXZlci5raW5kID09PSAndmlkZW8nXG4gICAgICAgICAgJiYgdHJhbnNjZWl2ZXIucmVjdkVuY29kaW5nUGFyYW1ldGVyc1xuICAgICAgICAgICYmIGVkZ2VWZXJzaW9uIDwgMTUwMTkpIHtcbiAgICAgICAgdHJhbnNjZWl2ZXIucmVjdkVuY29kaW5nUGFyYW1ldGVycy5mb3JFYWNoKGZ1bmN0aW9uKHApIHtcbiAgICAgICAgICBkZWxldGUgcC5ydHg7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgaWYgKHRyYW5zY2VpdmVyLnJlY3ZFbmNvZGluZ1BhcmFtZXRlcnMubGVuZ3RoKSB7XG4gICAgICAgIHBhcmFtcy5lbmNvZGluZ3MgPSB0cmFuc2NlaXZlci5yZWN2RW5jb2RpbmdQYXJhbWV0ZXJzO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGFyYW1zLmVuY29kaW5ncyA9IFt7fV07XG4gICAgICB9XG4gICAgICBwYXJhbXMucnRjcCA9IHtcbiAgICAgICAgY29tcG91bmQ6IHRyYW5zY2VpdmVyLnJ0Y3BQYXJhbWV0ZXJzLmNvbXBvdW5kXG4gICAgICB9O1xuICAgICAgaWYgKHRyYW5zY2VpdmVyLnJ0Y3BQYXJhbWV0ZXJzLmNuYW1lKSB7XG4gICAgICAgIHBhcmFtcy5ydGNwLmNuYW1lID0gdHJhbnNjZWl2ZXIucnRjcFBhcmFtZXRlcnMuY25hbWU7XG4gICAgICB9XG4gICAgICBpZiAodHJhbnNjZWl2ZXIuc2VuZEVuY29kaW5nUGFyYW1ldGVycy5sZW5ndGgpIHtcbiAgICAgICAgcGFyYW1zLnJ0Y3Auc3NyYyA9IHRyYW5zY2VpdmVyLnNlbmRFbmNvZGluZ1BhcmFtZXRlcnNbMF0uc3NyYztcbiAgICAgIH1cbiAgICAgIHRyYW5zY2VpdmVyLnJ0cFJlY2VpdmVyLnJlY2VpdmUocGFyYW1zKTtcbiAgICB9XG4gIH07XG5cbiAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnNldExvY2FsRGVzY3JpcHRpb24gPSBmdW5jdGlvbihkZXNjcmlwdGlvbikge1xuICAgIHZhciBwYyA9IHRoaXM7XG5cbiAgICAvLyBOb3RlOiBwcmFuc3dlciBpcyBub3Qgc3VwcG9ydGVkLlxuICAgIGlmIChbJ29mZmVyJywgJ2Fuc3dlciddLmluZGV4T2YoZGVzY3JpcHRpb24udHlwZSkgPT09IC0xKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobWFrZUVycm9yKCdUeXBlRXJyb3InLFxuICAgICAgICAgICdVbnN1cHBvcnRlZCB0eXBlIFwiJyArIGRlc2NyaXB0aW9uLnR5cGUgKyAnXCInKSk7XG4gICAgfVxuXG4gICAgaWYgKCFpc0FjdGlvbkFsbG93ZWRJblNpZ25hbGluZ1N0YXRlKCdzZXRMb2NhbERlc2NyaXB0aW9uJyxcbiAgICAgICAgZGVzY3JpcHRpb24udHlwZSwgcGMuc2lnbmFsaW5nU3RhdGUpIHx8IHBjLl9pc0Nsb3NlZCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG1ha2VFcnJvcignSW52YWxpZFN0YXRlRXJyb3InLFxuICAgICAgICAgICdDYW4gbm90IHNldCBsb2NhbCAnICsgZGVzY3JpcHRpb24udHlwZSArXG4gICAgICAgICAgJyBpbiBzdGF0ZSAnICsgcGMuc2lnbmFsaW5nU3RhdGUpKTtcbiAgICB9XG5cbiAgICB2YXIgc2VjdGlvbnM7XG4gICAgdmFyIHNlc3Npb25wYXJ0O1xuICAgIGlmIChkZXNjcmlwdGlvbi50eXBlID09PSAnb2ZmZXInKSB7XG4gICAgICAvLyBWRVJZIGxpbWl0ZWQgc3VwcG9ydCBmb3IgU0RQIG11bmdpbmcuIExpbWl0ZWQgdG86XG4gICAgICAvLyAqIGNoYW5naW5nIHRoZSBvcmRlciBvZiBjb2RlY3NcbiAgICAgIHNlY3Rpb25zID0gU0RQVXRpbHMuc3BsaXRTZWN0aW9ucyhkZXNjcmlwdGlvbi5zZHApO1xuICAgICAgc2Vzc2lvbnBhcnQgPSBzZWN0aW9ucy5zaGlmdCgpO1xuICAgICAgc2VjdGlvbnMuZm9yRWFjaChmdW5jdGlvbihtZWRpYVNlY3Rpb24sIHNkcE1MaW5lSW5kZXgpIHtcbiAgICAgICAgdmFyIGNhcHMgPSBTRFBVdGlscy5wYXJzZVJ0cFBhcmFtZXRlcnMobWVkaWFTZWN0aW9uKTtcbiAgICAgICAgcGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLmxvY2FsQ2FwYWJpbGl0aWVzID0gY2FwcztcbiAgICAgIH0pO1xuXG4gICAgICBwYy50cmFuc2NlaXZlcnMuZm9yRWFjaChmdW5jdGlvbih0cmFuc2NlaXZlciwgc2RwTUxpbmVJbmRleCkge1xuICAgICAgICBwYy5fZ2F0aGVyKHRyYW5zY2VpdmVyLm1pZCwgc2RwTUxpbmVJbmRleCk7XG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKGRlc2NyaXB0aW9uLnR5cGUgPT09ICdhbnN3ZXInKSB7XG4gICAgICBzZWN0aW9ucyA9IFNEUFV0aWxzLnNwbGl0U2VjdGlvbnMocGMucmVtb3RlRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgIHNlc3Npb25wYXJ0ID0gc2VjdGlvbnMuc2hpZnQoKTtcbiAgICAgIHZhciBpc0ljZUxpdGUgPSBTRFBVdGlscy5tYXRjaFByZWZpeChzZXNzaW9ucGFydCxcbiAgICAgICAgICAnYT1pY2UtbGl0ZScpLmxlbmd0aCA+IDA7XG4gICAgICBzZWN0aW9ucy5mb3JFYWNoKGZ1bmN0aW9uKG1lZGlhU2VjdGlvbiwgc2RwTUxpbmVJbmRleCkge1xuICAgICAgICB2YXIgdHJhbnNjZWl2ZXIgPSBwYy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF07XG4gICAgICAgIHZhciBpY2VHYXRoZXJlciA9IHRyYW5zY2VpdmVyLmljZUdhdGhlcmVyO1xuICAgICAgICB2YXIgaWNlVHJhbnNwb3J0ID0gdHJhbnNjZWl2ZXIuaWNlVHJhbnNwb3J0O1xuICAgICAgICB2YXIgZHRsc1RyYW5zcG9ydCA9IHRyYW5zY2VpdmVyLmR0bHNUcmFuc3BvcnQ7XG4gICAgICAgIHZhciBsb2NhbENhcGFiaWxpdGllcyA9IHRyYW5zY2VpdmVyLmxvY2FsQ2FwYWJpbGl0aWVzO1xuICAgICAgICB2YXIgcmVtb3RlQ2FwYWJpbGl0aWVzID0gdHJhbnNjZWl2ZXIucmVtb3RlQ2FwYWJpbGl0aWVzO1xuXG4gICAgICAgIC8vIHRyZWF0IGJ1bmRsZS1vbmx5IGFzIG5vdC1yZWplY3RlZC5cbiAgICAgICAgdmFyIHJlamVjdGVkID0gU0RQVXRpbHMuaXNSZWplY3RlZChtZWRpYVNlY3Rpb24pICYmXG4gICAgICAgICAgICBTRFBVdGlscy5tYXRjaFByZWZpeChtZWRpYVNlY3Rpb24sICdhPWJ1bmRsZS1vbmx5JykubGVuZ3RoID09PSAwO1xuXG4gICAgICAgIGlmICghcmVqZWN0ZWQgJiYgIXRyYW5zY2VpdmVyLnJlamVjdGVkKSB7XG4gICAgICAgICAgdmFyIHJlbW90ZUljZVBhcmFtZXRlcnMgPSBTRFBVdGlscy5nZXRJY2VQYXJhbWV0ZXJzKFxuICAgICAgICAgICAgICBtZWRpYVNlY3Rpb24sIHNlc3Npb25wYXJ0KTtcbiAgICAgICAgICB2YXIgcmVtb3RlRHRsc1BhcmFtZXRlcnMgPSBTRFBVdGlscy5nZXREdGxzUGFyYW1ldGVycyhcbiAgICAgICAgICAgICAgbWVkaWFTZWN0aW9uLCBzZXNzaW9ucGFydCk7XG4gICAgICAgICAgaWYgKGlzSWNlTGl0ZSkge1xuICAgICAgICAgICAgcmVtb3RlRHRsc1BhcmFtZXRlcnMucm9sZSA9ICdzZXJ2ZXInO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghcGMudXNpbmdCdW5kbGUgfHwgc2RwTUxpbmVJbmRleCA9PT0gMCkge1xuICAgICAgICAgICAgcGMuX2dhdGhlcih0cmFuc2NlaXZlci5taWQsIHNkcE1MaW5lSW5kZXgpO1xuICAgICAgICAgICAgaWYgKGljZVRyYW5zcG9ydC5zdGF0ZSA9PT0gJ25ldycpIHtcbiAgICAgICAgICAgICAgaWNlVHJhbnNwb3J0LnN0YXJ0KGljZUdhdGhlcmVyLCByZW1vdGVJY2VQYXJhbWV0ZXJzLFxuICAgICAgICAgICAgICAgICAgaXNJY2VMaXRlID8gJ2NvbnRyb2xsaW5nJyA6ICdjb250cm9sbGVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZHRsc1RyYW5zcG9ydC5zdGF0ZSA9PT0gJ25ldycpIHtcbiAgICAgICAgICAgICAgZHRsc1RyYW5zcG9ydC5zdGFydChyZW1vdGVEdGxzUGFyYW1ldGVycyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gQ2FsY3VsYXRlIGludGVyc2VjdGlvbiBvZiBjYXBhYmlsaXRpZXMuXG4gICAgICAgICAgdmFyIHBhcmFtcyA9IGdldENvbW1vbkNhcGFiaWxpdGllcyhsb2NhbENhcGFiaWxpdGllcyxcbiAgICAgICAgICAgICAgcmVtb3RlQ2FwYWJpbGl0aWVzKTtcblxuICAgICAgICAgIC8vIFN0YXJ0IHRoZSBSVENSdHBTZW5kZXIuIFRoZSBSVENSdHBSZWNlaXZlciBmb3IgdGhpc1xuICAgICAgICAgIC8vIHRyYW5zY2VpdmVyIGhhcyBhbHJlYWR5IGJlZW4gc3RhcnRlZCBpbiBzZXRSZW1vdGVEZXNjcmlwdGlvbi5cbiAgICAgICAgICBwYy5fdHJhbnNjZWl2ZSh0cmFuc2NlaXZlcixcbiAgICAgICAgICAgICAgcGFyYW1zLmNvZGVjcy5sZW5ndGggPiAwLFxuICAgICAgICAgICAgICBmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHBjLmxvY2FsRGVzY3JpcHRpb24gPSB7XG4gICAgICB0eXBlOiBkZXNjcmlwdGlvbi50eXBlLFxuICAgICAgc2RwOiBkZXNjcmlwdGlvbi5zZHBcbiAgICB9O1xuICAgIGlmIChkZXNjcmlwdGlvbi50eXBlID09PSAnb2ZmZXInKSB7XG4gICAgICBwYy5fdXBkYXRlU2lnbmFsaW5nU3RhdGUoJ2hhdmUtbG9jYWwtb2ZmZXInKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcGMuX3VwZGF0ZVNpZ25hbGluZ1N0YXRlKCdzdGFibGUnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH07XG5cbiAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnNldFJlbW90ZURlc2NyaXB0aW9uID0gZnVuY3Rpb24oZGVzY3JpcHRpb24pIHtcbiAgICB2YXIgcGMgPSB0aGlzO1xuXG4gICAgLy8gTm90ZTogcHJhbnN3ZXIgaXMgbm90IHN1cHBvcnRlZC5cbiAgICBpZiAoWydvZmZlcicsICdhbnN3ZXInXS5pbmRleE9mKGRlc2NyaXB0aW9uLnR5cGUpID09PSAtMSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG1ha2VFcnJvcignVHlwZUVycm9yJyxcbiAgICAgICAgICAnVW5zdXBwb3J0ZWQgdHlwZSBcIicgKyBkZXNjcmlwdGlvbi50eXBlICsgJ1wiJykpO1xuICAgIH1cblxuICAgIGlmICghaXNBY3Rpb25BbGxvd2VkSW5TaWduYWxpbmdTdGF0ZSgnc2V0UmVtb3RlRGVzY3JpcHRpb24nLFxuICAgICAgICBkZXNjcmlwdGlvbi50eXBlLCBwYy5zaWduYWxpbmdTdGF0ZSkgfHwgcGMuX2lzQ2xvc2VkKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobWFrZUVycm9yKCdJbnZhbGlkU3RhdGVFcnJvcicsXG4gICAgICAgICAgJ0NhbiBub3Qgc2V0IHJlbW90ZSAnICsgZGVzY3JpcHRpb24udHlwZSArXG4gICAgICAgICAgJyBpbiBzdGF0ZSAnICsgcGMuc2lnbmFsaW5nU3RhdGUpKTtcbiAgICB9XG5cbiAgICB2YXIgc3RyZWFtcyA9IHt9O1xuICAgIHBjLnJlbW90ZVN0cmVhbXMuZm9yRWFjaChmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgIHN0cmVhbXNbc3RyZWFtLmlkXSA9IHN0cmVhbTtcbiAgICB9KTtcbiAgICB2YXIgcmVjZWl2ZXJMaXN0ID0gW107XG4gICAgdmFyIHNlY3Rpb25zID0gU0RQVXRpbHMuc3BsaXRTZWN0aW9ucyhkZXNjcmlwdGlvbi5zZHApO1xuICAgIHZhciBzZXNzaW9ucGFydCA9IHNlY3Rpb25zLnNoaWZ0KCk7XG4gICAgdmFyIGlzSWNlTGl0ZSA9IFNEUFV0aWxzLm1hdGNoUHJlZml4KHNlc3Npb25wYXJ0LFxuICAgICAgICAnYT1pY2UtbGl0ZScpLmxlbmd0aCA+IDA7XG4gICAgdmFyIHVzaW5nQnVuZGxlID0gU0RQVXRpbHMubWF0Y2hQcmVmaXgoc2Vzc2lvbnBhcnQsXG4gICAgICAgICdhPWdyb3VwOkJVTkRMRSAnKS5sZW5ndGggPiAwO1xuICAgIHBjLnVzaW5nQnVuZGxlID0gdXNpbmdCdW5kbGU7XG4gICAgdmFyIGljZU9wdGlvbnMgPSBTRFBVdGlscy5tYXRjaFByZWZpeChzZXNzaW9ucGFydCxcbiAgICAgICAgJ2E9aWNlLW9wdGlvbnM6JylbMF07XG4gICAgaWYgKGljZU9wdGlvbnMpIHtcbiAgICAgIHBjLmNhblRyaWNrbGVJY2VDYW5kaWRhdGVzID0gaWNlT3B0aW9ucy5zdWJzdHIoMTQpLnNwbGl0KCcgJylcbiAgICAgICAgICAuaW5kZXhPZigndHJpY2tsZScpID49IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIHBjLmNhblRyaWNrbGVJY2VDYW5kaWRhdGVzID0gZmFsc2U7XG4gICAgfVxuXG4gICAgc2VjdGlvbnMuZm9yRWFjaChmdW5jdGlvbihtZWRpYVNlY3Rpb24sIHNkcE1MaW5lSW5kZXgpIHtcbiAgICAgIHZhciBsaW5lcyA9IFNEUFV0aWxzLnNwbGl0TGluZXMobWVkaWFTZWN0aW9uKTtcbiAgICAgIHZhciBraW5kID0gU0RQVXRpbHMuZ2V0S2luZChtZWRpYVNlY3Rpb24pO1xuICAgICAgLy8gdHJlYXQgYnVuZGxlLW9ubHkgYXMgbm90LXJlamVjdGVkLlxuICAgICAgdmFyIHJlamVjdGVkID0gU0RQVXRpbHMuaXNSZWplY3RlZChtZWRpYVNlY3Rpb24pICYmXG4gICAgICAgICAgU0RQVXRpbHMubWF0Y2hQcmVmaXgobWVkaWFTZWN0aW9uLCAnYT1idW5kbGUtb25seScpLmxlbmd0aCA9PT0gMDtcbiAgICAgIHZhciBwcm90b2NvbCA9IGxpbmVzWzBdLnN1YnN0cigyKS5zcGxpdCgnICcpWzJdO1xuXG4gICAgICB2YXIgZGlyZWN0aW9uID0gU0RQVXRpbHMuZ2V0RGlyZWN0aW9uKG1lZGlhU2VjdGlvbiwgc2Vzc2lvbnBhcnQpO1xuICAgICAgdmFyIHJlbW90ZU1zaWQgPSBTRFBVdGlscy5wYXJzZU1zaWQobWVkaWFTZWN0aW9uKTtcblxuICAgICAgdmFyIG1pZCA9IFNEUFV0aWxzLmdldE1pZChtZWRpYVNlY3Rpb24pIHx8IFNEUFV0aWxzLmdlbmVyYXRlSWRlbnRpZmllcigpO1xuXG4gICAgICAvLyBSZWplY3QgZGF0YWNoYW5uZWxzIHdoaWNoIGFyZSBub3QgaW1wbGVtZW50ZWQgeWV0LlxuICAgICAgaWYgKChraW5kID09PSAnYXBwbGljYXRpb24nICYmIHByb3RvY29sID09PSAnRFRMUy9TQ1RQJykgfHwgcmVqZWN0ZWQpIHtcbiAgICAgICAgLy8gVE9ETzogdGhpcyBpcyBkYW5nZXJvdXMgaW4gdGhlIGNhc2Ugd2hlcmUgYSBub24tcmVqZWN0ZWQgbS1saW5lXG4gICAgICAgIC8vICAgICBiZWNvbWVzIHJlamVjdGVkLlxuICAgICAgICBwYy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF0gPSB7XG4gICAgICAgICAgbWlkOiBtaWQsXG4gICAgICAgICAga2luZDoga2luZCxcbiAgICAgICAgICByZWplY3RlZDogdHJ1ZVxuICAgICAgICB9O1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmICghcmVqZWN0ZWQgJiYgcGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdICYmXG4gICAgICAgICAgcGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLnJlamVjdGVkKSB7XG4gICAgICAgIC8vIHJlY3ljbGUgYSByZWplY3RlZCB0cmFuc2NlaXZlci5cbiAgICAgICAgcGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdID0gcGMuX2NyZWF0ZVRyYW5zY2VpdmVyKGtpbmQsIHRydWUpO1xuICAgICAgfVxuXG4gICAgICB2YXIgdHJhbnNjZWl2ZXI7XG4gICAgICB2YXIgaWNlR2F0aGVyZXI7XG4gICAgICB2YXIgaWNlVHJhbnNwb3J0O1xuICAgICAgdmFyIGR0bHNUcmFuc3BvcnQ7XG4gICAgICB2YXIgcnRwUmVjZWl2ZXI7XG4gICAgICB2YXIgc2VuZEVuY29kaW5nUGFyYW1ldGVycztcbiAgICAgIHZhciByZWN2RW5jb2RpbmdQYXJhbWV0ZXJzO1xuICAgICAgdmFyIGxvY2FsQ2FwYWJpbGl0aWVzO1xuXG4gICAgICB2YXIgdHJhY2s7XG4gICAgICAvLyBGSVhNRTogZW5zdXJlIHRoZSBtZWRpYVNlY3Rpb24gaGFzIHJ0Y3AtbXV4IHNldC5cbiAgICAgIHZhciByZW1vdGVDYXBhYmlsaXRpZXMgPSBTRFBVdGlscy5wYXJzZVJ0cFBhcmFtZXRlcnMobWVkaWFTZWN0aW9uKTtcbiAgICAgIHZhciByZW1vdGVJY2VQYXJhbWV0ZXJzO1xuICAgICAgdmFyIHJlbW90ZUR0bHNQYXJhbWV0ZXJzO1xuICAgICAgaWYgKCFyZWplY3RlZCkge1xuICAgICAgICByZW1vdGVJY2VQYXJhbWV0ZXJzID0gU0RQVXRpbHMuZ2V0SWNlUGFyYW1ldGVycyhtZWRpYVNlY3Rpb24sXG4gICAgICAgICAgICBzZXNzaW9ucGFydCk7XG4gICAgICAgIHJlbW90ZUR0bHNQYXJhbWV0ZXJzID0gU0RQVXRpbHMuZ2V0RHRsc1BhcmFtZXRlcnMobWVkaWFTZWN0aW9uLFxuICAgICAgICAgICAgc2Vzc2lvbnBhcnQpO1xuICAgICAgICByZW1vdGVEdGxzUGFyYW1ldGVycy5yb2xlID0gJ2NsaWVudCc7XG4gICAgICB9XG4gICAgICByZWN2RW5jb2RpbmdQYXJhbWV0ZXJzID1cbiAgICAgICAgICBTRFBVdGlscy5wYXJzZVJ0cEVuY29kaW5nUGFyYW1ldGVycyhtZWRpYVNlY3Rpb24pO1xuXG4gICAgICB2YXIgcnRjcFBhcmFtZXRlcnMgPSBTRFBVdGlscy5wYXJzZVJ0Y3BQYXJhbWV0ZXJzKG1lZGlhU2VjdGlvbik7XG5cbiAgICAgIHZhciBpc0NvbXBsZXRlID0gU0RQVXRpbHMubWF0Y2hQcmVmaXgobWVkaWFTZWN0aW9uLFxuICAgICAgICAgICdhPWVuZC1vZi1jYW5kaWRhdGVzJywgc2Vzc2lvbnBhcnQpLmxlbmd0aCA+IDA7XG4gICAgICB2YXIgY2FuZHMgPSBTRFBVdGlscy5tYXRjaFByZWZpeChtZWRpYVNlY3Rpb24sICdhPWNhbmRpZGF0ZTonKVxuICAgICAgICAgIC5tYXAoZnVuY3Rpb24oY2FuZCkge1xuICAgICAgICAgICAgcmV0dXJuIFNEUFV0aWxzLnBhcnNlQ2FuZGlkYXRlKGNhbmQpO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLmZpbHRlcihmdW5jdGlvbihjYW5kKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FuZC5jb21wb25lbnQgPT09IDE7XG4gICAgICAgICAgfSk7XG5cbiAgICAgIC8vIENoZWNrIGlmIHdlIGNhbiB1c2UgQlVORExFIGFuZCBkaXNwb3NlIHRyYW5zcG9ydHMuXG4gICAgICBpZiAoKGRlc2NyaXB0aW9uLnR5cGUgPT09ICdvZmZlcicgfHwgZGVzY3JpcHRpb24udHlwZSA9PT0gJ2Fuc3dlcicpICYmXG4gICAgICAgICAgIXJlamVjdGVkICYmIHVzaW5nQnVuZGxlICYmIHNkcE1MaW5lSW5kZXggPiAwICYmXG4gICAgICAgICAgcGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdKSB7XG4gICAgICAgIHBjLl9kaXNwb3NlSWNlQW5kRHRsc1RyYW5zcG9ydHMoc2RwTUxpbmVJbmRleCk7XG4gICAgICAgIHBjLnRyYW5zY2VpdmVyc1tzZHBNTGluZUluZGV4XS5pY2VHYXRoZXJlciA9XG4gICAgICAgICAgICBwYy50cmFuc2NlaXZlcnNbMF0uaWNlR2F0aGVyZXI7XG4gICAgICAgIHBjLnRyYW5zY2VpdmVyc1tzZHBNTGluZUluZGV4XS5pY2VUcmFuc3BvcnQgPVxuICAgICAgICAgICAgcGMudHJhbnNjZWl2ZXJzWzBdLmljZVRyYW5zcG9ydDtcbiAgICAgICAgcGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLmR0bHNUcmFuc3BvcnQgPVxuICAgICAgICAgICAgcGMudHJhbnNjZWl2ZXJzWzBdLmR0bHNUcmFuc3BvcnQ7XG4gICAgICAgIGlmIChwYy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF0ucnRwU2VuZGVyKSB7XG4gICAgICAgICAgcGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLnJ0cFNlbmRlci5zZXRUcmFuc3BvcnQoXG4gICAgICAgICAgICAgIHBjLnRyYW5zY2VpdmVyc1swXS5kdGxzVHJhbnNwb3J0KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLnJ0cFJlY2VpdmVyKSB7XG4gICAgICAgICAgcGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdLnJ0cFJlY2VpdmVyLnNldFRyYW5zcG9ydChcbiAgICAgICAgICAgICAgcGMudHJhbnNjZWl2ZXJzWzBdLmR0bHNUcmFuc3BvcnQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoZGVzY3JpcHRpb24udHlwZSA9PT0gJ29mZmVyJyAmJiAhcmVqZWN0ZWQpIHtcbiAgICAgICAgdHJhbnNjZWl2ZXIgPSBwYy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF0gfHxcbiAgICAgICAgICAgIHBjLl9jcmVhdGVUcmFuc2NlaXZlcihraW5kKTtcbiAgICAgICAgdHJhbnNjZWl2ZXIubWlkID0gbWlkO1xuXG4gICAgICAgIGlmICghdHJhbnNjZWl2ZXIuaWNlR2F0aGVyZXIpIHtcbiAgICAgICAgICB0cmFuc2NlaXZlci5pY2VHYXRoZXJlciA9IHBjLl9jcmVhdGVJY2VHYXRoZXJlcihzZHBNTGluZUluZGV4LFxuICAgICAgICAgICAgICB1c2luZ0J1bmRsZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY2FuZHMubGVuZ3RoICYmIHRyYW5zY2VpdmVyLmljZVRyYW5zcG9ydC5zdGF0ZSA9PT0gJ25ldycpIHtcbiAgICAgICAgICBpZiAoaXNDb21wbGV0ZSAmJiAoIXVzaW5nQnVuZGxlIHx8IHNkcE1MaW5lSW5kZXggPT09IDApKSB7XG4gICAgICAgICAgICB0cmFuc2NlaXZlci5pY2VUcmFuc3BvcnQuc2V0UmVtb3RlQ2FuZGlkYXRlcyhjYW5kcyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNhbmRzLmZvckVhY2goZnVuY3Rpb24oY2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgIG1heWJlQWRkQ2FuZGlkYXRlKHRyYW5zY2VpdmVyLmljZVRyYW5zcG9ydCwgY2FuZGlkYXRlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxvY2FsQ2FwYWJpbGl0aWVzID0gd2luZG93LlJUQ1J0cFJlY2VpdmVyLmdldENhcGFiaWxpdGllcyhraW5kKTtcblxuICAgICAgICAvLyBmaWx0ZXIgUlRYIHVudGlsIGFkZGl0aW9uYWwgc3R1ZmYgbmVlZGVkIGZvciBSVFggaXMgaW1wbGVtZW50ZWRcbiAgICAgICAgLy8gaW4gYWRhcHRlci5qc1xuICAgICAgICBpZiAoZWRnZVZlcnNpb24gPCAxNTAxOSkge1xuICAgICAgICAgIGxvY2FsQ2FwYWJpbGl0aWVzLmNvZGVjcyA9IGxvY2FsQ2FwYWJpbGl0aWVzLmNvZGVjcy5maWx0ZXIoXG4gICAgICAgICAgICAgIGZ1bmN0aW9uKGNvZGVjKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvZGVjLm5hbWUgIT09ICdydHgnO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNlbmRFbmNvZGluZ1BhcmFtZXRlcnMgPSB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzIHx8IFt7XG4gICAgICAgICAgc3NyYzogKDIgKiBzZHBNTGluZUluZGV4ICsgMikgKiAxMDAxXG4gICAgICAgIH1dO1xuXG4gICAgICAgIC8vIFRPRE86IHJld3JpdGUgdG8gdXNlIGh0dHA6Ly93M2MuZ2l0aHViLmlvL3dlYnJ0Yy1wYy8jc2V0LWFzc29jaWF0ZWQtcmVtb3RlLXN0cmVhbXNcbiAgICAgICAgdmFyIGlzTmV3VHJhY2sgPSBmYWxzZTtcbiAgICAgICAgaWYgKGRpcmVjdGlvbiA9PT0gJ3NlbmRyZWN2JyB8fCBkaXJlY3Rpb24gPT09ICdzZW5kb25seScpIHtcbiAgICAgICAgICBpc05ld1RyYWNrID0gIXRyYW5zY2VpdmVyLnJ0cFJlY2VpdmVyO1xuICAgICAgICAgIHJ0cFJlY2VpdmVyID0gdHJhbnNjZWl2ZXIucnRwUmVjZWl2ZXIgfHxcbiAgICAgICAgICAgICAgbmV3IHdpbmRvdy5SVENSdHBSZWNlaXZlcih0cmFuc2NlaXZlci5kdGxzVHJhbnNwb3J0LCBraW5kKTtcblxuICAgICAgICAgIGlmIChpc05ld1RyYWNrKSB7XG4gICAgICAgICAgICB2YXIgc3RyZWFtO1xuICAgICAgICAgICAgdHJhY2sgPSBydHBSZWNlaXZlci50cmFjaztcbiAgICAgICAgICAgIC8vIEZJWE1FOiBkb2VzIG5vdCB3b3JrIHdpdGggUGxhbiBCLlxuICAgICAgICAgICAgaWYgKHJlbW90ZU1zaWQgJiYgcmVtb3RlTXNpZC5zdHJlYW0gPT09ICctJykge1xuICAgICAgICAgICAgICAvLyBuby1vcC4gYSBzdHJlYW0gaWQgb2YgJy0nIG1lYW5zOiBubyBhc3NvY2lhdGVkIHN0cmVhbS5cbiAgICAgICAgICAgIH0gZWxzZSBpZiAocmVtb3RlTXNpZCkge1xuICAgICAgICAgICAgICBpZiAoIXN0cmVhbXNbcmVtb3RlTXNpZC5zdHJlYW1dKSB7XG4gICAgICAgICAgICAgICAgc3RyZWFtc1tyZW1vdGVNc2lkLnN0cmVhbV0gPSBuZXcgd2luZG93Lk1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHN0cmVhbXNbcmVtb3RlTXNpZC5zdHJlYW1dLCAnaWQnLCB7XG4gICAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVtb3RlTXNpZC5zdHJlYW07XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRyYWNrLCAnaWQnLCB7XG4gICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiByZW1vdGVNc2lkLnRyYWNrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHN0cmVhbSA9IHN0cmVhbXNbcmVtb3RlTXNpZC5zdHJlYW1dO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaWYgKCFzdHJlYW1zLmRlZmF1bHQpIHtcbiAgICAgICAgICAgICAgICBzdHJlYW1zLmRlZmF1bHQgPSBuZXcgd2luZG93Lk1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgc3RyZWFtID0gc3RyZWFtcy5kZWZhdWx0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHN0cmVhbSkge1xuICAgICAgICAgICAgICBhZGRUcmFja1RvU3RyZWFtQW5kRmlyZUV2ZW50KHRyYWNrLCBzdHJlYW0pO1xuICAgICAgICAgICAgICB0cmFuc2NlaXZlci5hc3NvY2lhdGVkUmVtb3RlTWVkaWFTdHJlYW1zLnB1c2goc3RyZWFtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlY2VpdmVyTGlzdC5wdXNoKFt0cmFjaywgcnRwUmVjZWl2ZXIsIHN0cmVhbV0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0cmFuc2NlaXZlci5ydHBSZWNlaXZlciAmJiB0cmFuc2NlaXZlci5ydHBSZWNlaXZlci50cmFjaykge1xuICAgICAgICAgIHRyYW5zY2VpdmVyLmFzc29jaWF0ZWRSZW1vdGVNZWRpYVN0cmVhbXMuZm9yRWFjaChmdW5jdGlvbihzKSB7XG4gICAgICAgICAgICB2YXIgbmF0aXZlVHJhY2sgPSBzLmdldFRyYWNrcygpLmZpbmQoZnVuY3Rpb24odCkge1xuICAgICAgICAgICAgICByZXR1cm4gdC5pZCA9PT0gdHJhbnNjZWl2ZXIucnRwUmVjZWl2ZXIudHJhY2suaWQ7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChuYXRpdmVUcmFjaykge1xuICAgICAgICAgICAgICByZW1vdmVUcmFja0Zyb21TdHJlYW1BbmRGaXJlRXZlbnQobmF0aXZlVHJhY2ssIHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHRyYW5zY2VpdmVyLmFzc29jaWF0ZWRSZW1vdGVNZWRpYVN0cmVhbXMgPSBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyYW5zY2VpdmVyLmxvY2FsQ2FwYWJpbGl0aWVzID0gbG9jYWxDYXBhYmlsaXRpZXM7XG4gICAgICAgIHRyYW5zY2VpdmVyLnJlbW90ZUNhcGFiaWxpdGllcyA9IHJlbW90ZUNhcGFiaWxpdGllcztcbiAgICAgICAgdHJhbnNjZWl2ZXIucnRwUmVjZWl2ZXIgPSBydHBSZWNlaXZlcjtcbiAgICAgICAgdHJhbnNjZWl2ZXIucnRjcFBhcmFtZXRlcnMgPSBydGNwUGFyYW1ldGVycztcbiAgICAgICAgdHJhbnNjZWl2ZXIuc2VuZEVuY29kaW5nUGFyYW1ldGVycyA9IHNlbmRFbmNvZGluZ1BhcmFtZXRlcnM7XG4gICAgICAgIHRyYW5zY2VpdmVyLnJlY3ZFbmNvZGluZ1BhcmFtZXRlcnMgPSByZWN2RW5jb2RpbmdQYXJhbWV0ZXJzO1xuXG4gICAgICAgIC8vIFN0YXJ0IHRoZSBSVENSdHBSZWNlaXZlciBub3cuIFRoZSBSVFBTZW5kZXIgaXMgc3RhcnRlZCBpblxuICAgICAgICAvLyBzZXRMb2NhbERlc2NyaXB0aW9uLlxuICAgICAgICBwYy5fdHJhbnNjZWl2ZShwYy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF0sXG4gICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgIGlzTmV3VHJhY2spO1xuICAgICAgfSBlbHNlIGlmIChkZXNjcmlwdGlvbi50eXBlID09PSAnYW5zd2VyJyAmJiAhcmVqZWN0ZWQpIHtcbiAgICAgICAgdHJhbnNjZWl2ZXIgPSBwYy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF07XG4gICAgICAgIGljZUdhdGhlcmVyID0gdHJhbnNjZWl2ZXIuaWNlR2F0aGVyZXI7XG4gICAgICAgIGljZVRyYW5zcG9ydCA9IHRyYW5zY2VpdmVyLmljZVRyYW5zcG9ydDtcbiAgICAgICAgZHRsc1RyYW5zcG9ydCA9IHRyYW5zY2VpdmVyLmR0bHNUcmFuc3BvcnQ7XG4gICAgICAgIHJ0cFJlY2VpdmVyID0gdHJhbnNjZWl2ZXIucnRwUmVjZWl2ZXI7XG4gICAgICAgIHNlbmRFbmNvZGluZ1BhcmFtZXRlcnMgPSB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzO1xuICAgICAgICBsb2NhbENhcGFiaWxpdGllcyA9IHRyYW5zY2VpdmVyLmxvY2FsQ2FwYWJpbGl0aWVzO1xuXG4gICAgICAgIHBjLnRyYW5zY2VpdmVyc1tzZHBNTGluZUluZGV4XS5yZWN2RW5jb2RpbmdQYXJhbWV0ZXJzID1cbiAgICAgICAgICAgIHJlY3ZFbmNvZGluZ1BhcmFtZXRlcnM7XG4gICAgICAgIHBjLnRyYW5zY2VpdmVyc1tzZHBNTGluZUluZGV4XS5yZW1vdGVDYXBhYmlsaXRpZXMgPVxuICAgICAgICAgICAgcmVtb3RlQ2FwYWJpbGl0aWVzO1xuICAgICAgICBwYy50cmFuc2NlaXZlcnNbc2RwTUxpbmVJbmRleF0ucnRjcFBhcmFtZXRlcnMgPSBydGNwUGFyYW1ldGVycztcblxuICAgICAgICBpZiAoY2FuZHMubGVuZ3RoICYmIGljZVRyYW5zcG9ydC5zdGF0ZSA9PT0gJ25ldycpIHtcbiAgICAgICAgICBpZiAoKGlzSWNlTGl0ZSB8fCBpc0NvbXBsZXRlKSAmJlxuICAgICAgICAgICAgICAoIXVzaW5nQnVuZGxlIHx8IHNkcE1MaW5lSW5kZXggPT09IDApKSB7XG4gICAgICAgICAgICBpY2VUcmFuc3BvcnQuc2V0UmVtb3RlQ2FuZGlkYXRlcyhjYW5kcyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNhbmRzLmZvckVhY2goZnVuY3Rpb24oY2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgIG1heWJlQWRkQ2FuZGlkYXRlKHRyYW5zY2VpdmVyLmljZVRyYW5zcG9ydCwgY2FuZGlkYXRlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdXNpbmdCdW5kbGUgfHwgc2RwTUxpbmVJbmRleCA9PT0gMCkge1xuICAgICAgICAgIGlmIChpY2VUcmFuc3BvcnQuc3RhdGUgPT09ICduZXcnKSB7XG4gICAgICAgICAgICBpY2VUcmFuc3BvcnQuc3RhcnQoaWNlR2F0aGVyZXIsIHJlbW90ZUljZVBhcmFtZXRlcnMsXG4gICAgICAgICAgICAgICAgJ2NvbnRyb2xsaW5nJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChkdGxzVHJhbnNwb3J0LnN0YXRlID09PSAnbmV3Jykge1xuICAgICAgICAgICAgZHRsc1RyYW5zcG9ydC5zdGFydChyZW1vdGVEdGxzUGFyYW1ldGVycyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcGMuX3RyYW5zY2VpdmUodHJhbnNjZWl2ZXIsXG4gICAgICAgICAgICBkaXJlY3Rpb24gPT09ICdzZW5kcmVjdicgfHwgZGlyZWN0aW9uID09PSAncmVjdm9ubHknLFxuICAgICAgICAgICAgZGlyZWN0aW9uID09PSAnc2VuZHJlY3YnIHx8IGRpcmVjdGlvbiA9PT0gJ3NlbmRvbmx5Jyk7XG5cbiAgICAgICAgLy8gVE9ETzogcmV3cml0ZSB0byB1c2UgaHR0cDovL3czYy5naXRodWIuaW8vd2VicnRjLXBjLyNzZXQtYXNzb2NpYXRlZC1yZW1vdGUtc3RyZWFtc1xuICAgICAgICBpZiAocnRwUmVjZWl2ZXIgJiZcbiAgICAgICAgICAgIChkaXJlY3Rpb24gPT09ICdzZW5kcmVjdicgfHwgZGlyZWN0aW9uID09PSAnc2VuZG9ubHknKSkge1xuICAgICAgICAgIHRyYWNrID0gcnRwUmVjZWl2ZXIudHJhY2s7XG4gICAgICAgICAgaWYgKHJlbW90ZU1zaWQpIHtcbiAgICAgICAgICAgIGlmICghc3RyZWFtc1tyZW1vdGVNc2lkLnN0cmVhbV0pIHtcbiAgICAgICAgICAgICAgc3RyZWFtc1tyZW1vdGVNc2lkLnN0cmVhbV0gPSBuZXcgd2luZG93Lk1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhZGRUcmFja1RvU3RyZWFtQW5kRmlyZUV2ZW50KHRyYWNrLCBzdHJlYW1zW3JlbW90ZU1zaWQuc3RyZWFtXSk7XG4gICAgICAgICAgICByZWNlaXZlckxpc3QucHVzaChbdHJhY2ssIHJ0cFJlY2VpdmVyLCBzdHJlYW1zW3JlbW90ZU1zaWQuc3RyZWFtXV0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoIXN0cmVhbXMuZGVmYXVsdCkge1xuICAgICAgICAgICAgICBzdHJlYW1zLmRlZmF1bHQgPSBuZXcgd2luZG93Lk1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhZGRUcmFja1RvU3RyZWFtQW5kRmlyZUV2ZW50KHRyYWNrLCBzdHJlYW1zLmRlZmF1bHQpO1xuICAgICAgICAgICAgcmVjZWl2ZXJMaXN0LnB1c2goW3RyYWNrLCBydHBSZWNlaXZlciwgc3RyZWFtcy5kZWZhdWx0XSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIEZJWE1FOiBhY3R1YWxseSB0aGUgcmVjZWl2ZXIgc2hvdWxkIGJlIGNyZWF0ZWQgbGF0ZXIuXG4gICAgICAgICAgZGVsZXRlIHRyYW5zY2VpdmVyLnJ0cFJlY2VpdmVyO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpZiAocGMuX2R0bHNSb2xlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHBjLl9kdGxzUm9sZSA9IGRlc2NyaXB0aW9uLnR5cGUgPT09ICdvZmZlcicgPyAnYWN0aXZlJyA6ICdwYXNzaXZlJztcbiAgICB9XG5cbiAgICBwYy5yZW1vdGVEZXNjcmlwdGlvbiA9IHtcbiAgICAgIHR5cGU6IGRlc2NyaXB0aW9uLnR5cGUsXG4gICAgICBzZHA6IGRlc2NyaXB0aW9uLnNkcFxuICAgIH07XG4gICAgaWYgKGRlc2NyaXB0aW9uLnR5cGUgPT09ICdvZmZlcicpIHtcbiAgICAgIHBjLl91cGRhdGVTaWduYWxpbmdTdGF0ZSgnaGF2ZS1yZW1vdGUtb2ZmZXInKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcGMuX3VwZGF0ZVNpZ25hbGluZ1N0YXRlKCdzdGFibGUnKTtcbiAgICB9XG4gICAgT2JqZWN0LmtleXMoc3RyZWFtcykuZm9yRWFjaChmdW5jdGlvbihzaWQpIHtcbiAgICAgIHZhciBzdHJlYW0gPSBzdHJlYW1zW3NpZF07XG4gICAgICBpZiAoc3RyZWFtLmdldFRyYWNrcygpLmxlbmd0aCkge1xuICAgICAgICBpZiAocGMucmVtb3RlU3RyZWFtcy5pbmRleE9mKHN0cmVhbSkgPT09IC0xKSB7XG4gICAgICAgICAgcGMucmVtb3RlU3RyZWFtcy5wdXNoKHN0cmVhbSk7XG4gICAgICAgICAgdmFyIGV2ZW50ID0gbmV3IEV2ZW50KCdhZGRzdHJlYW0nKTtcbiAgICAgICAgICBldmVudC5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBwYy5fZGlzcGF0Y2hFdmVudCgnYWRkc3RyZWFtJywgZXZlbnQpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVjZWl2ZXJMaXN0LmZvckVhY2goZnVuY3Rpb24oaXRlbSkge1xuICAgICAgICAgIHZhciB0cmFjayA9IGl0ZW1bMF07XG4gICAgICAgICAgdmFyIHJlY2VpdmVyID0gaXRlbVsxXTtcbiAgICAgICAgICBpZiAoc3RyZWFtLmlkICE9PSBpdGVtWzJdLmlkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIGZpcmVBZGRUcmFjayhwYywgdHJhY2ssIHJlY2VpdmVyLCBbc3RyZWFtXSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJlY2VpdmVyTGlzdC5mb3JFYWNoKGZ1bmN0aW9uKGl0ZW0pIHtcbiAgICAgIGlmIChpdGVtWzJdKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGZpcmVBZGRUcmFjayhwYywgaXRlbVswXSwgaXRlbVsxXSwgW10pO1xuICAgIH0pO1xuXG4gICAgLy8gY2hlY2sgd2hldGhlciBhZGRJY2VDYW5kaWRhdGUoe30pIHdhcyBjYWxsZWQgd2l0aGluIGZvdXIgc2Vjb25kcyBhZnRlclxuICAgIC8vIHNldFJlbW90ZURlc2NyaXB0aW9uLlxuICAgIHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKCEocGMgJiYgcGMudHJhbnNjZWl2ZXJzKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBwYy50cmFuc2NlaXZlcnMuZm9yRWFjaChmdW5jdGlvbih0cmFuc2NlaXZlcikge1xuICAgICAgICBpZiAodHJhbnNjZWl2ZXIuaWNlVHJhbnNwb3J0ICYmXG4gICAgICAgICAgICB0cmFuc2NlaXZlci5pY2VUcmFuc3BvcnQuc3RhdGUgPT09ICduZXcnICYmXG4gICAgICAgICAgICB0cmFuc2NlaXZlci5pY2VUcmFuc3BvcnQuZ2V0UmVtb3RlQ2FuZGlkYXRlcygpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oJ1RpbWVvdXQgZm9yIGFkZFJlbW90ZUNhbmRpZGF0ZS4gQ29uc2lkZXIgc2VuZGluZyAnICtcbiAgICAgICAgICAgICAgJ2FuIGVuZC1vZi1jYW5kaWRhdGVzIG5vdGlmaWNhdGlvbicpO1xuICAgICAgICAgIHRyYW5zY2VpdmVyLmljZVRyYW5zcG9ydC5hZGRSZW1vdGVDYW5kaWRhdGUoe30pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9LCA0MDAwKTtcblxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfTtcblxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuY2xvc2UgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnRyYW5zY2VpdmVycy5mb3JFYWNoKGZ1bmN0aW9uKHRyYW5zY2VpdmVyKSB7XG4gICAgICAvKiBub3QgeWV0XG4gICAgICBpZiAodHJhbnNjZWl2ZXIuaWNlR2F0aGVyZXIpIHtcbiAgICAgICAgdHJhbnNjZWl2ZXIuaWNlR2F0aGVyZXIuY2xvc2UoKTtcbiAgICAgIH1cbiAgICAgICovXG4gICAgICBpZiAodHJhbnNjZWl2ZXIuaWNlVHJhbnNwb3J0KSB7XG4gICAgICAgIHRyYW5zY2VpdmVyLmljZVRyYW5zcG9ydC5zdG9wKCk7XG4gICAgICB9XG4gICAgICBpZiAodHJhbnNjZWl2ZXIuZHRsc1RyYW5zcG9ydCkge1xuICAgICAgICB0cmFuc2NlaXZlci5kdGxzVHJhbnNwb3J0LnN0b3AoKTtcbiAgICAgIH1cbiAgICAgIGlmICh0cmFuc2NlaXZlci5ydHBTZW5kZXIpIHtcbiAgICAgICAgdHJhbnNjZWl2ZXIucnRwU2VuZGVyLnN0b3AoKTtcbiAgICAgIH1cbiAgICAgIGlmICh0cmFuc2NlaXZlci5ydHBSZWNlaXZlcikge1xuICAgICAgICB0cmFuc2NlaXZlci5ydHBSZWNlaXZlci5zdG9wKCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgLy8gRklYTUU6IGNsZWFuIHVwIHRyYWNrcywgbG9jYWwgc3RyZWFtcywgcmVtb3RlIHN0cmVhbXMsIGV0Y1xuICAgIHRoaXMuX2lzQ2xvc2VkID0gdHJ1ZTtcbiAgICB0aGlzLl91cGRhdGVTaWduYWxpbmdTdGF0ZSgnY2xvc2VkJyk7XG4gIH07XG5cbiAgLy8gVXBkYXRlIHRoZSBzaWduYWxpbmcgc3RhdGUuXG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5fdXBkYXRlU2lnbmFsaW5nU3RhdGUgPSBmdW5jdGlvbihuZXdTdGF0ZSkge1xuICAgIHRoaXMuc2lnbmFsaW5nU3RhdGUgPSBuZXdTdGF0ZTtcbiAgICB2YXIgZXZlbnQgPSBuZXcgRXZlbnQoJ3NpZ25hbGluZ3N0YXRlY2hhbmdlJyk7XG4gICAgdGhpcy5fZGlzcGF0Y2hFdmVudCgnc2lnbmFsaW5nc3RhdGVjaGFuZ2UnLCBldmVudCk7XG4gIH07XG5cbiAgLy8gRGV0ZXJtaW5lIHdoZXRoZXIgdG8gZmlyZSB0aGUgbmVnb3RpYXRpb25uZWVkZWQgZXZlbnQuXG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5fbWF5YmVGaXJlTmVnb3RpYXRpb25OZWVkZWQgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgcGMgPSB0aGlzO1xuICAgIGlmICh0aGlzLnNpZ25hbGluZ1N0YXRlICE9PSAnc3RhYmxlJyB8fCB0aGlzLm5lZWROZWdvdGlhdGlvbiA9PT0gdHJ1ZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLm5lZWROZWdvdGlhdGlvbiA9IHRydWU7XG4gICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICBpZiAocGMubmVlZE5lZ290aWF0aW9uKSB7XG4gICAgICAgIHBjLm5lZWROZWdvdGlhdGlvbiA9IGZhbHNlO1xuICAgICAgICB2YXIgZXZlbnQgPSBuZXcgRXZlbnQoJ25lZ290aWF0aW9ubmVlZGVkJyk7XG4gICAgICAgIHBjLl9kaXNwYXRjaEV2ZW50KCduZWdvdGlhdGlvbm5lZWRlZCcsIGV2ZW50KTtcbiAgICAgIH1cbiAgICB9LCAwKTtcbiAgfTtcblxuICAvLyBVcGRhdGUgdGhlIGljZSBjb25uZWN0aW9uIHN0YXRlLlxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuX3VwZGF0ZUljZUNvbm5lY3Rpb25TdGF0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBuZXdTdGF0ZTtcbiAgICB2YXIgc3RhdGVzID0ge1xuICAgICAgJ25ldyc6IDAsXG4gICAgICBjbG9zZWQ6IDAsXG4gICAgICBjaGVja2luZzogMCxcbiAgICAgIGNvbm5lY3RlZDogMCxcbiAgICAgIGNvbXBsZXRlZDogMCxcbiAgICAgIGRpc2Nvbm5lY3RlZDogMCxcbiAgICAgIGZhaWxlZDogMFxuICAgIH07XG4gICAgdGhpcy50cmFuc2NlaXZlcnMuZm9yRWFjaChmdW5jdGlvbih0cmFuc2NlaXZlcikge1xuICAgICAgc3RhdGVzW3RyYW5zY2VpdmVyLmljZVRyYW5zcG9ydC5zdGF0ZV0rKztcbiAgICB9KTtcblxuICAgIG5ld1N0YXRlID0gJ25ldyc7XG4gICAgaWYgKHN0YXRlcy5mYWlsZWQgPiAwKSB7XG4gICAgICBuZXdTdGF0ZSA9ICdmYWlsZWQnO1xuICAgIH0gZWxzZSBpZiAoc3RhdGVzLmNoZWNraW5nID4gMCkge1xuICAgICAgbmV3U3RhdGUgPSAnY2hlY2tpbmcnO1xuICAgIH0gZWxzZSBpZiAoc3RhdGVzLmRpc2Nvbm5lY3RlZCA+IDApIHtcbiAgICAgIG5ld1N0YXRlID0gJ2Rpc2Nvbm5lY3RlZCc7XG4gICAgfSBlbHNlIGlmIChzdGF0ZXMubmV3ID4gMCkge1xuICAgICAgbmV3U3RhdGUgPSAnbmV3JztcbiAgICB9IGVsc2UgaWYgKHN0YXRlcy5jb25uZWN0ZWQgPiAwKSB7XG4gICAgICBuZXdTdGF0ZSA9ICdjb25uZWN0ZWQnO1xuICAgIH0gZWxzZSBpZiAoc3RhdGVzLmNvbXBsZXRlZCA+IDApIHtcbiAgICAgIG5ld1N0YXRlID0gJ2NvbXBsZXRlZCc7XG4gICAgfVxuXG4gICAgaWYgKG5ld1N0YXRlICE9PSB0aGlzLmljZUNvbm5lY3Rpb25TdGF0ZSkge1xuICAgICAgdGhpcy5pY2VDb25uZWN0aW9uU3RhdGUgPSBuZXdTdGF0ZTtcbiAgICAgIHZhciBldmVudCA9IG5ldyBFdmVudCgnaWNlY29ubmVjdGlvbnN0YXRlY2hhbmdlJyk7XG4gICAgICB0aGlzLl9kaXNwYXRjaEV2ZW50KCdpY2Vjb25uZWN0aW9uc3RhdGVjaGFuZ2UnLCBldmVudCk7XG4gICAgfVxuICB9O1xuXG4gIC8vIFVwZGF0ZSB0aGUgY29ubmVjdGlvbiBzdGF0ZS5cbiAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLl91cGRhdGVDb25uZWN0aW9uU3RhdGUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgbmV3U3RhdGU7XG4gICAgdmFyIHN0YXRlcyA9IHtcbiAgICAgICduZXcnOiAwLFxuICAgICAgY2xvc2VkOiAwLFxuICAgICAgY29ubmVjdGluZzogMCxcbiAgICAgIGNvbm5lY3RlZDogMCxcbiAgICAgIGNvbXBsZXRlZDogMCxcbiAgICAgIGRpc2Nvbm5lY3RlZDogMCxcbiAgICAgIGZhaWxlZDogMFxuICAgIH07XG4gICAgdGhpcy50cmFuc2NlaXZlcnMuZm9yRWFjaChmdW5jdGlvbih0cmFuc2NlaXZlcikge1xuICAgICAgc3RhdGVzW3RyYW5zY2VpdmVyLmljZVRyYW5zcG9ydC5zdGF0ZV0rKztcbiAgICAgIHN0YXRlc1t0cmFuc2NlaXZlci5kdGxzVHJhbnNwb3J0LnN0YXRlXSsrO1xuICAgIH0pO1xuICAgIC8vIElDRVRyYW5zcG9ydC5jb21wbGV0ZWQgYW5kIGNvbm5lY3RlZCBhcmUgdGhlIHNhbWUgZm9yIHRoaXMgcHVycG9zZS5cbiAgICBzdGF0ZXMuY29ubmVjdGVkICs9IHN0YXRlcy5jb21wbGV0ZWQ7XG5cbiAgICBuZXdTdGF0ZSA9ICduZXcnO1xuICAgIGlmIChzdGF0ZXMuZmFpbGVkID4gMCkge1xuICAgICAgbmV3U3RhdGUgPSAnZmFpbGVkJztcbiAgICB9IGVsc2UgaWYgKHN0YXRlcy5jb25uZWN0aW5nID4gMCkge1xuICAgICAgbmV3U3RhdGUgPSAnY29ubmVjdGluZyc7XG4gICAgfSBlbHNlIGlmIChzdGF0ZXMuZGlzY29ubmVjdGVkID4gMCkge1xuICAgICAgbmV3U3RhdGUgPSAnZGlzY29ubmVjdGVkJztcbiAgICB9IGVsc2UgaWYgKHN0YXRlcy5uZXcgPiAwKSB7XG4gICAgICBuZXdTdGF0ZSA9ICduZXcnO1xuICAgIH0gZWxzZSBpZiAoc3RhdGVzLmNvbm5lY3RlZCA+IDApIHtcbiAgICAgIG5ld1N0YXRlID0gJ2Nvbm5lY3RlZCc7XG4gICAgfVxuXG4gICAgaWYgKG5ld1N0YXRlICE9PSB0aGlzLmNvbm5lY3Rpb25TdGF0ZSkge1xuICAgICAgdGhpcy5jb25uZWN0aW9uU3RhdGUgPSBuZXdTdGF0ZTtcbiAgICAgIHZhciBldmVudCA9IG5ldyBFdmVudCgnY29ubmVjdGlvbnN0YXRlY2hhbmdlJyk7XG4gICAgICB0aGlzLl9kaXNwYXRjaEV2ZW50KCdjb25uZWN0aW9uc3RhdGVjaGFuZ2UnLCBldmVudCk7XG4gICAgfVxuICB9O1xuXG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5jcmVhdGVPZmZlciA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBwYyA9IHRoaXM7XG5cbiAgICBpZiAocGMuX2lzQ2xvc2VkKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobWFrZUVycm9yKCdJbnZhbGlkU3RhdGVFcnJvcicsXG4gICAgICAgICAgJ0NhbiBub3QgY2FsbCBjcmVhdGVPZmZlciBhZnRlciBjbG9zZScpKTtcbiAgICB9XG5cbiAgICB2YXIgbnVtQXVkaW9UcmFja3MgPSBwYy50cmFuc2NlaXZlcnMuZmlsdGVyKGZ1bmN0aW9uKHQpIHtcbiAgICAgIHJldHVybiB0LmtpbmQgPT09ICdhdWRpbyc7XG4gICAgfSkubGVuZ3RoO1xuICAgIHZhciBudW1WaWRlb1RyYWNrcyA9IHBjLnRyYW5zY2VpdmVycy5maWx0ZXIoZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIHQua2luZCA9PT0gJ3ZpZGVvJztcbiAgICB9KS5sZW5ndGg7XG5cbiAgICAvLyBEZXRlcm1pbmUgbnVtYmVyIG9mIGF1ZGlvIGFuZCB2aWRlbyB0cmFja3Mgd2UgbmVlZCB0byBzZW5kL3JlY3YuXG4gICAgdmFyIG9mZmVyT3B0aW9ucyA9IGFyZ3VtZW50c1swXTtcbiAgICBpZiAob2ZmZXJPcHRpb25zKSB7XG4gICAgICAvLyBSZWplY3QgQ2hyb21lIGxlZ2FjeSBjb25zdHJhaW50cy5cbiAgICAgIGlmIChvZmZlck9wdGlvbnMubWFuZGF0b3J5IHx8IG9mZmVyT3B0aW9ucy5vcHRpb25hbCkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgICAgJ0xlZ2FjeSBtYW5kYXRvcnkvb3B0aW9uYWwgY29uc3RyYWludHMgbm90IHN1cHBvcnRlZC4nKTtcbiAgICAgIH1cbiAgICAgIGlmIChvZmZlck9wdGlvbnMub2ZmZXJUb1JlY2VpdmVBdWRpbyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGlmIChvZmZlck9wdGlvbnMub2ZmZXJUb1JlY2VpdmVBdWRpbyA9PT0gdHJ1ZSkge1xuICAgICAgICAgIG51bUF1ZGlvVHJhY2tzID0gMTtcbiAgICAgICAgfSBlbHNlIGlmIChvZmZlck9wdGlvbnMub2ZmZXJUb1JlY2VpdmVBdWRpbyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICBudW1BdWRpb1RyYWNrcyA9IDA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbnVtQXVkaW9UcmFja3MgPSBvZmZlck9wdGlvbnMub2ZmZXJUb1JlY2VpdmVBdWRpbztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKG9mZmVyT3B0aW9ucy5vZmZlclRvUmVjZWl2ZVZpZGVvICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKG9mZmVyT3B0aW9ucy5vZmZlclRvUmVjZWl2ZVZpZGVvID09PSB0cnVlKSB7XG4gICAgICAgICAgbnVtVmlkZW9UcmFja3MgPSAxO1xuICAgICAgICB9IGVsc2UgaWYgKG9mZmVyT3B0aW9ucy5vZmZlclRvUmVjZWl2ZVZpZGVvID09PSBmYWxzZSkge1xuICAgICAgICAgIG51bVZpZGVvVHJhY2tzID0gMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBudW1WaWRlb1RyYWNrcyA9IG9mZmVyT3B0aW9ucy5vZmZlclRvUmVjZWl2ZVZpZGVvO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcGMudHJhbnNjZWl2ZXJzLmZvckVhY2goZnVuY3Rpb24odHJhbnNjZWl2ZXIpIHtcbiAgICAgIGlmICh0cmFuc2NlaXZlci5raW5kID09PSAnYXVkaW8nKSB7XG4gICAgICAgIG51bUF1ZGlvVHJhY2tzLS07XG4gICAgICAgIGlmIChudW1BdWRpb1RyYWNrcyA8IDApIHtcbiAgICAgICAgICB0cmFuc2NlaXZlci53YW50UmVjZWl2ZSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHRyYW5zY2VpdmVyLmtpbmQgPT09ICd2aWRlbycpIHtcbiAgICAgICAgbnVtVmlkZW9UcmFja3MtLTtcbiAgICAgICAgaWYgKG51bVZpZGVvVHJhY2tzIDwgMCkge1xuICAgICAgICAgIHRyYW5zY2VpdmVyLndhbnRSZWNlaXZlID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIENyZWF0ZSBNLWxpbmVzIGZvciByZWN2b25seSBzdHJlYW1zLlxuICAgIHdoaWxlIChudW1BdWRpb1RyYWNrcyA+IDAgfHwgbnVtVmlkZW9UcmFja3MgPiAwKSB7XG4gICAgICBpZiAobnVtQXVkaW9UcmFja3MgPiAwKSB7XG4gICAgICAgIHBjLl9jcmVhdGVUcmFuc2NlaXZlcignYXVkaW8nKTtcbiAgICAgICAgbnVtQXVkaW9UcmFja3MtLTtcbiAgICAgIH1cbiAgICAgIGlmIChudW1WaWRlb1RyYWNrcyA+IDApIHtcbiAgICAgICAgcGMuX2NyZWF0ZVRyYW5zY2VpdmVyKCd2aWRlbycpO1xuICAgICAgICBudW1WaWRlb1RyYWNrcy0tO1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBzZHAgPSBTRFBVdGlscy53cml0ZVNlc3Npb25Cb2lsZXJwbGF0ZShwYy5fc2RwU2Vzc2lvbklkLFxuICAgICAgICBwYy5fc2RwU2Vzc2lvblZlcnNpb24rKyk7XG4gICAgcGMudHJhbnNjZWl2ZXJzLmZvckVhY2goZnVuY3Rpb24odHJhbnNjZWl2ZXIsIHNkcE1MaW5lSW5kZXgpIHtcbiAgICAgIC8vIEZvciBlYWNoIHRyYWNrLCBjcmVhdGUgYW4gaWNlIGdhdGhlcmVyLCBpY2UgdHJhbnNwb3J0LFxuICAgICAgLy8gZHRscyB0cmFuc3BvcnQsIHBvdGVudGlhbGx5IHJ0cHNlbmRlciBhbmQgcnRwcmVjZWl2ZXIuXG4gICAgICB2YXIgdHJhY2sgPSB0cmFuc2NlaXZlci50cmFjaztcbiAgICAgIHZhciBraW5kID0gdHJhbnNjZWl2ZXIua2luZDtcbiAgICAgIHZhciBtaWQgPSB0cmFuc2NlaXZlci5taWQgfHwgU0RQVXRpbHMuZ2VuZXJhdGVJZGVudGlmaWVyKCk7XG4gICAgICB0cmFuc2NlaXZlci5taWQgPSBtaWQ7XG5cbiAgICAgIGlmICghdHJhbnNjZWl2ZXIuaWNlR2F0aGVyZXIpIHtcbiAgICAgICAgdHJhbnNjZWl2ZXIuaWNlR2F0aGVyZXIgPSBwYy5fY3JlYXRlSWNlR2F0aGVyZXIoc2RwTUxpbmVJbmRleCxcbiAgICAgICAgICAgIHBjLnVzaW5nQnVuZGxlKTtcbiAgICAgIH1cblxuICAgICAgdmFyIGxvY2FsQ2FwYWJpbGl0aWVzID0gd2luZG93LlJUQ1J0cFNlbmRlci5nZXRDYXBhYmlsaXRpZXMoa2luZCk7XG4gICAgICAvLyBmaWx0ZXIgUlRYIHVudGlsIGFkZGl0aW9uYWwgc3R1ZmYgbmVlZGVkIGZvciBSVFggaXMgaW1wbGVtZW50ZWRcbiAgICAgIC8vIGluIGFkYXB0ZXIuanNcbiAgICAgIGlmIChlZGdlVmVyc2lvbiA8IDE1MDE5KSB7XG4gICAgICAgIGxvY2FsQ2FwYWJpbGl0aWVzLmNvZGVjcyA9IGxvY2FsQ2FwYWJpbGl0aWVzLmNvZGVjcy5maWx0ZXIoXG4gICAgICAgICAgICBmdW5jdGlvbihjb2RlYykge1xuICAgICAgICAgICAgICByZXR1cm4gY29kZWMubmFtZSAhPT0gJ3J0eCc7XG4gICAgICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGxvY2FsQ2FwYWJpbGl0aWVzLmNvZGVjcy5mb3JFYWNoKGZ1bmN0aW9uKGNvZGVjKSB7XG4gICAgICAgIC8vIHdvcmsgYXJvdW5kIGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC93ZWJydGMvaXNzdWVzL2RldGFpbD9pZD02NTUyXG4gICAgICAgIC8vIGJ5IGFkZGluZyBsZXZlbC1hc3ltbWV0cnktYWxsb3dlZD0xXG4gICAgICAgIGlmIChjb2RlYy5uYW1lID09PSAnSDI2NCcgJiZcbiAgICAgICAgICAgIGNvZGVjLnBhcmFtZXRlcnNbJ2xldmVsLWFzeW1tZXRyeS1hbGxvd2VkJ10gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGNvZGVjLnBhcmFtZXRlcnNbJ2xldmVsLWFzeW1tZXRyeS1hbGxvd2VkJ10gPSAnMSc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBmb3Igc3Vic2VxdWVudCBvZmZlcnMsIHdlIG1pZ2h0IGhhdmUgdG8gcmUtdXNlIHRoZSBwYXlsb2FkXG4gICAgICAgIC8vIHR5cGUgb2YgdGhlIGxhc3Qgb2ZmZXIuXG4gICAgICAgIGlmICh0cmFuc2NlaXZlci5yZW1vdGVDYXBhYmlsaXRpZXMgJiZcbiAgICAgICAgICAgIHRyYW5zY2VpdmVyLnJlbW90ZUNhcGFiaWxpdGllcy5jb2RlY3MpIHtcbiAgICAgICAgICB0cmFuc2NlaXZlci5yZW1vdGVDYXBhYmlsaXRpZXMuY29kZWNzLmZvckVhY2goZnVuY3Rpb24ocmVtb3RlQ29kZWMpIHtcbiAgICAgICAgICAgIGlmIChjb2RlYy5uYW1lLnRvTG93ZXJDYXNlKCkgPT09IHJlbW90ZUNvZGVjLm5hbWUudG9Mb3dlckNhc2UoKSAmJlxuICAgICAgICAgICAgICAgIGNvZGVjLmNsb2NrUmF0ZSA9PT0gcmVtb3RlQ29kZWMuY2xvY2tSYXRlKSB7XG4gICAgICAgICAgICAgIGNvZGVjLnByZWZlcnJlZFBheWxvYWRUeXBlID0gcmVtb3RlQ29kZWMucGF5bG9hZFR5cGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgbG9jYWxDYXBhYmlsaXRpZXMuaGVhZGVyRXh0ZW5zaW9ucy5mb3JFYWNoKGZ1bmN0aW9uKGhkckV4dCkge1xuICAgICAgICB2YXIgcmVtb3RlRXh0ZW5zaW9ucyA9IHRyYW5zY2VpdmVyLnJlbW90ZUNhcGFiaWxpdGllcyAmJlxuICAgICAgICAgICAgdHJhbnNjZWl2ZXIucmVtb3RlQ2FwYWJpbGl0aWVzLmhlYWRlckV4dGVuc2lvbnMgfHwgW107XG4gICAgICAgIHJlbW90ZUV4dGVuc2lvbnMuZm9yRWFjaChmdW5jdGlvbihySGRyRXh0KSB7XG4gICAgICAgICAgaWYgKGhkckV4dC51cmkgPT09IHJIZHJFeHQudXJpKSB7XG4gICAgICAgICAgICBoZHJFeHQuaWQgPSBySGRyRXh0LmlkO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgLy8gZ2VuZXJhdGUgYW4gc3NyYyBub3csIHRvIGJlIHVzZWQgbGF0ZXIgaW4gcnRwU2VuZGVyLnNlbmRcbiAgICAgIHZhciBzZW5kRW5jb2RpbmdQYXJhbWV0ZXJzID0gdHJhbnNjZWl2ZXIuc2VuZEVuY29kaW5nUGFyYW1ldGVycyB8fCBbe1xuICAgICAgICBzc3JjOiAoMiAqIHNkcE1MaW5lSW5kZXggKyAxKSAqIDEwMDFcbiAgICAgIH1dO1xuICAgICAgaWYgKHRyYWNrKSB7XG4gICAgICAgIC8vIGFkZCBSVFhcbiAgICAgICAgaWYgKGVkZ2VWZXJzaW9uID49IDE1MDE5ICYmIGtpbmQgPT09ICd2aWRlbycgJiZcbiAgICAgICAgICAgICFzZW5kRW5jb2RpbmdQYXJhbWV0ZXJzWzBdLnJ0eCkge1xuICAgICAgICAgIHNlbmRFbmNvZGluZ1BhcmFtZXRlcnNbMF0ucnR4ID0ge1xuICAgICAgICAgICAgc3NyYzogc2VuZEVuY29kaW5nUGFyYW1ldGVyc1swXS5zc3JjICsgMVxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHRyYW5zY2VpdmVyLndhbnRSZWNlaXZlKSB7XG4gICAgICAgIHRyYW5zY2VpdmVyLnJ0cFJlY2VpdmVyID0gbmV3IHdpbmRvdy5SVENSdHBSZWNlaXZlcihcbiAgICAgICAgICAgIHRyYW5zY2VpdmVyLmR0bHNUcmFuc3BvcnQsIGtpbmQpO1xuICAgICAgfVxuXG4gICAgICB0cmFuc2NlaXZlci5sb2NhbENhcGFiaWxpdGllcyA9IGxvY2FsQ2FwYWJpbGl0aWVzO1xuICAgICAgdHJhbnNjZWl2ZXIuc2VuZEVuY29kaW5nUGFyYW1ldGVycyA9IHNlbmRFbmNvZGluZ1BhcmFtZXRlcnM7XG4gICAgfSk7XG5cbiAgICAvLyBhbHdheXMgb2ZmZXIgQlVORExFIGFuZCBkaXNwb3NlIG9uIHJldHVybiBpZiBub3Qgc3VwcG9ydGVkLlxuICAgIGlmIChwYy5fY29uZmlnLmJ1bmRsZVBvbGljeSAhPT0gJ21heC1jb21wYXQnKSB7XG4gICAgICBzZHAgKz0gJ2E9Z3JvdXA6QlVORExFICcgKyBwYy50cmFuc2NlaXZlcnMubWFwKGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgcmV0dXJuIHQubWlkO1xuICAgICAgfSkuam9pbignICcpICsgJ1xcclxcbic7XG4gICAgfVxuICAgIHNkcCArPSAnYT1pY2Utb3B0aW9uczp0cmlja2xlXFxyXFxuJztcblxuICAgIHBjLnRyYW5zY2VpdmVycy5mb3JFYWNoKGZ1bmN0aW9uKHRyYW5zY2VpdmVyLCBzZHBNTGluZUluZGV4KSB7XG4gICAgICBzZHAgKz0gd3JpdGVNZWRpYVNlY3Rpb24odHJhbnNjZWl2ZXIsIHRyYW5zY2VpdmVyLmxvY2FsQ2FwYWJpbGl0aWVzLFxuICAgICAgICAgICdvZmZlcicsIHRyYW5zY2VpdmVyLnN0cmVhbSwgcGMuX2R0bHNSb2xlKTtcbiAgICAgIHNkcCArPSAnYT1ydGNwLXJzaXplXFxyXFxuJztcblxuICAgICAgaWYgKHRyYW5zY2VpdmVyLmljZUdhdGhlcmVyICYmIHBjLmljZUdhdGhlcmluZ1N0YXRlICE9PSAnbmV3JyAmJlxuICAgICAgICAgIChzZHBNTGluZUluZGV4ID09PSAwIHx8ICFwYy51c2luZ0J1bmRsZSkpIHtcbiAgICAgICAgdHJhbnNjZWl2ZXIuaWNlR2F0aGVyZXIuZ2V0TG9jYWxDYW5kaWRhdGVzKCkuZm9yRWFjaChmdW5jdGlvbihjYW5kKSB7XG4gICAgICAgICAgY2FuZC5jb21wb25lbnQgPSAxO1xuICAgICAgICAgIHNkcCArPSAnYT0nICsgU0RQVXRpbHMud3JpdGVDYW5kaWRhdGUoY2FuZCkgKyAnXFxyXFxuJztcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHRyYW5zY2VpdmVyLmljZUdhdGhlcmVyLnN0YXRlID09PSAnY29tcGxldGVkJykge1xuICAgICAgICAgIHNkcCArPSAnYT1lbmQtb2YtY2FuZGlkYXRlc1xcclxcbic7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHZhciBkZXNjID0gbmV3IHdpbmRvdy5SVENTZXNzaW9uRGVzY3JpcHRpb24oe1xuICAgICAgdHlwZTogJ29mZmVyJyxcbiAgICAgIHNkcDogc2RwXG4gICAgfSk7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShkZXNjKTtcbiAgfTtcblxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuY3JlYXRlQW5zd2VyID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHBjID0gdGhpcztcblxuICAgIGlmIChwYy5faXNDbG9zZWQpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChtYWtlRXJyb3IoJ0ludmFsaWRTdGF0ZUVycm9yJyxcbiAgICAgICAgICAnQ2FuIG5vdCBjYWxsIGNyZWF0ZUFuc3dlciBhZnRlciBjbG9zZScpKTtcbiAgICB9XG5cbiAgICBpZiAoIShwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2hhdmUtcmVtb3RlLW9mZmVyJyB8fFxuICAgICAgICBwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2hhdmUtbG9jYWwtcHJhbnN3ZXInKSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG1ha2VFcnJvcignSW52YWxpZFN0YXRlRXJyb3InLFxuICAgICAgICAgICdDYW4gbm90IGNhbGwgY3JlYXRlQW5zd2VyIGluIHNpZ25hbGluZ1N0YXRlICcgKyBwYy5zaWduYWxpbmdTdGF0ZSkpO1xuICAgIH1cblxuICAgIHZhciBzZHAgPSBTRFBVdGlscy53cml0ZVNlc3Npb25Cb2lsZXJwbGF0ZShwYy5fc2RwU2Vzc2lvbklkLFxuICAgICAgICBwYy5fc2RwU2Vzc2lvblZlcnNpb24rKyk7XG4gICAgaWYgKHBjLnVzaW5nQnVuZGxlKSB7XG4gICAgICBzZHAgKz0gJ2E9Z3JvdXA6QlVORExFICcgKyBwYy50cmFuc2NlaXZlcnMubWFwKGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgcmV0dXJuIHQubWlkO1xuICAgICAgfSkuam9pbignICcpICsgJ1xcclxcbic7XG4gICAgfVxuICAgIHZhciBtZWRpYVNlY3Rpb25zSW5PZmZlciA9IFNEUFV0aWxzLmdldE1lZGlhU2VjdGlvbnMoXG4gICAgICAgIHBjLnJlbW90ZURlc2NyaXB0aW9uLnNkcCkubGVuZ3RoO1xuICAgIHBjLnRyYW5zY2VpdmVycy5mb3JFYWNoKGZ1bmN0aW9uKHRyYW5zY2VpdmVyLCBzZHBNTGluZUluZGV4KSB7XG4gICAgICBpZiAoc2RwTUxpbmVJbmRleCArIDEgPiBtZWRpYVNlY3Rpb25zSW5PZmZlcikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAodHJhbnNjZWl2ZXIucmVqZWN0ZWQpIHtcbiAgICAgICAgaWYgKHRyYW5zY2VpdmVyLmtpbmQgPT09ICdhcHBsaWNhdGlvbicpIHtcbiAgICAgICAgICBzZHAgKz0gJ209YXBwbGljYXRpb24gMCBEVExTL1NDVFAgNTAwMFxcclxcbic7XG4gICAgICAgIH0gZWxzZSBpZiAodHJhbnNjZWl2ZXIua2luZCA9PT0gJ2F1ZGlvJykge1xuICAgICAgICAgIHNkcCArPSAnbT1hdWRpbyAwIFVEUC9UTFMvUlRQL1NBVlBGIDBcXHJcXG4nICtcbiAgICAgICAgICAgICAgJ2E9cnRwbWFwOjAgUENNVS84MDAwXFxyXFxuJztcbiAgICAgICAgfSBlbHNlIGlmICh0cmFuc2NlaXZlci5raW5kID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgc2RwICs9ICdtPXZpZGVvIDAgVURQL1RMUy9SVFAvU0FWUEYgMTIwXFxyXFxuJyArXG4gICAgICAgICAgICAgICdhPXJ0cG1hcDoxMjAgVlA4LzkwMDAwXFxyXFxuJztcbiAgICAgICAgfVxuICAgICAgICBzZHAgKz0gJ2M9SU4gSVA0IDAuMC4wLjBcXHJcXG4nICtcbiAgICAgICAgICAgICdhPWluYWN0aXZlXFxyXFxuJyArXG4gICAgICAgICAgICAnYT1taWQ6JyArIHRyYW5zY2VpdmVyLm1pZCArICdcXHJcXG4nO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIEZJWE1FOiBsb29rIGF0IGRpcmVjdGlvbi5cbiAgICAgIGlmICh0cmFuc2NlaXZlci5zdHJlYW0pIHtcbiAgICAgICAgdmFyIGxvY2FsVHJhY2s7XG4gICAgICAgIGlmICh0cmFuc2NlaXZlci5raW5kID09PSAnYXVkaW8nKSB7XG4gICAgICAgICAgbG9jYWxUcmFjayA9IHRyYW5zY2VpdmVyLnN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdO1xuICAgICAgICB9IGVsc2UgaWYgKHRyYW5zY2VpdmVyLmtpbmQgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICBsb2NhbFRyYWNrID0gdHJhbnNjZWl2ZXIuc3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGxvY2FsVHJhY2spIHtcbiAgICAgICAgICAvLyBhZGQgUlRYXG4gICAgICAgICAgaWYgKGVkZ2VWZXJzaW9uID49IDE1MDE5ICYmIHRyYW5zY2VpdmVyLmtpbmQgPT09ICd2aWRlbycgJiZcbiAgICAgICAgICAgICAgIXRyYW5zY2VpdmVyLnNlbmRFbmNvZGluZ1BhcmFtZXRlcnNbMF0ucnR4KSB7XG4gICAgICAgICAgICB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzWzBdLnJ0eCA9IHtcbiAgICAgICAgICAgICAgc3NyYzogdHJhbnNjZWl2ZXIuc2VuZEVuY29kaW5nUGFyYW1ldGVyc1swXS5zc3JjICsgMVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gQ2FsY3VsYXRlIGludGVyc2VjdGlvbiBvZiBjYXBhYmlsaXRpZXMuXG4gICAgICB2YXIgY29tbW9uQ2FwYWJpbGl0aWVzID0gZ2V0Q29tbW9uQ2FwYWJpbGl0aWVzKFxuICAgICAgICAgIHRyYW5zY2VpdmVyLmxvY2FsQ2FwYWJpbGl0aWVzLFxuICAgICAgICAgIHRyYW5zY2VpdmVyLnJlbW90ZUNhcGFiaWxpdGllcyk7XG5cbiAgICAgIHZhciBoYXNSdHggPSBjb21tb25DYXBhYmlsaXRpZXMuY29kZWNzLmZpbHRlcihmdW5jdGlvbihjKSB7XG4gICAgICAgIHJldHVybiBjLm5hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ3J0eCc7XG4gICAgICB9KS5sZW5ndGg7XG4gICAgICBpZiAoIWhhc1J0eCAmJiB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzWzBdLnJ0eCkge1xuICAgICAgICBkZWxldGUgdHJhbnNjZWl2ZXIuc2VuZEVuY29kaW5nUGFyYW1ldGVyc1swXS5ydHg7XG4gICAgICB9XG5cbiAgICAgIHNkcCArPSB3cml0ZU1lZGlhU2VjdGlvbih0cmFuc2NlaXZlciwgY29tbW9uQ2FwYWJpbGl0aWVzLFxuICAgICAgICAgICdhbnN3ZXInLCB0cmFuc2NlaXZlci5zdHJlYW0sIHBjLl9kdGxzUm9sZSk7XG4gICAgICBpZiAodHJhbnNjZWl2ZXIucnRjcFBhcmFtZXRlcnMgJiZcbiAgICAgICAgICB0cmFuc2NlaXZlci5ydGNwUGFyYW1ldGVycy5yZWR1Y2VkU2l6ZSkge1xuICAgICAgICBzZHAgKz0gJ2E9cnRjcC1yc2l6ZVxcclxcbic7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB2YXIgZGVzYyA9IG5ldyB3aW5kb3cuUlRDU2Vzc2lvbkRlc2NyaXB0aW9uKHtcbiAgICAgIHR5cGU6ICdhbnN3ZXInLFxuICAgICAgc2RwOiBzZHBcbiAgICB9KTtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGRlc2MpO1xuICB9O1xuXG4gIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5hZGRJY2VDYW5kaWRhdGUgPSBmdW5jdGlvbihjYW5kaWRhdGUpIHtcbiAgICB2YXIgcGMgPSB0aGlzO1xuICAgIHZhciBzZWN0aW9ucztcbiAgICBpZiAoY2FuZGlkYXRlICYmICEoY2FuZGlkYXRlLnNkcE1MaW5lSW5kZXggIT09IHVuZGVmaW5lZCB8fFxuICAgICAgICBjYW5kaWRhdGUuc2RwTWlkKSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBUeXBlRXJyb3IoJ3NkcE1MaW5lSW5kZXggb3Igc2RwTWlkIHJlcXVpcmVkJykpO1xuICAgIH1cblxuICAgIC8vIFRPRE86IG5lZWRzIHRvIGdvIGludG8gb3BzIHF1ZXVlLlxuICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIGlmICghcGMucmVtb3RlRGVzY3JpcHRpb24pIHtcbiAgICAgICAgcmV0dXJuIHJlamVjdChtYWtlRXJyb3IoJ0ludmFsaWRTdGF0ZUVycm9yJyxcbiAgICAgICAgICAgICdDYW4gbm90IGFkZCBJQ0UgY2FuZGlkYXRlIHdpdGhvdXQgYSByZW1vdGUgZGVzY3JpcHRpb24nKSk7XG4gICAgICB9IGVsc2UgaWYgKCFjYW5kaWRhdGUgfHwgY2FuZGlkYXRlLmNhbmRpZGF0ZSA9PT0gJycpIHtcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBwYy50cmFuc2NlaXZlcnMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICBpZiAocGMudHJhbnNjZWl2ZXJzW2pdLnJlamVjdGVkKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcGMudHJhbnNjZWl2ZXJzW2pdLmljZVRyYW5zcG9ydC5hZGRSZW1vdGVDYW5kaWRhdGUoe30pO1xuICAgICAgICAgIHNlY3Rpb25zID0gU0RQVXRpbHMuZ2V0TWVkaWFTZWN0aW9ucyhwYy5yZW1vdGVEZXNjcmlwdGlvbi5zZHApO1xuICAgICAgICAgIHNlY3Rpb25zW2pdICs9ICdhPWVuZC1vZi1jYW5kaWRhdGVzXFxyXFxuJztcbiAgICAgICAgICBwYy5yZW1vdGVEZXNjcmlwdGlvbi5zZHAgPVxuICAgICAgICAgICAgICBTRFBVdGlscy5nZXREZXNjcmlwdGlvbihwYy5yZW1vdGVEZXNjcmlwdGlvbi5zZHApICtcbiAgICAgICAgICAgICAgc2VjdGlvbnMuam9pbignJyk7XG4gICAgICAgICAgaWYgKHBjLnVzaW5nQnVuZGxlKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBzZHBNTGluZUluZGV4ID0gY2FuZGlkYXRlLnNkcE1MaW5lSW5kZXg7XG4gICAgICAgIGlmIChjYW5kaWRhdGUuc2RwTWlkKSB7XG4gICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYy50cmFuc2NlaXZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChwYy50cmFuc2NlaXZlcnNbaV0ubWlkID09PSBjYW5kaWRhdGUuc2RwTWlkKSB7XG4gICAgICAgICAgICAgIHNkcE1MaW5lSW5kZXggPSBpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHRyYW5zY2VpdmVyID0gcGMudHJhbnNjZWl2ZXJzW3NkcE1MaW5lSW5kZXhdO1xuICAgICAgICBpZiAodHJhbnNjZWl2ZXIpIHtcbiAgICAgICAgICBpZiAodHJhbnNjZWl2ZXIucmVqZWN0ZWQpIHtcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZlKCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhciBjYW5kID0gT2JqZWN0LmtleXMoY2FuZGlkYXRlLmNhbmRpZGF0ZSkubGVuZ3RoID4gMCA/XG4gICAgICAgICAgICAgIFNEUFV0aWxzLnBhcnNlQ2FuZGlkYXRlKGNhbmRpZGF0ZS5jYW5kaWRhdGUpIDoge307XG4gICAgICAgICAgLy8gSWdub3JlIENocm9tZSdzIGludmFsaWQgY2FuZGlkYXRlcyBzaW5jZSBFZGdlIGRvZXMgbm90IGxpa2UgdGhlbS5cbiAgICAgICAgICBpZiAoY2FuZC5wcm90b2NvbCA9PT0gJ3RjcCcgJiYgKGNhbmQucG9ydCA9PT0gMCB8fCBjYW5kLnBvcnQgPT09IDkpKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBJZ25vcmUgUlRDUCBjYW5kaWRhdGVzLCB3ZSBhc3N1bWUgUlRDUC1NVVguXG4gICAgICAgICAgaWYgKGNhbmQuY29tcG9uZW50ICYmIGNhbmQuY29tcG9uZW50ICE9PSAxKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyB3aGVuIHVzaW5nIGJ1bmRsZSwgYXZvaWQgYWRkaW5nIGNhbmRpZGF0ZXMgdG8gdGhlIHdyb25nXG4gICAgICAgICAgLy8gaWNlIHRyYW5zcG9ydC4gQW5kIGF2b2lkIGFkZGluZyBjYW5kaWRhdGVzIGFkZGVkIGluIHRoZSBTRFAuXG4gICAgICAgICAgaWYgKHNkcE1MaW5lSW5kZXggPT09IDAgfHwgKHNkcE1MaW5lSW5kZXggPiAwICYmXG4gICAgICAgICAgICAgIHRyYW5zY2VpdmVyLmljZVRyYW5zcG9ydCAhPT0gcGMudHJhbnNjZWl2ZXJzWzBdLmljZVRyYW5zcG9ydCkpIHtcbiAgICAgICAgICAgIGlmICghbWF5YmVBZGRDYW5kaWRhdGUodHJhbnNjZWl2ZXIuaWNlVHJhbnNwb3J0LCBjYW5kKSkge1xuICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KG1ha2VFcnJvcignT3BlcmF0aW9uRXJyb3InLFxuICAgICAgICAgICAgICAgICAgJ0NhbiBub3QgYWRkIElDRSBjYW5kaWRhdGUnKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gdXBkYXRlIHRoZSByZW1vdGVEZXNjcmlwdGlvbi5cbiAgICAgICAgICB2YXIgY2FuZGlkYXRlU3RyaW5nID0gY2FuZGlkYXRlLmNhbmRpZGF0ZS50cmltKCk7XG4gICAgICAgICAgaWYgKGNhbmRpZGF0ZVN0cmluZy5pbmRleE9mKCdhPScpID09PSAwKSB7XG4gICAgICAgICAgICBjYW5kaWRhdGVTdHJpbmcgPSBjYW5kaWRhdGVTdHJpbmcuc3Vic3RyKDIpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzZWN0aW9ucyA9IFNEUFV0aWxzLmdldE1lZGlhU2VjdGlvbnMocGMucmVtb3RlRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICBzZWN0aW9uc1tzZHBNTGluZUluZGV4XSArPSAnYT0nICtcbiAgICAgICAgICAgICAgKGNhbmQudHlwZSA/IGNhbmRpZGF0ZVN0cmluZyA6ICdlbmQtb2YtY2FuZGlkYXRlcycpXG4gICAgICAgICAgICAgICsgJ1xcclxcbic7XG4gICAgICAgICAgcGMucmVtb3RlRGVzY3JpcHRpb24uc2RwID0gc2VjdGlvbnMuam9pbignJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChtYWtlRXJyb3IoJ09wZXJhdGlvbkVycm9yJyxcbiAgICAgICAgICAgICAgJ0NhbiBub3QgYWRkIElDRSBjYW5kaWRhdGUnKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJlc29sdmUoKTtcbiAgICB9KTtcbiAgfTtcblxuICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuZ2V0U3RhdHMgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgcHJvbWlzZXMgPSBbXTtcbiAgICB0aGlzLnRyYW5zY2VpdmVycy5mb3JFYWNoKGZ1bmN0aW9uKHRyYW5zY2VpdmVyKSB7XG4gICAgICBbJ3J0cFNlbmRlcicsICdydHBSZWNlaXZlcicsICdpY2VHYXRoZXJlcicsICdpY2VUcmFuc3BvcnQnLFxuICAgICAgICAgICdkdGxzVHJhbnNwb3J0J10uZm9yRWFjaChmdW5jdGlvbihtZXRob2QpIHtcbiAgICAgICAgICAgIGlmICh0cmFuc2NlaXZlclttZXRob2RdKSB7XG4gICAgICAgICAgICAgIHByb21pc2VzLnB1c2godHJhbnNjZWl2ZXJbbWV0aG9kXS5nZXRTdGF0cygpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICB9KTtcbiAgICB2YXIgZml4U3RhdHNUeXBlID0gZnVuY3Rpb24oc3RhdCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaW5ib3VuZHJ0cDogJ2luYm91bmQtcnRwJyxcbiAgICAgICAgb3V0Ym91bmRydHA6ICdvdXRib3VuZC1ydHAnLFxuICAgICAgICBjYW5kaWRhdGVwYWlyOiAnY2FuZGlkYXRlLXBhaXInLFxuICAgICAgICBsb2NhbGNhbmRpZGF0ZTogJ2xvY2FsLWNhbmRpZGF0ZScsXG4gICAgICAgIHJlbW90ZWNhbmRpZGF0ZTogJ3JlbW90ZS1jYW5kaWRhdGUnXG4gICAgICB9W3N0YXQudHlwZV0gfHwgc3RhdC50eXBlO1xuICAgIH07XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUpIHtcbiAgICAgIC8vIHNoaW0gZ2V0U3RhdHMgd2l0aCBtYXBsaWtlIHN1cHBvcnRcbiAgICAgIHZhciByZXN1bHRzID0gbmV3IE1hcCgpO1xuICAgICAgUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24ocmVzKSB7XG4gICAgICAgIHJlcy5mb3JFYWNoKGZ1bmN0aW9uKHJlc3VsdCkge1xuICAgICAgICAgIE9iamVjdC5rZXlzKHJlc3VsdCkuZm9yRWFjaChmdW5jdGlvbihpZCkge1xuICAgICAgICAgICAgcmVzdWx0W2lkXS50eXBlID0gZml4U3RhdHNUeXBlKHJlc3VsdFtpZF0pO1xuICAgICAgICAgICAgcmVzdWx0cy5zZXQoaWQsIHJlc3VsdFtpZF0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmVzb2x2ZShyZXN1bHRzKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9O1xuXG4gIC8vIGxlZ2FjeSBjYWxsYmFjayBzaGltcy4gU2hvdWxkIGJlIG1vdmVkIHRvIGFkYXB0ZXIuanMgc29tZSBkYXlzLlxuICB2YXIgbWV0aG9kcyA9IFsnY3JlYXRlT2ZmZXInLCAnY3JlYXRlQW5zd2VyJ107XG4gIG1ldGhvZHMuZm9yRWFjaChmdW5jdGlvbihtZXRob2QpIHtcbiAgICB2YXIgbmF0aXZlTWV0aG9kID0gUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlW21ldGhvZF07XG4gICAgUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlW21ldGhvZF0gPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgaWYgKHR5cGVvZiBhcmdzWzBdID09PSAnZnVuY3Rpb24nIHx8XG4gICAgICAgICAgdHlwZW9mIGFyZ3NbMV0gPT09ICdmdW5jdGlvbicpIHsgLy8gbGVnYWN5XG4gICAgICAgIHJldHVybiBuYXRpdmVNZXRob2QuYXBwbHkodGhpcywgW2FyZ3VtZW50c1syXV0pXG4gICAgICAgIC50aGVuKGZ1bmN0aW9uKGRlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBhcmdzWzBdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBhcmdzWzBdLmFwcGx5KG51bGwsIFtkZXNjcmlwdGlvbl0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSwgZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGFyZ3NbMV0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGFyZ3NbMV0uYXBwbHkobnVsbCwgW2Vycm9yXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuYXRpdmVNZXRob2QuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9O1xuICB9KTtcblxuICBtZXRob2RzID0gWydzZXRMb2NhbERlc2NyaXB0aW9uJywgJ3NldFJlbW90ZURlc2NyaXB0aW9uJywgJ2FkZEljZUNhbmRpZGF0ZSddO1xuICBtZXRob2RzLmZvckVhY2goZnVuY3Rpb24obWV0aG9kKSB7XG4gICAgdmFyIG5hdGl2ZU1ldGhvZCA9IFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZVttZXRob2RdO1xuICAgIFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZVttZXRob2RdID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgIGlmICh0eXBlb2YgYXJnc1sxXSA9PT0gJ2Z1bmN0aW9uJyB8fFxuICAgICAgICAgIHR5cGVvZiBhcmdzWzJdID09PSAnZnVuY3Rpb24nKSB7IC8vIGxlZ2FjeVxuICAgICAgICByZXR1cm4gbmF0aXZlTWV0aG9kLmFwcGx5KHRoaXMsIGFyZ3VtZW50cylcbiAgICAgICAgLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBhcmdzWzFdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBhcmdzWzFdLmFwcGx5KG51bGwpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSwgZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGFyZ3NbMl0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGFyZ3NbMl0uYXBwbHkobnVsbCwgW2Vycm9yXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuYXRpdmVNZXRob2QuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9O1xuICB9KTtcblxuICAvLyBnZXRTdGF0cyBpcyBzcGVjaWFsLiBJdCBkb2Vzbid0IGhhdmUgYSBzcGVjIGxlZ2FjeSBtZXRob2QgeWV0IHdlIHN1cHBvcnRcbiAgLy8gZ2V0U3RhdHMoc29tZXRoaW5nLCBjYikgd2l0aG91dCBlcnJvciBjYWxsYmFja3MuXG4gIFsnZ2V0U3RhdHMnXS5mb3JFYWNoKGZ1bmN0aW9uKG1ldGhvZCkge1xuICAgIHZhciBuYXRpdmVNZXRob2QgPSBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGVbbWV0aG9kXTtcbiAgICBSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGVbbWV0aG9kXSA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICBpZiAodHlwZW9mIGFyZ3NbMV0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIG5hdGl2ZU1ldGhvZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpXG4gICAgICAgIC50aGVuKGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGlmICh0eXBlb2YgYXJnc1sxXSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgYXJnc1sxXS5hcHBseShudWxsKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG5hdGl2ZU1ldGhvZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG4gIH0pO1xuXG4gIHJldHVybiBSVENQZWVyQ29ubmVjdGlvbjtcbn07XG4iLCJ2YXIgZ3JhbW1hciA9IG1vZHVsZS5leHBvcnRzID0ge1xuICB2OiBbe1xuICAgICAgbmFtZTogJ3ZlcnNpb24nLFxuICAgICAgcmVnOiAvXihcXGQqKSQvXG4gIH1dLFxuICBvOiBbeyAvL289LSAyMDUxOCAwIElOIElQNCAyMDMuMC4xMTMuMVxuICAgIC8vIE5COiBzZXNzaW9uSWQgd2lsbCBiZSBhIFN0cmluZyBpbiBtb3N0IGNhc2VzIGJlY2F1c2UgaXQgaXMgaHVnZVxuICAgIG5hbWU6ICdvcmlnaW4nLFxuICAgIHJlZzogL14oXFxTKikgKFxcZCopIChcXGQqKSAoXFxTKikgSVAoXFxkKSAoXFxTKikvLFxuICAgIG5hbWVzOiBbJ3VzZXJuYW1lJywgJ3Nlc3Npb25JZCcsICdzZXNzaW9uVmVyc2lvbicsICduZXRUeXBlJywgJ2lwVmVyJywgJ2FkZHJlc3MnXSxcbiAgICBmb3JtYXQ6IFwiJXMgJXMgJWQgJXMgSVAlZCAlc1wiXG4gIH1dLFxuICAvLyBkZWZhdWx0IHBhcnNpbmcgb2YgdGhlc2Ugb25seSAodGhvdWdoIHNvbWUgb2YgdGhlc2UgZmVlbCBvdXRkYXRlZClcbiAgczogW3sgbmFtZTogJ25hbWUnIH1dLFxuICBpOiBbeyBuYW1lOiAnZGVzY3JpcHRpb24nIH1dLFxuICB1OiBbeyBuYW1lOiAndXJpJyB9XSxcbiAgZTogW3sgbmFtZTogJ2VtYWlsJyB9XSxcbiAgcDogW3sgbmFtZTogJ3Bob25lJyB9XSxcbiAgejogW3sgbmFtZTogJ3RpbWV6b25lcycgfV0sIC8vIFRPRE86IHRoaXMgb25lIGNhbiBhY3R1YWxseSBiZSBwYXJzZWQgcHJvcGVybHkuLlxuICByOiBbeyBuYW1lOiAncmVwZWF0cycgfV0sICAgLy8gVE9ETzogdGhpcyBvbmUgY2FuIGFsc28gYmUgcGFyc2VkIHByb3Blcmx5XG4gIC8vazogW3t9XSwgLy8gb3V0ZGF0ZWQgdGhpbmcgaWdub3JlZFxuICB0OiBbeyAvL3Q9MCAwXG4gICAgbmFtZTogJ3RpbWluZycsXG4gICAgcmVnOiAvXihcXGQqKSAoXFxkKikvLFxuICAgIG5hbWVzOiBbJ3N0YXJ0JywgJ3N0b3AnXSxcbiAgICBmb3JtYXQ6IFwiJWQgJWRcIlxuICB9XSxcbiAgYzogW3sgLy9jPUlOIElQNCAxMC40Ny4xOTcuMjZcbiAgICAgIG5hbWU6ICdjb25uZWN0aW9uJyxcbiAgICAgIHJlZzogL15JTiBJUChcXGQpIChcXFMqKS8sXG4gICAgICBuYW1lczogWyd2ZXJzaW9uJywgJ2lwJ10sXG4gICAgICBmb3JtYXQ6IFwiSU4gSVAlZCAlc1wiXG4gIH1dLFxuICBiOiBbeyAvL2I9QVM6NDAwMFxuICAgICAgcHVzaDogJ2JhbmR3aWR0aCcsXG4gICAgICByZWc6IC9eKFRJQVN8QVN8Q1R8UlJ8UlMpOihcXGQqKS8sXG4gICAgICBuYW1lczogWyd0eXBlJywgJ2xpbWl0J10sXG4gICAgICBmb3JtYXQ6IFwiJXM6JXNcIlxuICB9XSxcbiAgbTogW3sgLy9tPXZpZGVvIDUxNzQ0IFJUUC9BVlAgMTI2IDk3IDk4IDM0IDMxXG4gICAgICAvLyBOQjogc3BlY2lhbCAtIHB1c2hlcyB0byBzZXNzaW9uXG4gICAgICAvLyBUT0RPOiBydHAvZm10cCBzaG91bGQgYmUgZmlsdGVyZWQgYnkgdGhlIHBheWxvYWRzIGZvdW5kIGhlcmU/XG4gICAgICByZWc6IC9eKFxcdyopIChcXGQqKSAoW1xcd1xcL10qKSg/OiAoLiopKT8vLFxuICAgICAgbmFtZXM6IFsndHlwZScsICdwb3J0JywgJ3Byb3RvY29sJywgJ3BheWxvYWRzJ10sXG4gICAgICBmb3JtYXQ6IFwiJXMgJWQgJXMgJXNcIlxuICB9XSxcbiAgYTogW1xuICAgIHsgLy9hPXJ0cG1hcDoxMTAgb3B1cy80ODAwMC8yXG4gICAgICBwdXNoOiAncnRwJyxcbiAgICAgIHJlZzogL15ydHBtYXA6KFxcZCopIChbXFx3XFwtXSopKD86XFxzKlxcLyhcXGQqKSg/OlxccypcXC8oXFxTKikpPyk/LyxcbiAgICAgIG5hbWVzOiBbJ3BheWxvYWQnLCAnY29kZWMnLCAncmF0ZScsICdlbmNvZGluZyddLFxuICAgICAgZm9ybWF0OiBmdW5jdGlvbiAobykge1xuICAgICAgICByZXR1cm4gKG8uZW5jb2RpbmcpID9cbiAgICAgICAgICBcInJ0cG1hcDolZCAlcy8lcy8lc1wiOlxuICAgICAgICAgIG8ucmF0ZSA/XG4gICAgICAgICAgXCJydHBtYXA6JWQgJXMvJXNcIjpcbiAgICAgICAgICBcInJ0cG1hcDolZCAlc1wiO1xuICAgICAgfVxuICAgIH0sXG4gICAge1xuICAgICAgLy9hPWZtdHA6MTA4IHByb2ZpbGUtbGV2ZWwtaWQ9MjQ7b2JqZWN0PTIzO2JpdHJhdGU9NjQwMDBcbiAgICAgIC8vYT1mbXRwOjExMSBtaW5wdGltZT0xMDsgdXNlaW5iYW5kZmVjPTFcbiAgICAgIHB1c2g6ICdmbXRwJyxcbiAgICAgIHJlZzogL15mbXRwOihcXGQqKSAoW1xcU3wgXSopLyxcbiAgICAgIG5hbWVzOiBbJ3BheWxvYWQnLCAnY29uZmlnJ10sXG4gICAgICBmb3JtYXQ6IFwiZm10cDolZCAlc1wiXG4gICAgfSxcbiAgICB7IC8vYT1jb250cm9sOnN0cmVhbWlkPTBcbiAgICAgICAgbmFtZTogJ2NvbnRyb2wnLFxuICAgICAgICByZWc6IC9eY29udHJvbDooLiopLyxcbiAgICAgICAgZm9ybWF0OiBcImNvbnRyb2w6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9cnRjcDo2NTE3OSBJTiBJUDQgMTkzLjg0Ljc3LjE5NFxuICAgICAgbmFtZTogJ3J0Y3AnLFxuICAgICAgcmVnOiAvXnJ0Y3A6KFxcZCopKD86IChcXFMqKSBJUChcXGQpIChcXFMqKSk/LyxcbiAgICAgIG5hbWVzOiBbJ3BvcnQnLCAnbmV0VHlwZScsICdpcFZlcicsICdhZGRyZXNzJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAoby5hZGRyZXNzICE9IG51bGwpID9cbiAgICAgICAgICBcInJ0Y3A6JWQgJXMgSVAlZCAlc1wiOlxuICAgICAgICAgIFwicnRjcDolZFwiO1xuICAgICAgfVxuICAgIH0sXG4gICAgeyAvL2E9cnRjcC1mYjo5OCB0cnItaW50IDEwMFxuICAgICAgcHVzaDogJ3J0Y3BGYlRyckludCcsXG4gICAgICByZWc6IC9ecnRjcC1mYjooXFwqfFxcZCopIHRyci1pbnQgKFxcZCopLyxcbiAgICAgIG5hbWVzOiBbJ3BheWxvYWQnLCAndmFsdWUnXSxcbiAgICAgIGZvcm1hdDogXCJydGNwLWZiOiVkIHRyci1pbnQgJWRcIlxuICAgIH0sXG4gICAgeyAvL2E9cnRjcC1mYjo5OCBuYWNrIHJwc2lcbiAgICAgIHB1c2g6ICdydGNwRmInLFxuICAgICAgcmVnOiAvXnJ0Y3AtZmI6KFxcKnxcXGQqKSAoW1xcdy1fXSopKD86IChbXFx3LV9dKikpPy8sXG4gICAgICBuYW1lczogWydwYXlsb2FkJywgJ3R5cGUnLCAnc3VidHlwZSddLFxuICAgICAgZm9ybWF0OiBmdW5jdGlvbiAobykge1xuICAgICAgICByZXR1cm4gKG8uc3VidHlwZSAhPSBudWxsKSA/XG4gICAgICAgICAgXCJydGNwLWZiOiVzICVzICVzXCI6XG4gICAgICAgICAgXCJydGNwLWZiOiVzICVzXCI7XG4gICAgICB9XG4gICAgfSxcbiAgICB7IC8vYT1leHRtYXA6MiB1cm46aWV0ZjpwYXJhbXM6cnRwLWhkcmV4dDp0b2Zmc2V0XG4gICAgICAvL2E9ZXh0bWFwOjEvcmVjdm9ubHkgVVJJLWdwcy1zdHJpbmdcbiAgICAgIHB1c2g6ICdleHQnLFxuICAgICAgcmVnOiAvXmV4dG1hcDooW1xcd19cXC9dKikgKFxcUyopKD86IChcXFMqKSk/LyxcbiAgICAgIG5hbWVzOiBbJ3ZhbHVlJywgJ3VyaScsICdjb25maWcnXSwgLy8gdmFsdWUgbWF5IGluY2x1ZGUgXCIvZGlyZWN0aW9uXCIgc3VmZml4XG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAoby5jb25maWcgIT0gbnVsbCkgP1xuICAgICAgICAgIFwiZXh0bWFwOiVzICVzICVzXCI6XG4gICAgICAgICAgXCJleHRtYXA6JXMgJXNcIjtcbiAgICAgIH1cbiAgICB9LFxuICAgIHtcbiAgICAgIC8vYT1jcnlwdG86MSBBRVNfQ01fMTI4X0hNQUNfU0hBMV84MCBpbmxpbmU6UFMxdVFDVmVlQ0ZDYW5WbWNqa3BQeXdqTldoY1lEMG1YWHR4YVZCUnwyXjIwfDE6MzJcbiAgICAgIHB1c2g6ICdjcnlwdG8nLFxuICAgICAgcmVnOiAvXmNyeXB0bzooXFxkKikgKFtcXHdfXSopIChcXFMqKSg/OiAoXFxTKikpPy8sXG4gICAgICBuYW1lczogWydpZCcsICdzdWl0ZScsICdjb25maWcnLCAnc2Vzc2lvbkNvbmZpZyddLFxuICAgICAgZm9ybWF0OiBmdW5jdGlvbiAobykge1xuICAgICAgICByZXR1cm4gKG8uc2Vzc2lvbkNvbmZpZyAhPSBudWxsKSA/XG4gICAgICAgICAgXCJjcnlwdG86JWQgJXMgJXMgJXNcIjpcbiAgICAgICAgICBcImNyeXB0bzolZCAlcyAlc1wiO1xuICAgICAgfVxuICAgIH0sXG4gICAgeyAvL2E9c2V0dXA6YWN0cGFzc1xuICAgICAgbmFtZTogJ3NldHVwJyxcbiAgICAgIHJlZzogL15zZXR1cDooXFx3KikvLFxuICAgICAgZm9ybWF0OiBcInNldHVwOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPW1pZDoxXG4gICAgICBuYW1lOiAnbWlkJyxcbiAgICAgIHJlZzogL15taWQ6KFteXFxzXSopLyxcbiAgICAgIGZvcm1hdDogXCJtaWQ6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9bXNpZDowYzhiMDY0ZC1kODA3LTQzYjQtYjQzNC1mOTJhODg5ZDg1ODcgOTgxNzg2ODUtZDQwOS00NmUwLThlMTYtN2VmMGRiMGRiNjRhXG4gICAgICBuYW1lOiAnbXNpZCcsXG4gICAgICByZWc6IC9ebXNpZDooLiopLyxcbiAgICAgIGZvcm1hdDogXCJtc2lkOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPXB0aW1lOjIwXG4gICAgICBuYW1lOiAncHRpbWUnLFxuICAgICAgcmVnOiAvXnB0aW1lOihcXGQqKS8sXG4gICAgICBmb3JtYXQ6IFwicHRpbWU6JWRcIlxuICAgIH0sXG4gICAgeyAvL2E9bWF4cHRpbWU6NjBcbiAgICAgIG5hbWU6ICdtYXhwdGltZScsXG4gICAgICByZWc6IC9ebWF4cHRpbWU6KFxcZCopLyxcbiAgICAgIGZvcm1hdDogXCJtYXhwdGltZTolZFwiXG4gICAgfSxcbiAgICB7IC8vYT1zZW5kcmVjdlxuICAgICAgbmFtZTogJ2RpcmVjdGlvbicsXG4gICAgICByZWc6IC9eKHNlbmRyZWN2fHJlY3Zvbmx5fHNlbmRvbmx5fGluYWN0aXZlKS9cbiAgICB9LFxuICAgIHsgLy9hPWljZS1saXRlXG4gICAgICBuYW1lOiAnaWNlbGl0ZScsXG4gICAgICByZWc6IC9eKGljZS1saXRlKS9cbiAgICB9LFxuICAgIHsgLy9hPWljZS11ZnJhZzpGN2dJXG4gICAgICBuYW1lOiAnaWNlVWZyYWcnLFxuICAgICAgcmVnOiAvXmljZS11ZnJhZzooXFxTKikvLFxuICAgICAgZm9ybWF0OiBcImljZS11ZnJhZzolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1pY2UtcHdkOng5Y21sL1l6aWNoVjIrWGxoaU11OGdcbiAgICAgIG5hbWU6ICdpY2VQd2QnLFxuICAgICAgcmVnOiAvXmljZS1wd2Q6KFxcUyopLyxcbiAgICAgIGZvcm1hdDogXCJpY2UtcHdkOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPWZpbmdlcnByaW50OlNIQS0xIDAwOjExOjIyOjMzOjQ0OjU1OjY2Ojc3Ojg4Ojk5OkFBOkJCOkNDOkREOkVFOkZGOjAwOjExOjIyOjMzXG4gICAgICBuYW1lOiAnZmluZ2VycHJpbnQnLFxuICAgICAgcmVnOiAvXmZpbmdlcnByaW50OihcXFMqKSAoXFxTKikvLFxuICAgICAgbmFtZXM6IFsndHlwZScsICdoYXNoJ10sXG4gICAgICBmb3JtYXQ6IFwiZmluZ2VycHJpbnQ6JXMgJXNcIlxuICAgIH0sXG4gICAge1xuICAgICAgLy9hPWNhbmRpZGF0ZTowIDEgVURQIDIxMTM2NjczMjcgMjAzLjAuMTEzLjEgNTQ0MDAgdHlwIGhvc3RcbiAgICAgIC8vYT1jYW5kaWRhdGU6MTE2Mjg3NTA4MSAxIHVkcCAyMTEzOTM3MTUxIDE5Mi4xNjguMzQuNzUgNjAwMTcgdHlwIGhvc3QgZ2VuZXJhdGlvbiAwXG4gICAgICAvL2E9Y2FuZGlkYXRlOjMyODk5MTI5NTcgMiB1ZHAgMTg0NTUwMTY5NSAxOTMuODQuNzcuMTk0IDYwMDE3IHR5cCBzcmZseCByYWRkciAxOTIuMTY4LjM0Ljc1IHJwb3J0IDYwMDE3IGdlbmVyYXRpb24gMFxuICAgICAgLy9hPWNhbmRpZGF0ZToyMjk4MTU2MjAgMSB0Y3AgMTUxODI4MDQ0NyAxOTIuMTY4LjE1MC4xOSA2MDAxNyB0eXAgaG9zdCB0Y3B0eXBlIGFjdGl2ZSBnZW5lcmF0aW9uIDBcbiAgICAgIC8vYT1jYW5kaWRhdGU6MzI4OTkxMjk1NyAyIHRjcCAxODQ1NTAxNjk1IDE5My44NC43Ny4xOTQgNjAwMTcgdHlwIHNyZmx4IHJhZGRyIDE5Mi4xNjguMzQuNzUgcnBvcnQgNjAwMTcgdGNwdHlwZSBwYXNzaXZlIGdlbmVyYXRpb24gMFxuICAgICAgcHVzaDonY2FuZGlkYXRlcycsXG4gICAgICByZWc6IC9eY2FuZGlkYXRlOihcXFMqKSAoXFxkKikgKFxcUyopIChcXGQqKSAoXFxTKikgKFxcZCopIHR5cCAoXFxTKikoPzogcmFkZHIgKFxcUyopIHJwb3J0IChcXGQqKSk/KD86IHRjcHR5cGUgKFxcUyopKT8oPzogZ2VuZXJhdGlvbiAoXFxkKikpPy8sXG4gICAgICBuYW1lczogWydmb3VuZGF0aW9uJywgJ2NvbXBvbmVudCcsICd0cmFuc3BvcnQnLCAncHJpb3JpdHknLCAnaXAnLCAncG9ydCcsICd0eXBlJywgJ3JhZGRyJywgJ3Jwb3J0JywgJ3RjcHR5cGUnLCAnZ2VuZXJhdGlvbiddLFxuICAgICAgZm9ybWF0OiBmdW5jdGlvbiAobykge1xuICAgICAgICB2YXIgc3RyID0gXCJjYW5kaWRhdGU6JXMgJWQgJXMgJWQgJXMgJWQgdHlwICVzXCI7XG5cbiAgICAgICAgc3RyICs9IChvLnJhZGRyICE9IG51bGwpID8gXCIgcmFkZHIgJXMgcnBvcnQgJWRcIiA6IFwiJXYldlwiO1xuXG4gICAgICAgIC8vIE5COiBjYW5kaWRhdGUgaGFzIHRocmVlIG9wdGlvbmFsIGNodW5rcywgc28gJXZvaWQgbWlkZGxlcyBvbmUgaWYgaXQncyBtaXNzaW5nXG4gICAgICAgIHN0ciArPSAoby50Y3B0eXBlICE9IG51bGwpID8gXCIgdGNwdHlwZSAlc1wiIDogXCIldlwiO1xuXG4gICAgICAgIGlmIChvLmdlbmVyYXRpb24gIT0gbnVsbCkge1xuICAgICAgICAgIHN0ciArPSBcIiBnZW5lcmF0aW9uICVkXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICAgIH1cbiAgICB9LFxuICAgIHsgLy9hPWVuZC1vZi1jYW5kaWRhdGVzIChrZWVwIGFmdGVyIHRoZSBjYW5kaWRhdGVzIGxpbmUgZm9yIHJlYWRhYmlsaXR5KVxuICAgICAgbmFtZTogJ2VuZE9mQ2FuZGlkYXRlcycsXG4gICAgICByZWc6IC9eKGVuZC1vZi1jYW5kaWRhdGVzKS9cbiAgICB9LFxuICAgIHsgLy9hPXJlbW90ZS1jYW5kaWRhdGVzOjEgMjAzLjAuMTEzLjEgNTQ0MDAgMiAyMDMuMC4xMTMuMSA1NDQwMSAuLi5cbiAgICAgIG5hbWU6ICdyZW1vdGVDYW5kaWRhdGVzJyxcbiAgICAgIHJlZzogL15yZW1vdGUtY2FuZGlkYXRlczooLiopLyxcbiAgICAgIGZvcm1hdDogXCJyZW1vdGUtY2FuZGlkYXRlczolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1pY2Utb3B0aW9uczpnb29nbGUtaWNlXG4gICAgICBuYW1lOiAnaWNlT3B0aW9ucycsXG4gICAgICByZWc6IC9eaWNlLW9wdGlvbnM6KFxcUyopLyxcbiAgICAgIGZvcm1hdDogXCJpY2Utb3B0aW9uczolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1zc3JjOjI1NjYxMDc1NjkgY25hbWU6dDlZVThNMVV4VEY4WTFBMVxuICAgICAgcHVzaDogXCJzc3Jjc1wiLFxuICAgICAgcmVnOiAvXnNzcmM6KFxcZCopIChbXFx3X10qKTooLiopLyxcbiAgICAgIG5hbWVzOiBbJ2lkJywgJ2F0dHJpYnV0ZScsICd2YWx1ZSddLFxuICAgICAgZm9ybWF0OiBcInNzcmM6JWQgJXM6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9c3NyYy1ncm91cDpGRUMgMSAyXG4gICAgICBwdXNoOiBcInNzcmNHcm91cHNcIixcbiAgICAgIHJlZzogL15zc3JjLWdyb3VwOihcXHcqKSAoLiopLyxcbiAgICAgIG5hbWVzOiBbJ3NlbWFudGljcycsICdzc3JjcyddLFxuICAgICAgZm9ybWF0OiBcInNzcmMtZ3JvdXA6JXMgJXNcIlxuICAgIH0sXG4gICAgeyAvL2E9bXNpZC1zZW1hbnRpYzogV01TIEp2bGFtNVgzU1gxT1A2cG4yMHpXb2d2YUtKejVIamY5T25sVlxuICAgICAgbmFtZTogXCJtc2lkU2VtYW50aWNcIixcbiAgICAgIHJlZzogL15tc2lkLXNlbWFudGljOlxccz8oXFx3KikgKFxcUyopLyxcbiAgICAgIG5hbWVzOiBbJ3NlbWFudGljJywgJ3Rva2VuJ10sXG4gICAgICBmb3JtYXQ6IFwibXNpZC1zZW1hbnRpYzogJXMgJXNcIiAvLyBzcGFjZSBhZnRlciBcIjpcIiBpcyBub3QgYWNjaWRlbnRhbFxuICAgIH0sXG4gICAgeyAvL2E9Z3JvdXA6QlVORExFIGF1ZGlvIHZpZGVvXG4gICAgICBwdXNoOiAnZ3JvdXBzJyxcbiAgICAgIHJlZzogL15ncm91cDooXFx3KikgKC4qKS8sXG4gICAgICBuYW1lczogWyd0eXBlJywgJ21pZHMnXSxcbiAgICAgIGZvcm1hdDogXCJncm91cDolcyAlc1wiXG4gICAgfSxcbiAgICB7IC8vYT1ydGNwLW11eFxuICAgICAgbmFtZTogJ3J0Y3BNdXgnLFxuICAgICAgcmVnOiAvXihydGNwLW11eCkvXG4gICAgfSxcbiAgICB7IC8vYT1ydGNwLXJzaXplXG4gICAgICBuYW1lOiAncnRjcFJzaXplJyxcbiAgICAgIHJlZzogL14ocnRjcC1yc2l6ZSkvXG4gICAgfSxcbiAgICB7IC8vIGFueSBhPSB0aGF0IHdlIGRvbid0IHVuZGVyc3RhbmQgaXMga2VwdHMgdmVyYmF0aW0gb24gbWVkaWEuaW52YWxpZFxuICAgICAgcHVzaDogJ2ludmFsaWQnLFxuICAgICAgbmFtZXM6IFtcInZhbHVlXCJdXG4gICAgfVxuICBdXG59O1xuXG4vLyBzZXQgc2Vuc2libGUgZGVmYXVsdHMgdG8gYXZvaWQgcG9sbHV0aW5nIHRoZSBncmFtbWFyIHdpdGggYm9yaW5nIGRldGFpbHNcbk9iamVjdC5rZXlzKGdyYW1tYXIpLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICB2YXIgb2JqcyA9IGdyYW1tYXJba2V5XTtcbiAgb2Jqcy5mb3JFYWNoKGZ1bmN0aW9uIChvYmopIHtcbiAgICBpZiAoIW9iai5yZWcpIHtcbiAgICAgIG9iai5yZWcgPSAvKC4qKS87XG4gICAgfVxuICAgIGlmICghb2JqLmZvcm1hdCkge1xuICAgICAgb2JqLmZvcm1hdCA9IFwiJXNcIjtcbiAgICB9XG4gIH0pO1xufSk7XG4iLCJ2YXIgcGFyc2VyID0gcmVxdWlyZSgnLi9wYXJzZXInKTtcbnZhciB3cml0ZXIgPSByZXF1aXJlKCcuL3dyaXRlcicpO1xuXG5leHBvcnRzLndyaXRlID0gd3JpdGVyO1xuZXhwb3J0cy5wYXJzZSA9IHBhcnNlci5wYXJzZTtcbmV4cG9ydHMucGFyc2VGbXRwQ29uZmlnID0gcGFyc2VyLnBhcnNlRm10cENvbmZpZztcbmV4cG9ydHMucGFyc2VQYXlsb2FkcyA9IHBhcnNlci5wYXJzZVBheWxvYWRzO1xuZXhwb3J0cy5wYXJzZVJlbW90ZUNhbmRpZGF0ZXMgPSBwYXJzZXIucGFyc2VSZW1vdGVDYW5kaWRhdGVzO1xuIiwidmFyIHRvSW50SWZJbnQgPSBmdW5jdGlvbiAodikge1xuICByZXR1cm4gU3RyaW5nKE51bWJlcih2KSkgPT09IHYgPyBOdW1iZXIodikgOiB2O1xufTtcblxudmFyIGF0dGFjaFByb3BlcnRpZXMgPSBmdW5jdGlvbiAobWF0Y2gsIGxvY2F0aW9uLCBuYW1lcywgcmF3TmFtZSkge1xuICBpZiAocmF3TmFtZSAmJiAhbmFtZXMpIHtcbiAgICBsb2NhdGlvbltyYXdOYW1lXSA9IHRvSW50SWZJbnQobWF0Y2hbMV0pO1xuICB9XG4gIGVsc2Uge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbmFtZXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgIGlmIChtYXRjaFtpKzFdICE9IG51bGwpIHtcbiAgICAgICAgbG9jYXRpb25bbmFtZXNbaV1dID0gdG9JbnRJZkludChtYXRjaFtpKzFdKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn07XG5cbnZhciBwYXJzZVJlZyA9IGZ1bmN0aW9uIChvYmosIGxvY2F0aW9uLCBjb250ZW50KSB7XG4gIHZhciBuZWVkc0JsYW5rID0gb2JqLm5hbWUgJiYgb2JqLm5hbWVzO1xuICBpZiAob2JqLnB1c2ggJiYgIWxvY2F0aW9uW29iai5wdXNoXSkge1xuICAgIGxvY2F0aW9uW29iai5wdXNoXSA9IFtdO1xuICB9XG4gIGVsc2UgaWYgKG5lZWRzQmxhbmsgJiYgIWxvY2F0aW9uW29iai5uYW1lXSkge1xuICAgIGxvY2F0aW9uW29iai5uYW1lXSA9IHt9O1xuICB9XG4gIHZhciBrZXlMb2NhdGlvbiA9IG9iai5wdXNoID9cbiAgICB7fSA6ICAvLyBibGFuayBvYmplY3QgdGhhdCB3aWxsIGJlIHB1c2hlZFxuICAgIG5lZWRzQmxhbmsgPyBsb2NhdGlvbltvYmoubmFtZV0gOiBsb2NhdGlvbjsgLy8gb3RoZXJ3aXNlLCBuYW1lZCBsb2NhdGlvbiBvciByb290XG5cbiAgYXR0YWNoUHJvcGVydGllcyhjb250ZW50Lm1hdGNoKG9iai5yZWcpLCBrZXlMb2NhdGlvbiwgb2JqLm5hbWVzLCBvYmoubmFtZSk7XG5cbiAgaWYgKG9iai5wdXNoKSB7XG4gICAgbG9jYXRpb25bb2JqLnB1c2hdLnB1c2goa2V5TG9jYXRpb24pO1xuICB9XG59O1xuXG52YXIgZ3JhbW1hciA9IHJlcXVpcmUoJy4vZ3JhbW1hcicpO1xudmFyIHZhbGlkTGluZSA9IFJlZ0V4cC5wcm90b3R5cGUudGVzdC5iaW5kKC9eKFthLXpdKT0oLiopLyk7XG5cbmV4cG9ydHMucGFyc2UgPSBmdW5jdGlvbiAoc2RwKSB7XG4gIHZhciBzZXNzaW9uID0ge31cbiAgICAsIG1lZGlhID0gW11cbiAgICAsIGxvY2F0aW9uID0gc2Vzc2lvbjsgLy8gcG9pbnRzIGF0IHdoZXJlIHByb3BlcnRpZXMgZ28gdW5kZXIgKG9uZSBvZiB0aGUgYWJvdmUpXG5cbiAgLy8gcGFyc2UgbGluZXMgd2UgdW5kZXJzdGFuZFxuICBzZHAuc3BsaXQoLyhcXHJcXG58XFxyfFxcbikvKS5maWx0ZXIodmFsaWRMaW5lKS5mb3JFYWNoKGZ1bmN0aW9uIChsKSB7XG4gICAgdmFyIHR5cGUgPSBsWzBdO1xuICAgIHZhciBjb250ZW50ID0gbC5zbGljZSgyKTtcbiAgICBpZiAodHlwZSA9PT0gJ20nKSB7XG4gICAgICBtZWRpYS5wdXNoKHtydHA6IFtdLCBmbXRwOiBbXX0pO1xuICAgICAgbG9jYXRpb24gPSBtZWRpYVttZWRpYS5sZW5ndGgtMV07IC8vIHBvaW50IGF0IGxhdGVzdCBtZWRpYSBsaW5lXG4gICAgfVxuXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCAoZ3JhbW1hclt0eXBlXSB8fCBbXSkubGVuZ3RoOyBqICs9IDEpIHtcbiAgICAgIHZhciBvYmogPSBncmFtbWFyW3R5cGVdW2pdO1xuICAgICAgaWYgKG9iai5yZWcudGVzdChjb250ZW50KSkge1xuICAgICAgICByZXR1cm4gcGFyc2VSZWcob2JqLCBsb2NhdGlvbiwgY29udGVudCk7XG4gICAgICB9XG4gICAgfVxuICB9KTtcblxuICBzZXNzaW9uLm1lZGlhID0gbWVkaWE7IC8vIGxpbmsgaXQgdXBcbiAgcmV0dXJuIHNlc3Npb247XG59O1xuXG52YXIgZm10cFJlZHVjZXIgPSBmdW5jdGlvbiAoYWNjLCBleHByKSB7XG4gIHZhciBzID0gZXhwci5zcGxpdCgnPScpO1xuICBpZiAocy5sZW5ndGggPT09IDIpIHtcbiAgICBhY2Nbc1swXV0gPSB0b0ludElmSW50KHNbMV0pO1xuICB9XG4gIHJldHVybiBhY2M7XG59O1xuXG5leHBvcnRzLnBhcnNlRm10cENvbmZpZyA9IGZ1bmN0aW9uIChzdHIpIHtcbiAgcmV0dXJuIHN0ci5zcGxpdCgvXFw7XFxzPy8pLnJlZHVjZShmbXRwUmVkdWNlciwge30pO1xufTtcblxuZXhwb3J0cy5wYXJzZVBheWxvYWRzID0gZnVuY3Rpb24gKHN0cikge1xuICByZXR1cm4gc3RyLnNwbGl0KCcgJykubWFwKE51bWJlcik7XG59O1xuXG5leHBvcnRzLnBhcnNlUmVtb3RlQ2FuZGlkYXRlcyA9IGZ1bmN0aW9uIChzdHIpIHtcbiAgdmFyIGNhbmRpZGF0ZXMgPSBbXTtcbiAgdmFyIHBhcnRzID0gc3RyLnNwbGl0KCcgJykubWFwKHRvSW50SWZJbnQpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHBhcnRzLmxlbmd0aDsgaSArPSAzKSB7XG4gICAgY2FuZGlkYXRlcy5wdXNoKHtcbiAgICAgIGNvbXBvbmVudDogcGFydHNbaV0sXG4gICAgICBpcDogcGFydHNbaSArIDFdLFxuICAgICAgcG9ydDogcGFydHNbaSArIDJdXG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIGNhbmRpZGF0ZXM7XG59O1xuIiwidmFyIGdyYW1tYXIgPSByZXF1aXJlKCcuL2dyYW1tYXInKTtcblxuLy8gY3VzdG9taXplZCB1dGlsLmZvcm1hdCAtIGRpc2NhcmRzIGV4Y2VzcyBhcmd1bWVudHMgYW5kIGNhbiB2b2lkIG1pZGRsZSBvbmVzXG52YXIgZm9ybWF0UmVnRXhwID0gLyVbc2R2JV0vZztcbnZhciBmb3JtYXQgPSBmdW5jdGlvbiAoZm9ybWF0U3RyKSB7XG4gIHZhciBpID0gMTtcbiAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gIHZhciBsZW4gPSBhcmdzLmxlbmd0aDtcbiAgcmV0dXJuIGZvcm1hdFN0ci5yZXBsYWNlKGZvcm1hdFJlZ0V4cCwgZnVuY3Rpb24gKHgpIHtcbiAgICBpZiAoaSA+PSBsZW4pIHtcbiAgICAgIHJldHVybiB4OyAvLyBtaXNzaW5nIGFyZ3VtZW50XG4gICAgfVxuICAgIHZhciBhcmcgPSBhcmdzW2ldO1xuICAgIGkgKz0gMTtcbiAgICBzd2l0Y2ggKHgpIHtcbiAgICAgIGNhc2UgJyUlJzpcbiAgICAgICAgcmV0dXJuICclJztcbiAgICAgIGNhc2UgJyVzJzpcbiAgICAgICAgcmV0dXJuIFN0cmluZyhhcmcpO1xuICAgICAgY2FzZSAnJWQnOlxuICAgICAgICByZXR1cm4gTnVtYmVyKGFyZyk7XG4gICAgICBjYXNlICcldic6XG4gICAgICAgIHJldHVybiAnJztcbiAgICB9XG4gIH0pO1xuICAvLyBOQjogd2UgZGlzY2FyZCBleGNlc3MgYXJndW1lbnRzIC0gdGhleSBhcmUgdHlwaWNhbGx5IHVuZGVmaW5lZCBmcm9tIG1ha2VMaW5lXG59O1xuXG52YXIgbWFrZUxpbmUgPSBmdW5jdGlvbiAodHlwZSwgb2JqLCBsb2NhdGlvbikge1xuICB2YXIgc3RyID0gb2JqLmZvcm1hdCBpbnN0YW5jZW9mIEZ1bmN0aW9uID9cbiAgICAob2JqLmZvcm1hdChvYmoucHVzaCA/IGxvY2F0aW9uIDogbG9jYXRpb25bb2JqLm5hbWVdKSkgOlxuICAgIG9iai5mb3JtYXQ7XG5cbiAgdmFyIGFyZ3MgPSBbdHlwZSArICc9JyArIHN0cl07XG4gIGlmIChvYmoubmFtZXMpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iai5uYW1lcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgdmFyIG4gPSBvYmoubmFtZXNbaV07XG4gICAgICBpZiAob2JqLm5hbWUpIHtcbiAgICAgICAgYXJncy5wdXNoKGxvY2F0aW9uW29iai5uYW1lXVtuXSk7XG4gICAgICB9XG4gICAgICBlbHNlIHsgLy8gZm9yIG1MaW5lIGFuZCBwdXNoIGF0dHJpYnV0ZXNcbiAgICAgICAgYXJncy5wdXNoKGxvY2F0aW9uW29iai5uYW1lc1tpXV0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBlbHNlIHtcbiAgICBhcmdzLnB1c2gobG9jYXRpb25bb2JqLm5hbWVdKTtcbiAgfVxuICByZXR1cm4gZm9ybWF0LmFwcGx5KG51bGwsIGFyZ3MpO1xufTtcblxuLy8gUkZDIHNwZWNpZmllZCBvcmRlclxuLy8gVE9ETzogZXh0ZW5kIHRoaXMgd2l0aCBhbGwgdGhlIHJlc3RcbnZhciBkZWZhdWx0T3V0ZXJPcmRlciA9IFtcbiAgJ3YnLCAnbycsICdzJywgJ2knLFxuICAndScsICdlJywgJ3AnLCAnYycsXG4gICdiJywgJ3QnLCAncicsICd6JywgJ2EnXG5dO1xudmFyIGRlZmF1bHRJbm5lck9yZGVyID0gWydpJywgJ2MnLCAnYicsICdhJ107XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoc2Vzc2lvbiwgb3B0cykge1xuICBvcHRzID0gb3B0cyB8fCB7fTtcbiAgLy8gZW5zdXJlIGNlcnRhaW4gcHJvcGVydGllcyBleGlzdFxuICBpZiAoc2Vzc2lvbi52ZXJzaW9uID09IG51bGwpIHtcbiAgICBzZXNzaW9uLnZlcnNpb24gPSAwOyAvLyBcInY9MFwiIG11c3QgYmUgdGhlcmUgKG9ubHkgZGVmaW5lZCB2ZXJzaW9uIGF0bSlcbiAgfVxuICBpZiAoc2Vzc2lvbi5uYW1lID09IG51bGwpIHtcbiAgICBzZXNzaW9uLm5hbWUgPSBcIiBcIjsgLy8gXCJzPSBcIiBtdXN0IGJlIHRoZXJlIGlmIG5vIG1lYW5pbmdmdWwgbmFtZSBzZXRcbiAgfVxuICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24gKG1MaW5lKSB7XG4gICAgaWYgKG1MaW5lLnBheWxvYWRzID09IG51bGwpIHtcbiAgICAgIG1MaW5lLnBheWxvYWRzID0gXCJcIjtcbiAgICB9XG4gIH0pO1xuXG4gIHZhciBvdXRlck9yZGVyID0gb3B0cy5vdXRlck9yZGVyIHx8IGRlZmF1bHRPdXRlck9yZGVyO1xuICB2YXIgaW5uZXJPcmRlciA9IG9wdHMuaW5uZXJPcmRlciB8fCBkZWZhdWx0SW5uZXJPcmRlcjtcbiAgdmFyIHNkcCA9IFtdO1xuXG4gIC8vIGxvb3AgdGhyb3VnaCBvdXRlck9yZGVyIGZvciBtYXRjaGluZyBwcm9wZXJ0aWVzIG9uIHNlc3Npb25cbiAgb3V0ZXJPcmRlci5mb3JFYWNoKGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgZ3JhbW1hclt0eXBlXS5mb3JFYWNoKGZ1bmN0aW9uIChvYmopIHtcbiAgICAgIGlmIChvYmoubmFtZSBpbiBzZXNzaW9uICYmIHNlc3Npb25bb2JqLm5hbWVdICE9IG51bGwpIHtcbiAgICAgICAgc2RwLnB1c2gobWFrZUxpbmUodHlwZSwgb2JqLCBzZXNzaW9uKSk7XG4gICAgICB9XG4gICAgICBlbHNlIGlmIChvYmoucHVzaCBpbiBzZXNzaW9uICYmIHNlc3Npb25bb2JqLnB1c2hdICE9IG51bGwpIHtcbiAgICAgICAgc2Vzc2lvbltvYmoucHVzaF0uZm9yRWFjaChmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICBzZHAucHVzaChtYWtlTGluZSh0eXBlLCBvYmosIGVsKSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICAvLyB0aGVuIGZvciBlYWNoIG1lZGlhIGxpbmUsIGZvbGxvdyB0aGUgaW5uZXJPcmRlclxuICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24gKG1MaW5lKSB7XG4gICAgc2RwLnB1c2gobWFrZUxpbmUoJ20nLCBncmFtbWFyLm1bMF0sIG1MaW5lKSk7XG5cbiAgICBpbm5lck9yZGVyLmZvckVhY2goZnVuY3Rpb24gKHR5cGUpIHtcbiAgICAgIGdyYW1tYXJbdHlwZV0uZm9yRWFjaChmdW5jdGlvbiAob2JqKSB7XG4gICAgICAgIGlmIChvYmoubmFtZSBpbiBtTGluZSAmJiBtTGluZVtvYmoubmFtZV0gIT0gbnVsbCkge1xuICAgICAgICAgIHNkcC5wdXNoKG1ha2VMaW5lKHR5cGUsIG9iaiwgbUxpbmUpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChvYmoucHVzaCBpbiBtTGluZSAmJiBtTGluZVtvYmoucHVzaF0gIT0gbnVsbCkge1xuICAgICAgICAgIG1MaW5lW29iai5wdXNoXS5mb3JFYWNoKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgICAgc2RwLnB1c2gobWFrZUxpbmUodHlwZSwgb2JqLCBlbCkpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgcmV0dXJuIHNkcC5qb2luKCdcXHJcXG4nKSArICdcXHJcXG4nO1xufTtcbiIsIi8qIENvcHlyaWdodCBAIDIwMTUgQXRsYXNzaWFuIFB0eSBMdGRcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBhcnJheUVxdWFscyhhcnJheSkge1xuICAgIC8vIGlmIHRoZSBvdGhlciBhcnJheSBpcyBhIGZhbHN5IHZhbHVlLCByZXR1cm5cbiAgICBpZiAoIWFycmF5KVxuICAgICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICAvLyBjb21wYXJlIGxlbmd0aHMgLSBjYW4gc2F2ZSBhIGxvdCBvZiB0aW1lXG4gICAgaWYgKHRoaXMubGVuZ3RoICE9IGFycmF5Lmxlbmd0aClcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIGwgPSB0aGlzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICAvLyBDaGVjayBpZiB3ZSBoYXZlIG5lc3RlZCBhcnJheXNcbiAgICAgICAgaWYgKHRoaXNbaV0gaW5zdGFuY2VvZiBBcnJheSAmJiBhcnJheVtpXSBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICAgICAgICAvLyByZWN1cnNlIGludG8gdGhlIG5lc3RlZCBhcnJheXNcbiAgICAgICAgICAgIGlmICghYXJyYXlFcXVhbHMuYXBwbHkodGhpc1tpXSwgW2FycmF5W2ldXSkpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXNbaV0gIT0gYXJyYXlbaV0pIHtcbiAgICAgICAgICAgIC8vIFdhcm5pbmcgLSB0d28gZGlmZmVyZW50IG9iamVjdCBpbnN0YW5jZXMgd2lsbCBuZXZlciBiZSBlcXVhbDpcbiAgICAgICAgICAgIC8vIHt4OjIwfSAhPSB7eDoyMH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn07XG5cbiIsIi8qIENvcHlyaWdodCBAIDIwMTUgQXRsYXNzaWFuIFB0eSBMdGRcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuZXhwb3J0cy5JbnRlcm9wID0gcmVxdWlyZSgnLi9pbnRlcm9wJyk7XG4iLCIvKiBDb3B5cmlnaHQgQCAyMDE1IEF0bGFzc2lhbiBQdHkgTHRkXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qIGdsb2JhbCBSVENTZXNzaW9uRGVzY3JpcHRpb24gKi9cbi8qIGdsb2JhbCBSVENJY2VDYW5kaWRhdGUgKi9cbi8qIGpzaGludCAtVzA5NyAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciB0cmFuc2Zvcm0gPSByZXF1aXJlKCcuL3RyYW5zZm9ybScpO1xudmFyIGFycmF5RXF1YWxzID0gcmVxdWlyZSgnLi9hcnJheS1lcXVhbHMnKTtcblxuZnVuY3Rpb24gSW50ZXJvcCgpIHtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWFwIGhvbGRzIHRoZSBtb3N0IHJlY2VudCBVbmlmaWVkIFBsYW4gb2ZmZXIvYW5zd2VyIFNEUCB0aGF0IHdhc1xuICAgICAqIGNvbnZlcnRlZCB0byBQbGFuIEIsIHdpdGggdGhlIFNEUCB0eXBlICgnb2ZmZXInIG9yICdhbnN3ZXInKSBhcyBrZXlzIGFuZFxuICAgICAqIHRoZSBTRFAgc3RyaW5nIGFzIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEB0eXBlIHt7fX1cbiAgICAgKi9cbiAgICB0aGlzLmNhY2hlID0ge1xuICAgICAgICBtbEIyVU1hcCA6IHt9LFxuICAgICAgICBtbFUyQk1hcCA6IHt9XG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBJbnRlcm9wO1xuXG4vKipcbiAqIENoYW5nZXMgdGhlIGNhbmRpZGF0ZSBhcmdzIHRvIG1hdGNoIHdpdGggdGhlIHJlbGF0ZWQgVW5pZmllZCBQbGFuXG4gKi9cbkludGVyb3AucHJvdG90eXBlLmNhbmRpZGF0ZVRvVW5pZmllZFBsYW4gPSBmdW5jdGlvbihjYW5kaWRhdGUpIHtcbiAgICB2YXIgY2FuZCA9IG5ldyBSVENJY2VDYW5kaWRhdGUoY2FuZGlkYXRlKTtcblxuICAgIGNhbmQuc2RwTUxpbmVJbmRleCA9IHRoaXMuY2FjaGUubWxCMlVNYXBbY2FuZC5zZHBNTGluZUluZGV4XTtcbiAgICAvKiBUT0RPOiBjaGFuZ2Ugc2RwTWlkIHRvIChhdWRpb3x2aWRlbyktU1NSQyAqL1xuXG4gICAgcmV0dXJuIGNhbmQ7XG59O1xuXG4vKipcbiAqIENoYW5nZXMgdGhlIGNhbmRpZGF0ZSBhcmdzIHRvIG1hdGNoIHdpdGggdGhlIHJlbGF0ZWQgUGxhbiBCXG4gKi9cbkludGVyb3AucHJvdG90eXBlLmNhbmRpZGF0ZVRvUGxhbkIgPSBmdW5jdGlvbihjYW5kaWRhdGUpIHtcbiAgICB2YXIgY2FuZCA9IG5ldyBSVENJY2VDYW5kaWRhdGUoY2FuZGlkYXRlKTtcblxuICAgIGlmIChjYW5kLnNkcE1pZC5pbmRleE9mKCdhdWRpbycpID09PSAwKSB7XG4gICAgICBjYW5kLnNkcE1pZCA9ICdhdWRpbyc7XG4gICAgfSBlbHNlIGlmIChjYW5kLnNkcE1pZC5pbmRleE9mKCd2aWRlbycpID09PSAwKSB7XG4gICAgICBjYW5kLnNkcE1pZCA9ICd2aWRlbyc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY2FuZGlkYXRlIHdpdGggJyArIGNhbmQuc2RwTWlkICsgJyBub3QgYWxsb3dlZCcpO1xuICAgIH1cblxuICAgIGNhbmQuc2RwTUxpbmVJbmRleCA9IHRoaXMuY2FjaGUubWxVMkJNYXBbY2FuZC5zZHBNTGluZUluZGV4XTtcblxuICAgIHJldHVybiBjYW5kO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgZmlyc3QgbS1saW5lIHdpdGggdGhlIGdpdmVuIG1lZGlhIHR5cGUgYW5kIHdpdGggYVxuICogZGlyZWN0aW9uIHdoaWNoIGFsbG93cyBzZW5kaW5nLCBpbiB0aGUgbGFzdCBVbmlmaWVkIFBsYW4gZGVzY3JpcHRpb24gd2l0aFxuICogdHlwZSBcImFuc3dlclwiIGNvbnZlcnRlZCB0byBQbGFuIEIuIFJldHVybnMge251bGx9IGlmIHRoZXJlIGlzIG5vIHNhdmVkXG4gKiBhbnN3ZXIsIG9yIGlmIG5vbmUgb2YgaXRzIG0tbGluZXMgd2l0aCB0aGUgZ2l2ZW4gdHlwZSBhbGxvdyBzZW5kaW5nLlxuICogQHBhcmFtIHR5cGUgdGhlIG1lZGlhIHR5cGUgKFwiYXVkaW9cIiBvciBcInZpZGVvXCIpLlxuICogQHJldHVybnMgeyp9XG4gKi9cbkludGVyb3AucHJvdG90eXBlLmdldEZpcnN0U2VuZGluZ0luZGV4RnJvbUFuc3dlciA9IGZ1bmN0aW9uKHR5cGUpIHtcbiAgICBpZiAoIXRoaXMuY2FjaGUuYW5zd2VyKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHZhciBzZXNzaW9uID0gdHJhbnNmb3JtLnBhcnNlKHRoaXMuY2FjaGUuYW5zd2VyKTtcbiAgICBpZiAoc2Vzc2lvbiAmJiBzZXNzaW9uLm1lZGlhICYmIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkpe1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNlc3Npb24ubWVkaWEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChzZXNzaW9uLm1lZGlhW2ldLnR5cGUgPT0gdHlwZSAmJlxuICAgICAgICAgICAgICAgICghc2Vzc2lvbi5tZWRpYVtpXS5kaXJlY3Rpb24gLyogZGVmYXVsdCB0byBzZW5kcmVjdiAqLyB8fFxuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLm1lZGlhW2ldLmRpcmVjdGlvbiA9PT0gJ3NlbmRyZWN2JyB8fFxuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLm1lZGlhW2ldLmRpcmVjdGlvbiA9PT0gJ3NlbmRvbmx5Jykpe1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG59O1xuXG4vKipcbiAqIFRoaXMgbWV0aG9kIHRyYW5zZm9ybXMgYSBVbmlmaWVkIFBsYW4gU0RQIHRvIGFuIGVxdWl2YWxlbnQgUGxhbiBCIFNEUC4gQVxuICogUGVlckNvbm5lY3Rpb24gd3JhcHBlciB0cmFuc2Zvcm1zIHRoZSBTRFAgdG8gUGxhbiBCIGJlZm9yZSBwYXNzaW5nIGl0IHRvIHRoZVxuICogYXBwbGljYXRpb24uXG4gKlxuICogQHBhcmFtIGRlc2NcbiAqIEByZXR1cm5zIHsqfVxuICovXG5JbnRlcm9wLnByb3RvdHlwZS50b1BsYW5CID0gZnVuY3Rpb24oZGVzYykge1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAvLyNyZWdpb24gUHJlbGltaW5hcnkgaW5wdXQgdmFsaWRhdGlvbi5cblxuICAgIGlmICh0eXBlb2YgZGVzYyAhPT0gJ29iamVjdCcgfHwgZGVzYyA9PT0gbnVsbCB8fFxuICAgICAgICB0eXBlb2YgZGVzYy5zZHAgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignQW4gZW1wdHkgZGVzY3JpcHRpb24gd2FzIHBhc3NlZCBhcyBhbiBhcmd1bWVudC4nKTtcbiAgICAgICAgcmV0dXJuIGRlc2M7XG4gICAgfVxuXG4gICAgLy8gT2JqZWN0aWZ5IHRoZSBTRFAgZm9yIGVhc2llciBtYW5pcHVsYXRpb24uXG4gICAgdmFyIHNlc3Npb24gPSB0cmFuc2Zvcm0ucGFyc2UoZGVzYy5zZHApO1xuXG4gICAgLy8gSWYgdGhlIFNEUCBjb250YWlucyBubyBtZWRpYSwgdGhlcmUncyBub3RoaW5nIHRvIHRyYW5zZm9ybS5cbiAgICBpZiAodHlwZW9mIHNlc3Npb24ubWVkaWEgPT09ICd1bmRlZmluZWQnIHx8XG4gICAgICAgICFBcnJheS5pc0FycmF5KHNlc3Npb24ubWVkaWEpIHx8IHNlc3Npb24ubWVkaWEubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignVGhlIGRlc2NyaXB0aW9uIGhhcyBubyBtZWRpYS4nKTtcbiAgICAgICAgcmV0dXJuIGRlc2M7XG4gICAgfVxuXG4gICAgLy8gVHJ5IHNvbWUgaGV1cmlzdGljcyB0byBcIm1ha2Ugc3VyZVwiIHRoaXMgaXMgYSBVbmlmaWVkIFBsYW4gU0RQLiBQbGFuIEJcbiAgICAvLyBTRFAgaGFzIGEgdmlkZW8sIGFuIGF1ZGlvIGFuZCBhIGRhdGEgXCJjaGFubmVsXCIgYXQgbW9zdC5cbiAgICBpZiAoc2Vzc2lvbi5tZWRpYS5sZW5ndGggPD0gMyAmJiBzZXNzaW9uLm1lZGlhLmV2ZXJ5KGZ1bmN0aW9uKG0pIHtcbiAgICAgICAgICAgIHJldHVybiBbJ3ZpZGVvJywgJ2F1ZGlvJywgJ2RhdGEnXS5pbmRleE9mKG0ubWlkKSAhPT0gLTE7XG4gICAgICAgIH0pKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignVGhpcyBkZXNjcmlwdGlvbiBkb2VzIG5vdCBsb29rIGxpa2UgVW5pZmllZCBQbGFuLicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICAvLyNlbmRyZWdpb25cblxuICAgIC8vIEhBQ0sgaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTExMzQ0M1xuICAgIHZhciBzZHAgPSBkZXNjLnNkcDtcbiAgICB2YXIgcmV3cml0ZSA9IGZhbHNlO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2Vzc2lvbi5tZWRpYS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdUxpbmUgPSBzZXNzaW9uLm1lZGlhW2ldO1xuICAgICAgICB1TGluZS5ydHAuZm9yRWFjaChmdW5jdGlvbihydHApIHtcbiAgICAgICAgICAgIGlmIChydHAuY29kZWMgPT09ICdOVUxMJylcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICByZXdyaXRlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB2YXIgb2ZmZXIgPSB0cmFuc2Zvcm0ucGFyc2Uoc2VsZi5jYWNoZS5vZmZlcik7XG4gICAgICAgICAgICAgICAgcnRwLmNvZGVjID0gb2ZmZXIubWVkaWFbaV0ucnRwWzBdLmNvZGVjO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgaWYgKHJld3JpdGUpIHtcbiAgICAgICAgc2RwID0gdHJhbnNmb3JtLndyaXRlKHNlc3Npb24pO1xuICAgIH1cblxuICAgIC8vIFVuaWZpZWQgUGxhbiBTRFAgaXMgb3VyIFwicHJlY2lvdXNcIi4gQ2FjaGUgaXQgZm9yIGxhdGVyIHVzZSBpbiB0aGUgUGxhbiBCXG4gICAgLy8gLT4gVW5pZmllZCBQbGFuIHRyYW5zZm9ybWF0aW9uLlxuICAgIHRoaXMuY2FjaGVbZGVzYy50eXBlXSA9IHNkcDtcblxuICAgIC8vI3JlZ2lvbiBDb252ZXJ0IGZyb20gVW5pZmllZCBQbGFuIHRvIFBsYW4gQi5cblxuICAgIC8vIFdlIHJlYnVpbGQgdGhlIHNlc3Npb24ubWVkaWEgYXJyYXkuXG4gICAgdmFyIG1lZGlhID0gc2Vzc2lvbi5tZWRpYTtcbiAgICBzZXNzaW9uLm1lZGlhID0gW107XG5cbiAgICAvLyBBc3NvY2lhdGl2ZSBhcnJheSB0aGF0IG1hcHMgY2hhbm5lbCB0eXBlcyB0byBjaGFubmVsIG9iamVjdHMgZm9yIGZhc3RcbiAgICAvLyBhY2Nlc3MgdG8gY2hhbm5lbCBvYmplY3RzIGJ5IHRoZWlyIHR5cGUsIGUuZy4gdHlwZTJibFsnYXVkaW8nXS0+Y2hhbm5lbFxuICAgIC8vIG9iai5cbiAgICB2YXIgdHlwZTJibCA9IHt9O1xuXG4gICAgLy8gVXNlZCB0byBidWlsZCB0aGUgZ3JvdXA6QlVORExFIHZhbHVlIGFmdGVyIHRoZSBjaGFubmVscyBjb25zdHJ1Y3Rpb25cbiAgICAvLyBsb29wLlxuICAgIHZhciB0eXBlcyA9IFtdO1xuXG4gICAgbWVkaWEuZm9yRWFjaChmdW5jdGlvbih1TGluZSkge1xuICAgICAgICAvLyBydGNwLW11eCBpcyByZXF1aXJlZCBpbiB0aGUgUGxhbiBCIFNEUC5cbiAgICAgICAgaWYgKCh0eXBlb2YgdUxpbmUucnRjcE11eCAhPT0gJ3N0cmluZycgfHxcbiAgICAgICAgICAgIHVMaW5lLnJ0Y3BNdXggIT09ICdydGNwLW11eCcpICYmXG4gICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gIT09ICdpbmFjdGl2ZScpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGNvbnZlcnQgdG8gUGxhbiBCIGJlY2F1c2UgbS1saW5lcyAnICtcbiAgICAgICAgICAgICAgICAnd2l0aG91dCB0aGUgcnRjcC1tdXggYXR0cmlidXRlIHdlcmUgZm91bmQuJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB3ZSBkb24ndCBoYXZlIGEgY2hhbm5lbCBmb3IgdGhpcyB1TGluZS50eXBlIE9SIHRoZSBzZWxlY3RlZCBpc1xuICAgICAgICAvLyBpbmFjdGl2ZSwgdGhlbiBzZWxlY3QgdGhpcyB1TGluZSBhcyB0aGUgY2hhbm5lbCBiYXNpcy5cbiAgICAgICAgaWYgKHR5cGVvZiB0eXBlMmJsW3VMaW5lLnR5cGVdID09PSAndW5kZWZpbmVkJyB8fFxuICAgICAgICAgICAgdHlwZTJibFt1TGluZS50eXBlXS5kaXJlY3Rpb24gPT09ICdpbmFjdGl2ZScpIHtcbiAgICAgICAgICAgIHR5cGUyYmxbdUxpbmUudHlwZV0gPSB1TGluZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh1TGluZS5wcm90b2NvbCAhPSB0eXBlMmJsW3VMaW5lLnR5cGVdLnByb3RvY29sKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgY29udmVydCB0byBQbGFuIEIgYmVjYXVzZSBtLWxpbmVzICcgK1xuICAgICAgICAgICAgICAnaGF2ZSBkaWZmZXJlbnQgcHJvdG9jb2xzIGFuZCB0aGlzIGxpYnJhcnkgZG9lcyBub3QgaGF2ZSAnICtcbiAgICAgICAgICAgICAgJ3N1cHBvcnQgZm9yIHRoYXQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh1TGluZS5wYXlsb2FkcyAhPSB0eXBlMmJsW3VMaW5lLnR5cGVdLnBheWxvYWRzKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgY29udmVydCB0byBQbGFuIEIgYmVjYXVzZSBtLWxpbmVzICcgK1xuICAgICAgICAgICAgICAnaGF2ZSBkaWZmZXJlbnQgcGF5bG9hZHMgYW5kIHRoaXMgbGlicmFyeSBkb2VzIG5vdCBoYXZlICcgK1xuICAgICAgICAgICAgICAnc3VwcG9ydCBmb3IgdGhhdCcpO1xuICAgICAgICB9XG5cbiAgICB9KTtcblxuICAgIC8vIEltcGxvZGUgdGhlIFVuaWZpZWQgUGxhbiBtLWxpbmVzL3RyYWNrcyBpbnRvIFBsYW4gQiBjaGFubmVscy5cbiAgICBtZWRpYS5mb3JFYWNoKGZ1bmN0aW9uKHVMaW5lKSB7XG4gICAgICAgIGlmICh1TGluZS50eXBlID09PSAnYXBwbGljYXRpb24nKSB7XG4gICAgICAgICAgICBzZXNzaW9uLm1lZGlhLnB1c2godUxpbmUpO1xuICAgICAgICAgICAgdHlwZXMucHVzaCh1TGluZS5taWQpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkIHNvdXJjZXMgdG8gdGhlIGNoYW5uZWwgYW5kIGhhbmRsZSBhPW1zaWQuXG4gICAgICAgIGlmICh0eXBlb2YgdUxpbmUuc291cmNlcyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHVMaW5lLnNvdXJjZXMpLmZvckVhY2goZnVuY3Rpb24oc3NyYykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdHlwZTJibFt1TGluZS50eXBlXS5zb3VyY2VzICE9PSAnb2JqZWN0JylcbiAgICAgICAgICAgICAgICAgICAgdHlwZTJibFt1TGluZS50eXBlXS5zb3VyY2VzID0ge307XG5cbiAgICAgICAgICAgICAgICAvLyBBc3NpZ24gdGhlIHNvdXJjZXMgdG8gdGhlIGNoYW5uZWwuXG4gICAgICAgICAgICAgICAgdHlwZTJibFt1TGluZS50eXBlXS5zb3VyY2VzW3NzcmNdID1cbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuc291cmNlc1tzc3JjXTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdUxpbmUubXNpZCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSW4gUGxhbiBCIHRoZSBtc2lkIGlzIGFuIFNTUkMgYXR0cmlidXRlLiBBbHNvLCB3ZSBkb24ndFxuICAgICAgICAgICAgICAgICAgICAvLyBjYXJlIGFib3V0IHRoZSBvYnNvbGV0ZSBsYWJlbCBhbmQgbXNsYWJlbCBhdHRyaWJ1dGVzLlxuICAgICAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgICAgICAvLyBOb3RlIHRoYXQgaXQgaXMgbm90IGd1YXJhbnRlZWQgdGhhdCB0aGUgdUxpbmUgd2lsbFxuICAgICAgICAgICAgICAgICAgICAvLyBoYXZlIGFuIG1zaWQuIHJlY3Zvbmx5IGNoYW5uZWxzIGluIHBhcnRpY3VsYXIgZG9uJ3QgaGF2ZVxuICAgICAgICAgICAgICAgICAgICAvLyBvbmUuXG4gICAgICAgICAgICAgICAgICAgIHR5cGUyYmxbdUxpbmUudHlwZV0uc291cmNlc1tzc3JjXS5tc2lkID1cbiAgICAgICAgICAgICAgICAgICAgICAgIHVMaW5lLm1zaWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIE5PVEUgc3NyY3MgaW4gc3NyYyBncm91cHMgd2lsbCBzaGFyZSBtc2lkcywgYXNcbiAgICAgICAgICAgICAgICAvLyBkcmFmdC11YmVydGktcnRjd2ViLXBsYW4tMDAgbWFuZGF0ZXMuXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEFkZCBzc3JjIGdyb3VwcyB0byB0aGUgY2hhbm5lbC5cbiAgICAgICAgaWYgKHR5cGVvZiB1TGluZS5zc3JjR3JvdXBzICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgICAgIEFycmF5LmlzQXJyYXkodUxpbmUuc3NyY0dyb3VwcykpIHtcblxuICAgICAgICAgICAgLy8gQ3JlYXRlIHRoZSBzc3JjR3JvdXBzIGFycmF5LCBpZiBpdCdzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgICAgaWYgKHR5cGVvZiB0eXBlMmJsW3VMaW5lLnR5cGVdLnNzcmNHcm91cHMgPT09ICd1bmRlZmluZWQnIHx8XG4gICAgICAgICAgICAgICAgICAgICFBcnJheS5pc0FycmF5KHR5cGUyYmxbdUxpbmUudHlwZV0uc3NyY0dyb3VwcykpIHtcbiAgICAgICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLnNzcmNHcm91cHMgPSBbXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdHlwZTJibFt1TGluZS50eXBlXS5zc3JjR3JvdXBzID1cbiAgICAgICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLnNzcmNHcm91cHMuY29uY2F0KFxuICAgICAgICAgICAgICAgICAgICB1TGluZS5zc3JjR3JvdXBzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlMmJsW3VMaW5lLnR5cGVdID09PSB1TGluZSkge1xuICAgICAgICAgICAgLy8gUGxhbiBCIG1pZHMgYXJlIGluIFsnYXVkaW8nLCAndmlkZW8nLCAnZGF0YSddXG4gICAgICAgICAgICB1TGluZS5taWQgPSB1TGluZS50eXBlO1xuXG4gICAgICAgICAgICAvLyBQbGFuIEIgZG9lc24ndCBzdXBwb3J0L25lZWQgdGhlIGJ1bmRsZS1vbmx5IGF0dHJpYnV0ZS5cbiAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5idW5kbGVPbmx5O1xuXG4gICAgICAgICAgICAvLyBJbiBQbGFuIEIgdGhlIG1zaWQgaXMgYW4gU1NSQyBhdHRyaWJ1dGUuXG4gICAgICAgICAgICBkZWxldGUgdUxpbmUubXNpZDtcblxuXHQgICAgaWYgKHVMaW5lLnR5cGUgPT0gbWVkaWFbMF0udHlwZSkge1xuXHQgICAgICB0eXBlcy51bnNoaWZ0KHVMaW5lLnR5cGUpO1xuXHQgICAgICAvLyBBZGQgdGhlIGNoYW5uZWwgdG8gdGhlIG5ldyBtZWRpYSBhcnJheS5cblx0ICAgICAgc2Vzc2lvbi5tZWRpYS51bnNoaWZ0KHVMaW5lKTtcblx0ICAgIH0gZWxzZSB7XG5cdCAgICAgIHR5cGVzLnB1c2godUxpbmUudHlwZSk7XG5cdCAgICAgIC8vIEFkZCB0aGUgY2hhbm5lbCB0byB0aGUgbmV3IG1lZGlhIGFycmF5LlxuXHQgICAgICBzZXNzaW9uLm1lZGlhLnB1c2godUxpbmUpO1xuXHQgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICBpZiAodHlwZW9mIHNlc3Npb24uZ3JvdXBzICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgLy8gV2UgcmVnZW5lcmF0ZSB0aGUgQlVORExFIGdyb3VwIHdpdGggdGhlIG5ldyBtaWRzLlxuICAgICAgc2Vzc2lvbi5ncm91cHMuc29tZShmdW5jdGlvbihncm91cCkge1xuXHQgIGlmIChncm91cC50eXBlID09PSAnQlVORExFJykge1xuXHQgICAgICBncm91cC5taWRzID0gdHlwZXMuam9pbignICcpO1xuXHQgICAgICByZXR1cm4gdHJ1ZTtcblx0ICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBtc2lkIHNlbWFudGljXG4gICAgc2Vzc2lvbi5tc2lkU2VtYW50aWMgPSB7XG4gICAgICAgIHNlbWFudGljOiAnV01TJyxcbiAgICAgICAgdG9rZW46ICcqJ1xuICAgIH07XG5cbiAgICB2YXIgcmVzU3RyID0gdHJhbnNmb3JtLndyaXRlKHNlc3Npb24pO1xuXG4gICAgcmV0dXJuIG5ldyBSVENTZXNzaW9uRGVzY3JpcHRpb24oe1xuICAgICAgICB0eXBlOiBkZXNjLnR5cGUsXG4gICAgICAgIHNkcDogcmVzU3RyXG4gICAgfSk7XG5cbiAgICAvLyNlbmRyZWdpb25cbn07XG5cbi8qIGZvbGxvdyBydWxlcyBkZWZpbmVkIGluIFJGQzQxNDUgKi9cbmZ1bmN0aW9uIGFkZFNldHVwQXR0cih1TGluZSkge1xuICAgIGlmICh0eXBlb2YgdUxpbmUuc2V0dXAgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodUxpbmUuc2V0dXAgPT09IFwiYWN0aXZlXCIpIHtcbiAgICAgICAgICAgIHVMaW5lLnNldHVwID0gXCJwYXNzaXZlXCI7XG4gICAgfSBlbHNlIGlmICh1TGluZS5zZXR1cCA9PT0gXCJwYXNzaXZlXCIpIHtcbiAgICAgICAgdUxpbmUuc2V0dXAgPSBcImFjdGl2ZVwiO1xuICAgIH1cbn1cblxuLyoqXG4gKiBUaGlzIG1ldGhvZCB0cmFuc2Zvcm1zIGEgUGxhbiBCIFNEUCB0byBhbiBlcXVpdmFsZW50IFVuaWZpZWQgUGxhbiBTRFAuIEFcbiAqIFBlZXJDb25uZWN0aW9uIHdyYXBwZXIgdHJhbnNmb3JtcyB0aGUgU0RQIHRvIFVuaWZpZWQgUGxhbiBiZWZvcmUgcGFzc2luZyBpdFxuICogdG8gRkYuXG4gKlxuICogQHBhcmFtIGRlc2NcbiAqIEByZXR1cm5zIHsqfVxuICovXG5JbnRlcm9wLnByb3RvdHlwZS50b1VuaWZpZWRQbGFuID0gZnVuY3Rpb24oZGVzYykge1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAvLyNyZWdpb24gUHJlbGltaW5hcnkgaW5wdXQgdmFsaWRhdGlvbi5cblxuICAgIGlmICh0eXBlb2YgZGVzYyAhPT0gJ29iamVjdCcgfHwgZGVzYyA9PT0gbnVsbCB8fFxuICAgICAgICB0eXBlb2YgZGVzYy5zZHAgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignQW4gZW1wdHkgZGVzY3JpcHRpb24gd2FzIHBhc3NlZCBhcyBhbiBhcmd1bWVudC4nKTtcbiAgICAgICAgcmV0dXJuIGRlc2M7XG4gICAgfVxuXG4gICAgdmFyIHNlc3Npb24gPSB0cmFuc2Zvcm0ucGFyc2UoZGVzYy5zZHApO1xuXG4gICAgLy8gSWYgdGhlIFNEUCBjb250YWlucyBubyBtZWRpYSwgdGhlcmUncyBub3RoaW5nIHRvIHRyYW5zZm9ybS5cbiAgICBpZiAodHlwZW9mIHNlc3Npb24ubWVkaWEgPT09ICd1bmRlZmluZWQnIHx8XG4gICAgICAgICFBcnJheS5pc0FycmF5KHNlc3Npb24ubWVkaWEpIHx8IHNlc3Npb24ubWVkaWEubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignVGhlIGRlc2NyaXB0aW9uIGhhcyBubyBtZWRpYS4nKTtcbiAgICAgICAgcmV0dXJuIGRlc2M7XG4gICAgfVxuXG4gICAgLy8gVHJ5IHNvbWUgaGV1cmlzdGljcyB0byBcIm1ha2Ugc3VyZVwiIHRoaXMgaXMgYSBQbGFuIEIgU0RQLiBQbGFuIEIgU0RQIGhhc1xuICAgIC8vIGEgdmlkZW8sIGFuIGF1ZGlvIGFuZCBhIGRhdGEgXCJjaGFubmVsXCIgYXQgbW9zdC5cbiAgICBpZiAoc2Vzc2lvbi5tZWRpYS5sZW5ndGggPiAzIHx8ICFzZXNzaW9uLm1lZGlhLmV2ZXJ5KGZ1bmN0aW9uKG0pIHtcbiAgICAgICAgICAgIHJldHVybiBbJ3ZpZGVvJywgJ2F1ZGlvJywgJ2RhdGEnXS5pbmRleE9mKG0ubWlkKSAhPT0gLTE7XG4gICAgICAgIH0pKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignVGhpcyBkZXNjcmlwdGlvbiBkb2VzIG5vdCBsb29rIGxpa2UgUGxhbiBCLicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICAvLyBNYWtlIHN1cmUgdGhpcyBQbGFuIEIgU0RQIGNhbiBiZSBjb252ZXJ0ZWQgdG8gYSBVbmlmaWVkIFBsYW4gU0RQLlxuICAgIHZhciBtaWRzID0gW107XG4gICAgc2Vzc2lvbi5tZWRpYS5mb3JFYWNoKGZ1bmN0aW9uKG0pIHtcbiAgICAgICAgbWlkcy5wdXNoKG0ubWlkKTtcbiAgICB9KTtcblxuICAgIHZhciBoYXNCdW5kbGUgPSBmYWxzZTtcbiAgICBpZiAodHlwZW9mIHNlc3Npb24uZ3JvdXBzICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICBBcnJheS5pc0FycmF5KHNlc3Npb24uZ3JvdXBzKSkge1xuICAgICAgICBoYXNCdW5kbGUgPSBzZXNzaW9uLmdyb3Vwcy5ldmVyeShmdW5jdGlvbihnKSB7XG4gICAgICAgICAgICByZXR1cm4gZy50eXBlICE9PSAnQlVORExFJyB8fFxuICAgICAgICAgICAgICAgIGFycmF5RXF1YWxzLmFwcGx5KGcubWlkcy5zb3J0KCksIFttaWRzLnNvcnQoKV0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAoIWhhc0J1bmRsZSkge1xuICAgICAgICB2YXIgbXVzdEJlQnVuZGxlID0gZmFsc2U7XG5cbiAgICAgICAgc2Vzc2lvbi5tZWRpYS5mb3JFYWNoKGZ1bmN0aW9uKG0pIHtcbiAgICAgICAgICAgIGlmIChtLmRpcmVjdGlvbiAhPT0gJ2luYWN0aXZlJykge1xuICAgICAgICAgICAgICAgIG11c3RCZUJ1bmRsZSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChtdXN0QmVCdW5kbGUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBjb252ZXJ0IHRvIFVuaWZpZWQgUGxhbiBiZWNhdXNlIG0tbGluZXMgdGhhdFwiICtcbiAgICAgICAgICAgICAgXCIgYXJlIG5vdCBidW5kbGVkIHdlcmUgZm91bmQuXCIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8jZW5kcmVnaW9uXG5cblxuICAgIC8vI3JlZ2lvbiBDb252ZXJ0IGZyb20gUGxhbiBCIHRvIFVuaWZpZWQgUGxhbi5cblxuICAgIC8vIFVuZm9ydHVuYXRlbHksIGEgUGxhbiBCIG9mZmVyL2Fuc3dlciBkb2Vzbid0IGhhdmUgZW5vdWdoIGluZm9ybWF0aW9uIHRvXG4gICAgLy8gcmVidWlsZCBhbiBlcXVpdmFsZW50IFVuaWZpZWQgUGxhbiBvZmZlci9hbnN3ZXIuXG4gICAgLy9cbiAgICAvLyBGb3IgZXhhbXBsZSwgaWYgdGhpcyBpcyBhIGxvY2FsIGFuc3dlciAoaW4gVW5pZmllZCBQbGFuIHN0eWxlKSB0aGF0IHdlXG4gICAgLy8gY29udmVydCB0byBQbGFuIEIgcHJpb3IgdG8gaGFuZGluZyBpdCBvdmVyIHRvIHRoZSBhcHBsaWNhdGlvbiAodGhlXG4gICAgLy8gUGVlckNvbm5lY3Rpb24gd3JhcHBlciBjYWxsZWQgdXMsIGZvciBpbnN0YW5jZSwgYWZ0ZXIgYSBzdWNjZXNzZnVsXG4gICAgLy8gY3JlYXRlQW5zd2VyKSwgd2Ugd2FudCB0byByZW1lbWJlciB0aGUgbS1saW5lIGF0IHdoaWNoIHdlJ3ZlIHNlZW4gdGhlXG4gICAgLy8gKGxvY2FsKSBTU1JDLiBUaGF0J3MgYmVjYXVzZSB3aGVuIHRoZSBhcHBsaWNhdGlvbiB3YW50cyB0byBkbyBjYWxsIHRoZVxuICAgIC8vIFNMRCBtZXRob2QsIGZvcmNpbmcgdXMgdG8gZG8gdGhlIGludmVyc2UgdHJhbnNmb3JtYXRpb24gKGZyb20gUGxhbiBCIHRvXG4gICAgLy8gVW5pZmllZCBQbGFuKSwgd2UgbmVlZCB0byBrbm93IHRvIHdoaWNoIG0tbGluZSB0byBhc3NpZ24gdGhlIChsb2NhbClcbiAgICAvLyBTU1JDLiBXZSBhbHNvIG5lZWQgdG8ga25vdyBhbGwgdGhlIG90aGVyIG0tbGluZXMgdGhhdCB0aGUgb3JpZ2luYWxcbiAgICAvLyBhbnN3ZXIgaGFkIGFuZCBpbmNsdWRlIHRoZW0gaW4gdGhlIHRyYW5zZm9ybWVkIGFuc3dlciBhcyB3ZWxsLlxuICAgIC8vXG4gICAgLy8gQW5vdGhlciBleGFtcGxlIGlzIGlmIHRoaXMgaXMgYSByZW1vdGUgb2ZmZXIgdGhhdCB3ZSBjb252ZXJ0IHRvIFBsYW4gQlxuICAgIC8vIHByaW9yIHRvIGdpdmluZyBpdCB0byB0aGUgYXBwbGljYXRpb24sIHdlIHdhbnQgdG8gcmVtZW1iZXIgdGhlIG1pZCBhdFxuICAgIC8vIHdoaWNoIHdlJ3ZlIHNlZW4gdGhlIChyZW1vdGUpIFNTUkMuXG4gICAgLy9cbiAgICAvLyBJbiB0aGUgaXRlcmF0aW9uIHRoYXQgZm9sbG93cywgd2UgdXNlIHRoZSBjYWNoZWQgVW5pZmllZCBQbGFuIChpZiBpdFxuICAgIC8vIGV4aXN0cykgdG8gYXNzaWduIG1pZHMgdG8gc3NyY3MuXG5cbiAgICB2YXIgdHlwZTtcbiAgICBpZiAoZGVzYy50eXBlID09PSAnYW5zd2VyJykge1xuICAgICAgICB0eXBlID0gJ29mZmVyJztcbiAgICB9IGVsc2UgaWYgKGRlc2MudHlwZSA9PT0gJ29mZmVyJykge1xuICAgICAgICB0eXBlID0gJ2Fuc3dlcic7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVHlwZSAnXCIgKyBkZXNjLnR5cGUgKyBcIicgbm90IHN1cHBvcnRlZC5cIik7XG4gICAgfVxuXG4gICAgdmFyIGNhY2hlZDtcbiAgICBpZiAodHlwZW9mIHRoaXMuY2FjaGVbdHlwZV0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGNhY2hlZCA9IHRyYW5zZm9ybS5wYXJzZSh0aGlzLmNhY2hlW3R5cGVdKTtcbiAgICB9XG5cbiAgICB2YXIgcmVjdm9ubHlTc3JjcyA9IHtcbiAgICAgICAgYXVkaW86IHt9LFxuICAgICAgICB2aWRlbzoge31cbiAgICB9O1xuXG4gICAgLy8gQSBoZWxwZXIgbWFwIHRoYXQgc2VuZHMgbWlkcyB0byBtLWxpbmUgb2JqZWN0cy4gV2UgdXNlIGl0IGxhdGVyIHRvXG4gICAgLy8gcmVidWlsZCB0aGUgVW5pZmllZCBQbGFuIHN0eWxlIHNlc3Npb24ubWVkaWEgYXJyYXkuXG4gICAgdmFyIG1pZDJ1bCA9IHt9O1xuICAgIHZhciBiSWR4ID0gMDtcbiAgICB2YXIgdUlkeCA9IDA7XG5cbiAgICB2YXIgc291cmNlczJ1bCA9IHt9O1xuXG4gICAgdmFyIGNhbmRpZGF0ZXM7XG4gICAgdmFyIGljZVVmcmFnO1xuICAgIHZhciBpY2VQd2Q7XG4gICAgdmFyIGZpbmdlcnByaW50O1xuICAgIHZhciBwYXlsb2FkcyA9IHt9O1xuICAgIHZhciBydGNwRmIgPSB7fTtcbiAgICB2YXIgcnRwID0ge307XG5cbiAgICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24oYkxpbmUpIHtcbiAgICAgICAgaWYgKCh0eXBlb2YgYkxpbmUucnRjcE11eCAhPT0gJ3N0cmluZycgfHxcbiAgICAgICAgICAgIGJMaW5lLnJ0Y3BNdXggIT09ICdydGNwLW11eCcpICYmXG4gICAgICAgICAgICBiTGluZS5kaXJlY3Rpb24gIT09ICdpbmFjdGl2ZScpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBjb252ZXJ0IHRvIFVuaWZpZWQgUGxhbiBiZWNhdXNlIG0tbGluZXMgXCIgK1xuICAgICAgICAgICAgICAgIFwid2l0aG91dCB0aGUgcnRjcC1tdXggYXR0cmlidXRlIHdlcmUgZm91bmQuXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGJMaW5lLnR5cGUgPT09ICdhcHBsaWNhdGlvbicpIHtcbiAgICAgICAgICAgIG1pZDJ1bFtiTGluZS5taWRdID0gYkxpbmU7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBXaXRoIHJ0Y3AtbXV4IGFuZCBidW5kbGUgYWxsIHRoZSBjaGFubmVscyBzaG91bGQgaGF2ZSB0aGUgc2FtZSBJQ0VcbiAgICAgICAgLy8gc3R1ZmYuXG4gICAgICAgIHZhciBzb3VyY2VzID0gYkxpbmUuc291cmNlcztcbiAgICAgICAgdmFyIHNzcmNHcm91cHMgPSBiTGluZS5zc3JjR3JvdXBzO1xuICAgICAgICB2YXIgcG9ydCA9IGJMaW5lLnBvcnQ7XG5cbiAgICAgICAgLyogQ2hyb21lIGFkZHMgZGlmZmVyZW50IGNhbmRpZGF0ZXMgZXZlbiB1c2luZyBidW5kbGUsIHNvIHdlIGNvbmNhdCB0aGUgY2FuZGlkYXRlcyBsaXN0ICovXG4gICAgICAgIGlmICh0eXBlb2YgYkxpbmUuY2FuZGlkYXRlcyAhPSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBjYW5kaWRhdGVzICE9ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgY2FuZGlkYXRlcyA9IGNhbmRpZGF0ZXMuY29uY2F0KGJMaW5lLmNhbmRpZGF0ZXMpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjYW5kaWRhdGVzID0gYkxpbmUuY2FuZGlkYXRlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgodHlwZW9mIGljZVVmcmFnICE9ICd1bmRlZmluZWQnKSAmJiAodHlwZW9mIGJMaW5lLmljZVVmcmFnICE9ICd1bmRlZmluZWQnKSAmJiAoaWNlVWZyYWcgIT0gYkxpbmUuaWNlVWZyYWcpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJPbmx5IEJVTkRMRSBzdXBwb3J0ZWQsIGljZVVmcmFnIG11c3QgYmUgdGhlIHNhbWUgZm9yIGFsbCBtLWxpbmVzLlxcblwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlxcdExhc3QgaWNlVWZyYWc6IFwiICsgaWNlVWZyYWcgKyBcIlxcblwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlxcdE5ldyBpY2VVZnJhZzogXCIgKyBiTGluZS5pY2VVZnJhZ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgYkxpbmUuaWNlVWZyYWcgIT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICBpY2VVZnJhZyA9IGJMaW5lLmljZVVmcmFnO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCh0eXBlb2YgaWNlUHdkICE9ICd1bmRlZmluZWQnKSAmJiAodHlwZW9mIGJMaW5lLmljZVB3ZCAhPSAndW5kZWZpbmVkJykgJiYgKGljZVB3ZCAhPSBiTGluZS5pY2VQd2QpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJPbmx5IEJVTkRMRSBzdXBwb3J0ZWQsIGljZVB3ZCBtdXN0IGJlIHRoZSBzYW1lIGZvciBhbGwgbS1saW5lcy5cXG5cIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJcXHRMYXN0IGljZVB3ZDogXCIgKyBpY2VQd2QgKyBcIlxcblwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlxcdE5ldyBpY2VQd2Q6IFwiICsgYkxpbmUuaWNlUHdkXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBiTGluZS5pY2VQd2QgIT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICBpY2VQd2QgPSBiTGluZS5pY2VQd2Q7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoKHR5cGVvZiBmaW5nZXJwcmludCAhPSAndW5kZWZpbmVkJykgJiYgKHR5cGVvZiBiTGluZS5maW5nZXJwcmludCAhPSAndW5kZWZpbmVkJykgJiZcbiAgICAgICAgICAgIChmaW5nZXJwcmludC50eXBlICE9IGJMaW5lLmZpbmdlcnByaW50LnR5cGUgfHwgZmluZ2VycHJpbnQuaGFzaCAhPSBiTGluZS5maW5nZXJwcmludC5oYXNoKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiT25seSBCVU5ETEUgc3VwcG9ydGVkLCBmaW5nZXJwcmludCBtdXN0IGJlIHRoZSBzYW1lIGZvciBhbGwgbS1saW5lcy5cXG5cIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJcXHRMYXN0IGZpbmdlcnByaW50OiBcIiArIEpTT04uc3RyaW5naWZ5KGZpbmdlcnByaW50KSArIFwiXFxuXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXFx0TmV3IGZpbmdlcnByaW50OiBcIiArIEpTT04uc3RyaW5naWZ5KGJMaW5lLmZpbmdlcnByaW50KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgYkxpbmUuZmluZ2VycHJpbnQgIT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICBmaW5nZXJwcmludCA9IGJMaW5lLmZpbmdlcnByaW50O1xuICAgICAgICB9XG5cbiAgICAgICAgcGF5bG9hZHNbYkxpbmUudHlwZV0gPSBiTGluZS5wYXlsb2FkcztcbiAgICAgICAgcnRjcEZiW2JMaW5lLnR5cGVdID0gYkxpbmUucnRjcEZiO1xuICAgICAgICBydHBbYkxpbmUudHlwZV0gPSBiTGluZS5ydHA7XG5cbiAgICAgICAgLy8gaW52ZXJ0ZWQgc3NyYyBncm91cCBtYXBcbiAgICAgICAgdmFyIHNzcmMyZ3JvdXAgPSB7fTtcbiAgICAgICAgaWYgKHR5cGVvZiBzc3JjR3JvdXBzICE9PSAndW5kZWZpbmVkJyAmJiBBcnJheS5pc0FycmF5KHNzcmNHcm91cHMpKSB7XG4gICAgICAgICAgICBzc3JjR3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKHNzcmNHcm91cCkge1xuICAgICAgICAgICAgICAgIC8vIFhYWCBUaGlzIG1pZ2h0IGJyYWtlIGlmIGFuIFNTUkMgaXMgaW4gbW9yZSB0aGFuIG9uZSBncm91cFxuICAgICAgICAgICAgICAgIC8vIGZvciBzb21lIHJlYXNvbi5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHNzcmNHcm91cC5zc3JjcyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgICAgICAgICAgICAgQXJyYXkuaXNBcnJheShzc3JjR3JvdXAuc3NyY3MpKSB7XG4gICAgICAgICAgICAgICAgICAgIHNzcmNHcm91cC5zc3Jjcy5mb3JFYWNoKGZ1bmN0aW9uIChzc3JjKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHNzcmMyZ3JvdXBbc3NyY10gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3NyYzJncm91cFtzc3JjXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBzc3JjMmdyb3VwW3NzcmNdLnB1c2goc3NyY0dyb3VwKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzc3JjIHRvIG0tbGluZSBpbmRleC5cbiAgICAgICAgdmFyIHNzcmMybWwgPSB7fTtcblxuICAgICAgICBpZiAodHlwZW9mIHNvdXJjZXMgPT09ICdvYmplY3QnKSB7XG5cbiAgICAgICAgICAgIC8vIFdlJ2xsIHVzZSB0aGUgXCJiTGluZVwiIG9iamVjdCBhcyBhIHByb3RvdHlwZSBmb3IgZWFjaCBuZXcgXCJtTGluZVwiXG4gICAgICAgICAgICAvLyB0aGF0IHdlIGNyZWF0ZSwgYnV0IGZpcnN0IHdlIG5lZWQgdG8gY2xlYW4gaXQgdXAgYSBiaXQuXG4gICAgICAgICAgICBkZWxldGUgYkxpbmUuc291cmNlcztcbiAgICAgICAgICAgIGRlbGV0ZSBiTGluZS5zc3JjR3JvdXBzO1xuICAgICAgICAgICAgZGVsZXRlIGJMaW5lLmNhbmRpZGF0ZXM7XG4gICAgICAgICAgICBkZWxldGUgYkxpbmUuaWNlVWZyYWc7XG4gICAgICAgICAgICBkZWxldGUgYkxpbmUuaWNlUHdkO1xuICAgICAgICAgICAgZGVsZXRlIGJMaW5lLmZpbmdlcnByaW50O1xuICAgICAgICAgICAgZGVsZXRlIGJMaW5lLnBvcnQ7XG4gICAgICAgICAgICBkZWxldGUgYkxpbmUubWlkO1xuXG4gICAgICAgICAgICAvLyBFeHBsb2RlIHRoZSBQbGFuIEIgY2hhbm5lbCBzb3VyY2VzIHdpdGggb25lIG0tbGluZSBwZXIgc291cmNlLlxuICAgICAgICAgICAgT2JqZWN0LmtleXMoc291cmNlcykuZm9yRWFjaChmdW5jdGlvbihzc3JjKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBUaGUgKHVuaWZpZWQpIG0tbGluZSBmb3IgdGhpcyBTU1JDLiBXZSBlaXRoZXIgY3JlYXRlIGl0IGZyb21cbiAgICAgICAgICAgICAgICAvLyBzY3JhdGNoIG9yLCBpZiBpdCdzIGEgZ3JvdXBlZCBTU1JDLCB3ZSByZS11c2UgYSByZWxhdGVkXG4gICAgICAgICAgICAgICAgLy8gbWxpbmUuIEluIG90aGVyIHdvcmRzLCBpZiB0aGUgc291cmNlIGlzIGdyb3VwZWQgd2l0aCBhbm90aGVyXG4gICAgICAgICAgICAgICAgLy8gc291cmNlLCBwdXQgdGhlIHR3byB0b2dldGhlciBpbiB0aGUgc2FtZSBtLWxpbmUuXG4gICAgICAgICAgICAgICAgdmFyIHVMaW5lO1xuXG4gICAgICAgICAgICAgICAgLy8gV2UgYXNzdW1lIGhlcmUgdGhhdCB3ZSBhcmUgdGhlIGFuc3dlcmVyIGluIHRoZSBPL0EsIHNvIGFueVxuICAgICAgICAgICAgICAgIC8vIG9mZmVycyB3aGljaCB3ZSB0cmFuc2xhdGUgY29tZSBmcm9tIHRoZSByZW1vdGUgc2lkZSwgd2hpbGVcbiAgICAgICAgICAgICAgICAvLyBhbnN3ZXJzIGFyZSBsb2NhbC4gU28gdGhlIGNoZWNrIGJlbG93IGlzIHRvIG1ha2UgdGhhdCB3ZVxuICAgICAgICAgICAgICAgIC8vIGhhbmRsZSByZWNlaXZlLW9ubHkgU1NSQ3MgaW4gYSBzcGVjaWFsIHdheSBvbmx5IGlmIHRoZXkgY29tZVxuICAgICAgICAgICAgICAgIC8vIGZyb20gdGhlIHJlbW90ZSBzaWRlLlxuICAgICAgICAgICAgICAgIGlmIChkZXNjLnR5cGU9PT0nb2ZmZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdlIHdhbnQgdG8gZGV0ZWN0IFNTUkNzIHdoaWNoIGFyZSB1c2VkIGJ5IGEgcmVtb3RlIHBlZXJcbiAgICAgICAgICAgICAgICAgICAgLy8gaW4gYW4gbS1saW5lIHdpdGggZGlyZWN0aW9uPXJlY3Zvbmx5IChpLmUuIHRoZXkgYXJlXG4gICAgICAgICAgICAgICAgICAgIC8vIGJlaW5nIHVzZWQgZm9yIFJUQ1Agb25seSkuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgaW5mb3JtYXRpb24gd291bGQgaGF2ZSBnb3R0ZW4gbG9zdCBpZiB0aGUgcmVtb3RlXG4gICAgICAgICAgICAgICAgICAgIC8vIHBlZXIgdXNlZCBVbmlmaWVkIFBsYW4gYW5kIHRoZWlyIGxvY2FsIGRlc2NyaXB0aW9uIHdhc1xuICAgICAgICAgICAgICAgICAgICAvLyB0cmFuc2xhdGVkIHRvIFBsYW4gQi4gU28gd2UgdXNlIHRoZSBsYWNrIG9mIGFuIE1TSURcbiAgICAgICAgICAgICAgICAgICAgLy8gYXR0cmlidXRlIHRvIGRlZHVjZSBhIFwicmVjZWl2ZSBvbmx5XCIgU1NSQy5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzb3VyY2VzW3NzcmNdLm1zaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Zvbmx5U3NyY3NbYkxpbmUudHlwZV1bc3NyY10gPSBzb3VyY2VzW3NzcmNdO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVjZWl2ZS1vbmx5IFNTUkNzIG11c3Qgbm90IGNyZWF0ZSBuZXcgbS1saW5lcy4gV2VcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdpbGwgYXNzaWduIHRoZW0gdG8gYW4gZXhpc3RpbmcgbS1saW5lIGxhdGVyLlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBzc3JjMmdyb3VwW3NzcmNdICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KHNzcmMyZ3JvdXBbc3NyY10pKSB7XG4gICAgICAgICAgICAgICAgICAgIHNzcmMyZ3JvdXBbc3NyY10uc29tZShmdW5jdGlvbiAoc3NyY0dyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzc3JjR3JvdXAuc3NyY3MgKmlzKiBhbiBBcnJheSwgbm8gbmVlZCB0byBjaGVja1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWdhaW4gaGVyZS5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzc3JjR3JvdXAuc3NyY3Muc29tZShmdW5jdGlvbiAocmVsYXRlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc3NyYzJtbFtyZWxhdGVkXSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUgPSBzc3JjMm1sW3JlbGF0ZWRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB1TGluZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhlIG0tbGluZSBhbHJlYWR5IGV4aXN0cy4gSnVzdCBhZGQgdGhlIHNvdXJjZS5cbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuc291cmNlc1tzc3JjXSA9IHNvdXJjZXNbc3NyY107XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBzb3VyY2VzW3NzcmNdLm1zaWQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gVXNlIHRoZSBcImJMaW5lXCIgYXMgYSBwcm90b3R5cGUgZm9yIHRoZSBcInVMaW5lXCIuXG4gICAgICAgICAgICAgICAgICAgIHVMaW5lID0gT2JqZWN0LmNyZWF0ZShiTGluZSk7XG4gICAgICAgICAgICAgICAgICAgIHNzcmMybWxbc3NyY10gPSB1TGluZTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHNvdXJjZXNbc3NyY10ubXNpZCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFzc2lnbiB0aGUgbXNpZCBvZiB0aGUgc291cmNlIHRvIHRoZSBtLWxpbmUuIE5vdGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoYXQgaXQgaXMgbm90IGd1YXJhbnRlZWQgdGhhdCB0aGUgc291cmNlIHdpbGwgaGF2ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbXNpZC4gSW4gcGFydGljdWxhciBcInJlY3Zvbmx5XCIgc291cmNlcyBkb24ndCBoYXZlIGFuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBtc2lkLiBOb3RlIHRoYXQgXCJyZWN2b25seVwiIGlzIGEgdGVybSBvbmx5IGRlZmluZWRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZvciBtLWxpbmVzLlxuICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUubXNpZCA9IHNvdXJjZXNbc3NyY10ubXNpZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBzb3VyY2VzW3NzcmNdLm1zaWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBXZSBhc3NpZ24gb25lIFNTUkMgcGVyIG1lZGlhIGxpbmUuXG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLnNvdXJjZXMgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuc291cmNlc1tzc3JjXSA9IHNvdXJjZXNbc3NyY107XG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLnNzcmNHcm91cHMgPSBzc3JjMmdyb3VwW3NzcmNdO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFVzZSB0aGUgY2FjaGVkIFVuaWZpZWQgUGxhbiBTRFAgKGlmIGl0IGV4aXN0cykgdG8gYXNzaWduXG4gICAgICAgICAgICAgICAgICAgIC8vIFNTUkNzIHRvIG1pZHMuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2FjaGVkICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZW9mIGNhY2hlZC5tZWRpYSAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LmlzQXJyYXkoY2FjaGVkLm1lZGlhKSkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjYWNoZWQubWVkaWEuZm9yRWFjaChmdW5jdGlvbiAobSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbS5zb3VyY2VzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPYmplY3Qua2V5cyhtLnNvdXJjZXMpLmZvckVhY2goZnVuY3Rpb24gKHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzID09PSBzc3JjKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUubWlkID0gbS5taWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB1TGluZS5taWQgPT09ICd1bmRlZmluZWQnKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHRoaXMgaXMgYW4gU1NSQyB0aGF0IHdlIHNlZSBmb3IgdGhlIGZpcnN0IHRpbWVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFzc2lnbiBpdCBhIG5ldyBtaWQuIFRoaXMgaXMgdHlwaWNhbGx5IHRoZSBjYXNlIHdoZW5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoaXMgbWV0aG9kIGlzIGNhbGxlZCB0byB0cmFuc2Zvcm0gYSByZW1vdGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRlc2NyaXB0aW9uIGZvciB0aGUgZmlyc3QgdGltZSBvciB3aGVuIHRoZXJlIGlzIGFcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5ldyBTU1JDIGluIHRoZSByZW1vdGUgZGVzY3JpcHRpb24gYmVjYXVzZSBhIG5ld1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcGVlciBoYXMgam9pbmVkIHRoZSBjb25mZXJlbmNlLiBMb2NhbCBTU1JDcyBzaG91bGRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGhhdmUgYWxyZWFkeSBiZWVuIGFkZGVkIHRvIHRoZSBtYXAgaW4gdGhlIHRvUGxhbkJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG1ldGhvZC5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBCZWNhdXNlIEZGIGdlbmVyYXRlcyBhbnN3ZXJzIGluIFVuaWZpZWQgUGxhbiBzdHlsZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdlIE1VU1QgYWxyZWFkeSBoYXZlIGEgY2FjaGVkIGFuc3dlciB3aXRoIGFsbCB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGxvY2FsIFNTUkNzIG1hcHBlZCB0byBzb21lIG0tbGluZS9taWQuXG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHVMaW5lLm1pZCA9IFtiTGluZS50eXBlLCAnLScsIHNzcmNdLmpvaW4oJycpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSW5jbHVkZSB0aGUgY2FuZGlkYXRlcyBpbiB0aGUgMXN0IG1lZGlhIGxpbmUuXG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLmNhbmRpZGF0ZXMgPSBjYW5kaWRhdGVzO1xuICAgICAgICAgICAgICAgICAgICB1TGluZS5pY2VVZnJhZyA9IGljZVVmcmFnO1xuICAgICAgICAgICAgICAgICAgICB1TGluZS5pY2VQd2QgPSBpY2VQd2Q7XG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLmZpbmdlcnByaW50ID0gZmluZ2VycHJpbnQ7XG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLnBvcnQgPSBwb3J0O1xuXG4gICAgICAgICAgICAgICAgICAgIG1pZDJ1bFt1TGluZS5taWRdID0gdUxpbmU7XG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZXMydWxbdUlkeF0gPSB1TGluZS5zb3VyY2VzO1xuXG4gICAgICAgICAgICAgICAgICAgIHNlbGYuY2FjaGUubWxVMkJNYXBbdUlkeF0gPSBiSWR4O1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHNlbGYuY2FjaGUubWxCMlVNYXBbYklkeF0gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgc2VsZi5jYWNoZS5tbEIyVU1hcFtiSWR4XSA9IHVJZHg7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdUlkeCsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciB1TGluZSA9IGJMaW5lO1xuXG4gICAgICAgICAgdUxpbmUuY2FuZGlkYXRlcyA9IGNhbmRpZGF0ZXM7XG4gICAgICAgICAgdUxpbmUuaWNlVWZyYWcgPSBpY2VVZnJhZztcbiAgICAgICAgICB1TGluZS5pY2VQd2QgPSBpY2VQd2Q7XG4gICAgICAgICAgdUxpbmUuZmluZ2VycHJpbnQgPSBmaW5nZXJwcmludDtcbiAgICAgICAgICB1TGluZS5wb3J0ID0gcG9ydDtcblxuICAgICAgICAgIG1pZDJ1bFt1TGluZS5taWRdID0gdUxpbmU7XG5cbiAgICAgICAgICBzZWxmLmNhY2hlLm1sVTJCTWFwW3VJZHhdID0gYklkeDtcbiAgICAgICAgICBpZiAodHlwZW9mIHNlbGYuY2FjaGUubWxCMlVNYXBbYklkeF0gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBzZWxmLmNhY2hlLm1sQjJVTWFwW2JJZHhdID0gdUlkeDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBiSWR4Kys7XG4gICAgfSk7XG5cbiAgICAvLyBSZWJ1aWxkIHRoZSBtZWRpYSBhcnJheSBpbiB0aGUgcmlnaHQgb3JkZXIgYW5kIGFkZCB0aGUgbWlzc2luZyBtTGluZXNcbiAgICAvLyAobWlzc2luZyBmcm9tIHRoZSBQbGFuIEIgU0RQKS5cbiAgICBzZXNzaW9uLm1lZGlhID0gW107XG4gICAgbWlkcyA9IFtdOyAvLyByZXVzZVxuXG4gICAgaWYgKGRlc2MudHlwZSA9PT0gJ2Fuc3dlcicpIHtcblxuICAgICAgICAvLyBUaGUgbWVkaWEgbGluZXMgaW4gdGhlIGFuc3dlciBtdXN0IG1hdGNoIHRoZSBtZWRpYSBsaW5lcyBpbiB0aGVcbiAgICAgICAgLy8gb2ZmZXIuIFRoZSBvcmRlciBpcyBpbXBvcnRhbnQgdG9vLiBIZXJlIHdlIGFzc3VtZSB0aGF0IEZpcmVmb3ggaXNcbiAgICAgICAgLy8gdGhlIGFuc3dlcmVyLCBzbyB3ZSBtZXJlbHkgaGF2ZSB0byB1c2UgdGhlIHJlY29uc3RydWN0ZWQgKHVuaWZpZWQpXG4gICAgICAgIC8vIGFuc3dlciB0byB1cGRhdGUgdGhlIGNhY2hlZCAodW5pZmllZCkgYW5zd2VyIGFjY29yZGluZ2x5LlxuICAgICAgICAvL1xuICAgICAgICAvLyBJbiB0aGUgZ2VuZXJhbCBjYXNlLCBvbmUgd291bGQgaGF2ZSB0byB1c2UgdGhlIGNhY2hlZCAodW5pZmllZClcbiAgICAgICAgLy8gb2ZmZXIgdG8gZmluZCB0aGUgbS1saW5lcyB0aGF0IGFyZSBtaXNzaW5nIGZyb20gdGhlIHJlY29uc3RydWN0ZWRcbiAgICAgICAgLy8gYW5zd2VyLCBwb3RlbnRpYWxseSBncmFiYmluZyB0aGVtIGZyb20gdGhlIGNhY2hlZCAodW5pZmllZCkgYW5zd2VyLlxuICAgICAgICAvLyBPbmUgaGFzIHRvIGJlIGNhcmVmdWwgd2l0aCB0aGlzIGFwcHJvYWNoIGJlY2F1c2UgaW5hY3RpdmUgbS1saW5lcyBkb1xuICAgICAgICAvLyBub3QgYWx3YXlzIGhhdmUgYW4gbWlkLCBtYWtpbmcgaXQgdHJpY2t5IChpbXBvc3NpYmxlPykgdG8gZmluZCB3aGVyZVxuICAgICAgICAvLyBleGFjdGx5IGFuZCB3aGljaCBtLWxpbmVzIGFyZSBtaXNzaW5nIGZyb20gdGhlIHJlY29uc3RydWN0ZWQgYW5zd2VyLlxuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2FjaGVkLm1lZGlhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgdUxpbmUgPSBjYWNoZWQubWVkaWFbaV07XG5cbiAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5tc2lkO1xuICAgICAgICAgICAgZGVsZXRlIHVMaW5lLnNvdXJjZXM7XG4gICAgICAgICAgICBkZWxldGUgdUxpbmUuc3NyY0dyb3VwcztcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBzb3VyY2VzMnVsW2ldID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICBpZiAoIXVMaW5lLmRpcmVjdGlvblxuICAgICAgICAgICAgICAgICAgfHwgdUxpbmUuZGlyZWN0aW9uID09PSAnc2VuZHJlY3YnKVxuICAgICAgICAgICAgICAgICAgdUxpbmUuZGlyZWN0aW9uID0gJ3JlY3Zvbmx5JztcbiAgICAgICAgICAgICAgZWxzZSBpZiAodUxpbmUuZGlyZWN0aW9uID09PSAnc2VuZG9ubHknKVxuICAgICAgICAgICAgICAgICAgdUxpbmUuZGlyZWN0aW9uID0gJ2luYWN0aXZlJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGlmICghdUxpbmUuZGlyZWN0aW9uXG4gICAgICAgICAgICAgICAgICB8fCB1TGluZS5kaXJlY3Rpb24gPT09ICdzZW5kcmVjdicpXG4gICAgICAgICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gPSAnc2VuZHJlY3YnO1xuICAgICAgICAgICAgICBlbHNlIGlmICh1TGluZS5kaXJlY3Rpb24gPT09ICdyZWN2b25seScpXG4gICAgICAgICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gPSAnc2VuZG9ubHknO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB1TGluZS5zb3VyY2VzID0gc291cmNlczJ1bFtpXTtcbiAgICAgICAgICAgIHVMaW5lLmNhbmRpZGF0ZXMgPSBjYW5kaWRhdGVzO1xuICAgICAgICAgICAgdUxpbmUuaWNlVWZyYWcgPSBpY2VVZnJhZztcbiAgICAgICAgICAgIHVMaW5lLmljZVB3ZCA9IGljZVB3ZDtcbiAgICAgICAgICAgIHVMaW5lLmZpbmdlcnByaW50ID0gZmluZ2VycHJpbnQ7XG5cbiAgICAgICAgICAgIHVMaW5lLnJ0cCA9IHJ0cFt1TGluZS50eXBlXTtcbiAgICAgICAgICAgIHVMaW5lLnBheWxvYWRzID0gcGF5bG9hZHNbdUxpbmUudHlwZV07XG4gICAgICAgICAgICB1TGluZS5ydGNwRmIgPSBydGNwRmJbdUxpbmUudHlwZV07XG5cbiAgICAgICAgICAgIHNlc3Npb24ubWVkaWEucHVzaCh1TGluZSk7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdUxpbmUubWlkID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIC8vIGluYWN0aXZlIGxpbmVzIGRvbid0L21heSBub3QgaGF2ZSBhbiBtaWQuXG4gICAgICAgICAgICAgICAgbWlkcy5wdXNoKHVMaW5lLm1pZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuXG4gICAgICAgIC8vIFNEUCBvZmZlci9hbnN3ZXIgKGFuZCB0aGUgSlNFUCBzcGVjKSBmb3JiaWRzIHJlbW92aW5nIGFuIG0tc2VjdGlvblxuICAgICAgICAvLyB1bmRlciBhbnkgY2lyY3Vtc3RhbmNlcy4gSWYgd2UgYXJlIG5vIGxvbmdlciBpbnRlcmVzdGVkIGluIHNlbmRpbmcgYVxuICAgICAgICAvLyB0cmFjaywgd2UganVzdCByZW1vdmUgdGhlIG1zaWQgYW5kIHNzcmMgYXR0cmlidXRlcyBhbmQgc2V0IGl0IHRvXG4gICAgICAgIC8vIGVpdGhlciBhPXJlY3Zvbmx5IChhcyB0aGUgcmVvZmZlcmVyLCB3ZSBtdXN0IHVzZSByZWN2b25seSBpZiB0aGVcbiAgICAgICAgLy8gb3RoZXIgc2lkZSB3YXMgcHJldmlvdXNseSBzZW5kaW5nIG9uIHRoZSBtLXNlY3Rpb24sIGJ1dCB3ZSBjYW4gYWxzb1xuICAgICAgICAvLyBsZWF2ZSB0aGUgcG9zc2liaWxpdHkgb3BlbiBpZiBpdCB3YXNuJ3QgcHJldmlvdXNseSBpbiB1c2UpLCBvclxuICAgICAgICAvLyBhPWluYWN0aXZlLlxuXG4gICAgICAgIGlmICh0eXBlb2YgY2FjaGVkICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgdHlwZW9mIGNhY2hlZC5tZWRpYSAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgICAgIEFycmF5LmlzQXJyYXkoY2FjaGVkLm1lZGlhKSkge1xuICAgICAgICAgICAgY2FjaGVkLm1lZGlhLmZvckVhY2goZnVuY3Rpb24odUxpbmUpIHtcbiAgICAgICAgICAgICAgICBtaWRzLnB1c2godUxpbmUubWlkKTtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG1pZDJ1bFt1TGluZS5taWRdICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLm1lZGlhLnB1c2gobWlkMnVsW3VMaW5lLm1pZF0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5tc2lkO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdUxpbmUuc291cmNlcztcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHVMaW5lLnNzcmNHcm91cHM7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF1TGluZS5kaXJlY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgICAgIHx8IHVMaW5lLmRpcmVjdGlvbiA9PT0gJ3NlbmRyZWN2Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUuZGlyZWN0aW9uID0gJ3NlbmRvbmx5JztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoIXVMaW5lLmRpcmVjdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgfHwgdUxpbmUuZGlyZWN0aW9uID09PSAncmVjdm9ubHknKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gPSAnaW5hY3RpdmUnO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYWRkU2V0dXBBdHRyICh1TGluZSk7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWEucHVzaCh1TGluZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgYWxsIHRoZSByZW1haW5pbmcgKG5ldykgbS1saW5lcyBvZiB0aGUgdHJhbnNmb3JtZWQgU0RQLlxuICAgICAgICBPYmplY3Qua2V5cyhtaWQydWwpLmZvckVhY2goZnVuY3Rpb24obWlkKSB7XG4gICAgICAgICAgICBpZiAobWlkcy5pbmRleE9mKG1pZCkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgbWlkcy5wdXNoKG1pZCk7XG4gICAgICAgICAgICAgICAgaWYgKG1pZDJ1bFttaWRdLmRpcmVjdGlvbiA9PT0gJ3JlY3Zvbmx5Jykge1xuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIGEgcmVtb3RlIHJlY3Zvbmx5IGNoYW5uZWwuIEFkZCBpdHMgU1NSQyB0byB0aGVcbiAgICAgICAgICAgICAgICAgICAgLy8gYXBwcm9wcmlhdGUgc2VuZHJlY3Ygb3Igc2VuZG9ubHkgY2hhbm5lbC5cbiAgICAgICAgICAgICAgICAgICAgLy8gVE9ETyhncCkgd2hhdCBpZiB3ZSBkb24ndCBoYXZlIHNlbmRyZWN2L3NlbmRvbmx5XG4gICAgICAgICAgICAgICAgICAgIC8vIGNoYW5uZWw/XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvbmUgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLm1lZGlhLnNvbWUoZnVuY3Rpb24gKHVMaW5lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoKHVMaW5lLmRpcmVjdGlvbiA9PT0gJ3NlbmRyZWN2JyB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiA9PT0gJ3NlbmRvbmx5JykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1TGluZS50eXBlID09PSBtaWQydWxbbWlkXS50eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbWlkMnVsW21pZF0gc2hvdWxkbid0IGhhdmUgYW55IHNzcmMtZ3JvdXBzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmtleXMobWlkMnVsW21pZF0uc291cmNlcykuZm9yRWFjaChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gKHNzcmMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUuc291cmNlc1tzc3JjXSA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaWQydWxbbWlkXS5zb3VyY2VzW3NzcmNdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9uZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbi5tZWRpYS5wdXNoKG1pZDJ1bFttaWRdKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWEucHVzaChtaWQydWxbbWlkXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBBZnRlciB3ZSBoYXZlIGNvbnN0cnVjdGVkIHRoZSBQbGFuIFVuaWZpZWQgbS1saW5lcyB3ZSBjYW4gZmlndXJlIG91dFxuICAgIC8vIHdoZXJlIChpbiB3aGljaCBtLWxpbmUpIHRvIHBsYWNlIHRoZSAncmVjdm9ubHkgU1NSQ3MnLlxuICAgIC8vIE5vdGU6IHdlIGFzc3VtZSBoZXJlIHRoYXQgd2UgYXJlIHRoZSBhbnN3ZXJlciBpbiB0aGUgTy9BLCBzbyBhbnkgb2ZmZXJzXG4gICAgLy8gd2hpY2ggd2UgdHJhbnNsYXRlIGNvbWUgZnJvbSB0aGUgcmVtb3RlIHNpZGUsIHdoaWxlIGFuc3dlcnMgYXJlIGxvY2FsXG4gICAgLy8gKGFuZCBzbyBvdXIgbGFzdCBsb2NhbCBkZXNjcmlwdGlvbiBpcyBjYWNoZWQgYXMgYW4gJ2Fuc3dlcicpLlxuICAgIFtcImF1ZGlvXCIsIFwidmlkZW9cIl0uZm9yRWFjaChmdW5jdGlvbiAodHlwZSkge1xuICAgICAgICBpZiAoIXNlc3Npb24gfHwgIXNlc3Npb24ubWVkaWEgfHwgIUFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgdmFyIGlkeCA9IG51bGw7XG4gICAgICAgIGlmIChPYmplY3Qua2V5cyhyZWN2b25seVNzcmNzW3R5cGVdKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBpZHggPSBzZWxmLmdldEZpcnN0U2VuZGluZ0luZGV4RnJvbUFuc3dlcih0eXBlKTtcbiAgICAgICAgICAgIGlmIChpZHggPT09IG51bGwpe1xuICAgICAgICAgICAgICAgIC8vIElmIHRoaXMgaXMgdGhlIGZpcnN0IG9mZmVyIHdlIHJlY2VpdmUsIHdlIGRvbid0IGhhdmUgYVxuICAgICAgICAgICAgICAgIC8vIGNhY2hlZCBhbnN3ZXIuIEFzc3VtZSB0aGF0IHdlIHdpbGwgYmUgc2VuZGluZyBtZWRpYSB1c2luZ1xuICAgICAgICAgICAgICAgIC8vIHRoZSBmaXJzdCBtLWxpbmUgZm9yIGVhY2ggbWVkaWEgdHlwZS5cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2Vzc2lvbi5tZWRpYS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbi5tZWRpYVtpXS50eXBlID09PSB0eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZHggPSBpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaWR4ICYmIHNlc3Npb24ubWVkaWEubGVuZ3RoID4gaWR4KSB7XG4gICAgICAgICAgICB2YXIgbUxpbmUgPSBzZXNzaW9uLm1lZGlhW2lkeF07XG4gICAgICAgICAgICBPYmplY3Qua2V5cyhyZWN2b25seVNzcmNzW3R5cGVdKS5mb3JFYWNoKGZ1bmN0aW9uKHNzcmMpIHtcbiAgICAgICAgICAgICAgICBpZiAobUxpbmUuc291cmNlcyAmJiBtTGluZS5zb3VyY2VzW3NzcmNdKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcIlJlcGxhY2luZyBhbiBleGlzdGluZyBTU1JDLlwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCFtTGluZS5zb3VyY2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIG1MaW5lLnNvdXJjZXMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBtTGluZS5zb3VyY2VzW3NzcmNdID0gcmVjdm9ubHlTc3Jjc1t0eXBlXVtzc3JjXTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICBpZiAodHlwZW9mIHNlc3Npb24uZ3JvdXBzICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgLy8gV2UgcmVnZW5lcmF0ZSB0aGUgQlVORExFIGdyb3VwIChzaW5jZSB3ZSByZWdlbmVyYXRlZCB0aGUgbWlkcylcbiAgICAgIHNlc3Npb24uZ3JvdXBzLnNvbWUoZnVuY3Rpb24oZ3JvdXApIHtcblx0ICBpZiAoZ3JvdXAudHlwZSA9PT0gJ0JVTkRMRScpIHtcblx0ICAgICAgZ3JvdXAubWlkcyA9IG1pZHMuam9pbignICcpO1xuXHQgICAgICByZXR1cm4gdHJ1ZTtcblx0ICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBtc2lkIHNlbWFudGljXG4gICAgc2Vzc2lvbi5tc2lkU2VtYW50aWMgPSB7XG4gICAgICAgIHNlbWFudGljOiAnV01TJyxcbiAgICAgICAgdG9rZW46ICcqJ1xuICAgIH07XG5cbiAgICB2YXIgcmVzU3RyID0gdHJhbnNmb3JtLndyaXRlKHNlc3Npb24pO1xuXG4gICAgLy8gQ2FjaGUgdGhlIHRyYW5zZm9ybWVkIFNEUCAoVW5pZmllZCBQbGFuKSBmb3IgbGF0ZXIgcmUtdXNlIGluIHRoaXNcbiAgICAvLyBmdW5jdGlvbi5cbiAgICB0aGlzLmNhY2hlW2Rlc2MudHlwZV0gPSByZXNTdHI7XG5cbiAgICByZXR1cm4gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICAgIHR5cGU6IGRlc2MudHlwZSxcbiAgICAgICAgc2RwOiByZXNTdHJcbiAgICB9KTtcblxuICAgIC8vI2VuZHJlZ2lvblxufTtcbiIsIi8qIENvcHlyaWdodCBAIDIwMTUgQXRsYXNzaWFuIFB0eSBMdGRcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxudmFyIHRyYW5zZm9ybSA9IHJlcXVpcmUoJ3NkcC10cmFuc2Zvcm0nKTtcblxuZXhwb3J0cy53cml0ZSA9IGZ1bmN0aW9uKHNlc3Npb24sIG9wdHMpIHtcblxuICBpZiAodHlwZW9mIHNlc3Npb24gIT09ICd1bmRlZmluZWQnICYmXG4gICAgICB0eXBlb2Ygc2Vzc2lvbi5tZWRpYSAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkpIHtcblxuICAgIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbiAobUxpbmUpIHtcbiAgICAgIC8vIGV4cGFuZCBzb3VyY2VzIHRvIHNzcmNzXG4gICAgICBpZiAodHlwZW9mIG1MaW5lLnNvdXJjZXMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIE9iamVjdC5rZXlzKG1MaW5lLnNvdXJjZXMpLmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIG1MaW5lLnNzcmNzID0gW107XG4gICAgICAgICAgT2JqZWN0LmtleXMobUxpbmUuc291cmNlcykuZm9yRWFjaChmdW5jdGlvbiAoc3NyYykge1xuICAgICAgICAgICAgdmFyIHNvdXJjZSA9IG1MaW5lLnNvdXJjZXNbc3NyY107XG4gICAgICAgICAgICBPYmplY3Qua2V5cyhzb3VyY2UpLmZvckVhY2goZnVuY3Rpb24gKGF0dHJpYnV0ZSkge1xuICAgICAgICAgICAgICBtTGluZS5zc3Jjcy5wdXNoKHtcbiAgICAgICAgICAgICAgICBpZDogc3NyYyxcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGU6IGF0dHJpYnV0ZSxcbiAgICAgICAgICAgICAgICB2YWx1ZTogc291cmNlW2F0dHJpYnV0ZV1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBkZWxldGUgbUxpbmUuc291cmNlcztcbiAgICAgICAgfVxuXG4gICAgICAvLyBqb2luIHNzcmNzIGluIHNzcmMgZ3JvdXBzXG4gICAgICBpZiAodHlwZW9mIG1MaW5lLnNzcmNHcm91cHMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIEFycmF5LmlzQXJyYXkobUxpbmUuc3NyY0dyb3VwcykpIHtcbiAgICAgICAgICBtTGluZS5zc3JjR3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKHNzcmNHcm91cCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBzc3JjR3JvdXAuc3NyY3MgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICAgICAgQXJyYXkuaXNBcnJheShzc3JjR3JvdXAuc3NyY3MpKSB7XG4gICAgICAgICAgICAgIHNzcmNHcm91cC5zc3JjcyA9IHNzcmNHcm91cC5zc3Jjcy5qb2luKCcgJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8vIGpvaW4gZ3JvdXAgbWlkc1xuICBpZiAodHlwZW9mIHNlc3Npb24gIT09ICd1bmRlZmluZWQnICYmXG4gICAgICB0eXBlb2Ygc2Vzc2lvbi5ncm91cHMgIT09ICd1bmRlZmluZWQnICYmIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5ncm91cHMpKSB7XG5cbiAgICBzZXNzaW9uLmdyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uIChnKSB7XG4gICAgICBpZiAodHlwZW9mIGcubWlkcyAhPT0gJ3VuZGVmaW5lZCcgJiYgQXJyYXkuaXNBcnJheShnLm1pZHMpKSB7XG4gICAgICAgIGcubWlkcyA9IGcubWlkcy5qb2luKCcgJyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gdHJhbnNmb3JtLndyaXRlKHNlc3Npb24sIG9wdHMpO1xufTtcblxuZXhwb3J0cy5wYXJzZSA9IGZ1bmN0aW9uKHNkcCkge1xuICB2YXIgc2Vzc2lvbiA9IHRyYW5zZm9ybS5wYXJzZShzZHApO1xuXG4gIGlmICh0eXBlb2Ygc2Vzc2lvbiAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHNlc3Npb24ubWVkaWEgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICBBcnJheS5pc0FycmF5KHNlc3Npb24ubWVkaWEpKSB7XG5cbiAgICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24gKG1MaW5lKSB7XG4gICAgICAvLyBncm91cCBzb3VyY2VzIGF0dHJpYnV0ZXMgYnkgc3NyY1xuICAgICAgaWYgKHR5cGVvZiBtTGluZS5zc3JjcyAhPT0gJ3VuZGVmaW5lZCcgJiYgQXJyYXkuaXNBcnJheShtTGluZS5zc3JjcykpIHtcbiAgICAgICAgbUxpbmUuc291cmNlcyA9IHt9O1xuICAgICAgICBtTGluZS5zc3Jjcy5mb3JFYWNoKGZ1bmN0aW9uIChzc3JjKSB7XG4gICAgICAgICAgaWYgKCFtTGluZS5zb3VyY2VzW3NzcmMuaWRdKVxuICAgICAgICAgIG1MaW5lLnNvdXJjZXNbc3NyYy5pZF0gPSB7fTtcbiAgICAgICAgbUxpbmUuc291cmNlc1tzc3JjLmlkXVtzc3JjLmF0dHJpYnV0ZV0gPSBzc3JjLnZhbHVlO1xuICAgICAgICB9KTtcblxuICAgICAgICBkZWxldGUgbUxpbmUuc3NyY3M7XG4gICAgICB9XG5cbiAgICAgIC8vIHNwbGl0IHNzcmNzIGluIHNzcmMgZ3JvdXBzXG4gICAgICBpZiAodHlwZW9mIG1MaW5lLnNzcmNHcm91cHMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIEFycmF5LmlzQXJyYXkobUxpbmUuc3NyY0dyb3VwcykpIHtcbiAgICAgICAgICBtTGluZS5zc3JjR3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKHNzcmNHcm91cCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBzc3JjR3JvdXAuc3NyY3MgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIHNzcmNHcm91cC5zc3JjcyA9IHNzcmNHcm91cC5zc3Jjcy5zcGxpdCgnICcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSk7XG4gIH1cbiAgLy8gc3BsaXQgZ3JvdXAgbWlkc1xuICBpZiAodHlwZW9mIHNlc3Npb24gIT09ICd1bmRlZmluZWQnICYmXG4gICAgICB0eXBlb2Ygc2Vzc2lvbi5ncm91cHMgIT09ICd1bmRlZmluZWQnICYmIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5ncm91cHMpKSB7XG5cbiAgICBzZXNzaW9uLmdyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uIChnKSB7XG4gICAgICBpZiAodHlwZW9mIGcubWlkcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgZy5taWRzID0gZy5taWRzLnNwbGl0KCcgJyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gc2Vzc2lvbjtcbn07XG5cbiIsIiAvKiBlc2xpbnQtZW52IG5vZGUgKi9cbid1c2Ugc3RyaWN0JztcblxuLy8gU0RQIGhlbHBlcnMuXG52YXIgU0RQVXRpbHMgPSB7fTtcblxuLy8gR2VuZXJhdGUgYW4gYWxwaGFudW1lcmljIGlkZW50aWZpZXIgZm9yIGNuYW1lIG9yIG1pZHMuXG4vLyBUT0RPOiB1c2UgVVVJRHMgaW5zdGVhZD8gaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vamVkLzk4Mjg4M1xuU0RQVXRpbHMuZ2VuZXJhdGVJZGVudGlmaWVyID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zdWJzdHIoMiwgMTApO1xufTtcblxuLy8gVGhlIFJUQ1AgQ05BTUUgdXNlZCBieSBhbGwgcGVlcmNvbm5lY3Rpb25zIGZyb20gdGhlIHNhbWUgSlMuXG5TRFBVdGlscy5sb2NhbENOYW1lID0gU0RQVXRpbHMuZ2VuZXJhdGVJZGVudGlmaWVyKCk7XG5cbi8vIFNwbGl0cyBTRFAgaW50byBsaW5lcywgZGVhbGluZyB3aXRoIGJvdGggQ1JMRiBhbmQgTEYuXG5TRFBVdGlscy5zcGxpdExpbmVzID0gZnVuY3Rpb24oYmxvYikge1xuICByZXR1cm4gYmxvYi50cmltKCkuc3BsaXQoJ1xcbicpLm1hcChmdW5jdGlvbihsaW5lKSB7XG4gICAgcmV0dXJuIGxpbmUudHJpbSgpO1xuICB9KTtcbn07XG4vLyBTcGxpdHMgU0RQIGludG8gc2Vzc2lvbnBhcnQgYW5kIG1lZGlhc2VjdGlvbnMuIEVuc3VyZXMgQ1JMRi5cblNEUFV0aWxzLnNwbGl0U2VjdGlvbnMgPSBmdW5jdGlvbihibG9iKSB7XG4gIHZhciBwYXJ0cyA9IGJsb2Iuc3BsaXQoJ1xcbm09Jyk7XG4gIHJldHVybiBwYXJ0cy5tYXAoZnVuY3Rpb24ocGFydCwgaW5kZXgpIHtcbiAgICByZXR1cm4gKGluZGV4ID4gMCA/ICdtPScgKyBwYXJ0IDogcGFydCkudHJpbSgpICsgJ1xcclxcbic7XG4gIH0pO1xufTtcblxuLy8gcmV0dXJucyB0aGUgc2Vzc2lvbiBkZXNjcmlwdGlvbi5cblNEUFV0aWxzLmdldERlc2NyaXB0aW9uID0gZnVuY3Rpb24oYmxvYikge1xuICB2YXIgc2VjdGlvbnMgPSBTRFBVdGlscy5zcGxpdFNlY3Rpb25zKGJsb2IpO1xuICByZXR1cm4gc2VjdGlvbnMgJiYgc2VjdGlvbnNbMF07XG59O1xuXG4vLyByZXR1cm5zIHRoZSBpbmRpdmlkdWFsIG1lZGlhIHNlY3Rpb25zLlxuU0RQVXRpbHMuZ2V0TWVkaWFTZWN0aW9ucyA9IGZ1bmN0aW9uKGJsb2IpIHtcbiAgdmFyIHNlY3Rpb25zID0gU0RQVXRpbHMuc3BsaXRTZWN0aW9ucyhibG9iKTtcbiAgc2VjdGlvbnMuc2hpZnQoKTtcbiAgcmV0dXJuIHNlY3Rpb25zO1xufTtcblxuLy8gUmV0dXJucyBsaW5lcyB0aGF0IHN0YXJ0IHdpdGggYSBjZXJ0YWluIHByZWZpeC5cblNEUFV0aWxzLm1hdGNoUHJlZml4ID0gZnVuY3Rpb24oYmxvYiwgcHJlZml4KSB7XG4gIHJldHVybiBTRFBVdGlscy5zcGxpdExpbmVzKGJsb2IpLmZpbHRlcihmdW5jdGlvbihsaW5lKSB7XG4gICAgcmV0dXJuIGxpbmUuaW5kZXhPZihwcmVmaXgpID09PSAwO1xuICB9KTtcbn07XG5cbi8vIFBhcnNlcyBhbiBJQ0UgY2FuZGlkYXRlIGxpbmUuIFNhbXBsZSBpbnB1dDpcbi8vIGNhbmRpZGF0ZTo3MDI3ODYzNTAgMiB1ZHAgNDE4MTk5MDIgOC44LjguOCA2MDc2OSB0eXAgcmVsYXkgcmFkZHIgOC44LjguOFxuLy8gcnBvcnQgNTU5OTZcIlxuU0RQVXRpbHMucGFyc2VDYW5kaWRhdGUgPSBmdW5jdGlvbihsaW5lKSB7XG4gIHZhciBwYXJ0cztcbiAgLy8gUGFyc2UgYm90aCB2YXJpYW50cy5cbiAgaWYgKGxpbmUuaW5kZXhPZignYT1jYW5kaWRhdGU6JykgPT09IDApIHtcbiAgICBwYXJ0cyA9IGxpbmUuc3Vic3RyaW5nKDEyKS5zcGxpdCgnICcpO1xuICB9IGVsc2Uge1xuICAgIHBhcnRzID0gbGluZS5zdWJzdHJpbmcoMTApLnNwbGl0KCcgJyk7XG4gIH1cblxuICB2YXIgY2FuZGlkYXRlID0ge1xuICAgIGZvdW5kYXRpb246IHBhcnRzWzBdLFxuICAgIGNvbXBvbmVudDogcGFyc2VJbnQocGFydHNbMV0sIDEwKSxcbiAgICBwcm90b2NvbDogcGFydHNbMl0udG9Mb3dlckNhc2UoKSxcbiAgICBwcmlvcml0eTogcGFyc2VJbnQocGFydHNbM10sIDEwKSxcbiAgICBpcDogcGFydHNbNF0sXG4gICAgcG9ydDogcGFyc2VJbnQocGFydHNbNV0sIDEwKSxcbiAgICAvLyBza2lwIHBhcnRzWzZdID09ICd0eXAnXG4gICAgdHlwZTogcGFydHNbN11cbiAgfTtcblxuICBmb3IgKHZhciBpID0gODsgaSA8IHBhcnRzLmxlbmd0aDsgaSArPSAyKSB7XG4gICAgc3dpdGNoIChwYXJ0c1tpXSkge1xuICAgICAgY2FzZSAncmFkZHInOlxuICAgICAgICBjYW5kaWRhdGUucmVsYXRlZEFkZHJlc3MgPSBwYXJ0c1tpICsgMV07XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAncnBvcnQnOlxuICAgICAgICBjYW5kaWRhdGUucmVsYXRlZFBvcnQgPSBwYXJzZUludChwYXJ0c1tpICsgMV0sIDEwKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd0Y3B0eXBlJzpcbiAgICAgICAgY2FuZGlkYXRlLnRjcFR5cGUgPSBwYXJ0c1tpICsgMV07XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAndWZyYWcnOlxuICAgICAgICBjYW5kaWRhdGUudWZyYWcgPSBwYXJ0c1tpICsgMV07IC8vIGZvciBiYWNrd2FyZCBjb21wYWJpbGl0eS5cbiAgICAgICAgY2FuZGlkYXRlLnVzZXJuYW1lRnJhZ21lbnQgPSBwYXJ0c1tpICsgMV07XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDogLy8gZXh0ZW5zaW9uIGhhbmRsaW5nLCBpbiBwYXJ0aWN1bGFyIHVmcmFnXG4gICAgICAgIGNhbmRpZGF0ZVtwYXJ0c1tpXV0gPSBwYXJ0c1tpICsgMV07XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuICByZXR1cm4gY2FuZGlkYXRlO1xufTtcblxuLy8gVHJhbnNsYXRlcyBhIGNhbmRpZGF0ZSBvYmplY3QgaW50byBTRFAgY2FuZGlkYXRlIGF0dHJpYnV0ZS5cblNEUFV0aWxzLndyaXRlQ2FuZGlkYXRlID0gZnVuY3Rpb24oY2FuZGlkYXRlKSB7XG4gIHZhciBzZHAgPSBbXTtcbiAgc2RwLnB1c2goY2FuZGlkYXRlLmZvdW5kYXRpb24pO1xuICBzZHAucHVzaChjYW5kaWRhdGUuY29tcG9uZW50KTtcbiAgc2RwLnB1c2goY2FuZGlkYXRlLnByb3RvY29sLnRvVXBwZXJDYXNlKCkpO1xuICBzZHAucHVzaChjYW5kaWRhdGUucHJpb3JpdHkpO1xuICBzZHAucHVzaChjYW5kaWRhdGUuaXApO1xuICBzZHAucHVzaChjYW5kaWRhdGUucG9ydCk7XG5cbiAgdmFyIHR5cGUgPSBjYW5kaWRhdGUudHlwZTtcbiAgc2RwLnB1c2goJ3R5cCcpO1xuICBzZHAucHVzaCh0eXBlKTtcbiAgaWYgKHR5cGUgIT09ICdob3N0JyAmJiBjYW5kaWRhdGUucmVsYXRlZEFkZHJlc3MgJiZcbiAgICAgIGNhbmRpZGF0ZS5yZWxhdGVkUG9ydCkge1xuICAgIHNkcC5wdXNoKCdyYWRkcicpO1xuICAgIHNkcC5wdXNoKGNhbmRpZGF0ZS5yZWxhdGVkQWRkcmVzcyk7IC8vIHdhczogcmVsQWRkclxuICAgIHNkcC5wdXNoKCdycG9ydCcpO1xuICAgIHNkcC5wdXNoKGNhbmRpZGF0ZS5yZWxhdGVkUG9ydCk7IC8vIHdhczogcmVsUG9ydFxuICB9XG4gIGlmIChjYW5kaWRhdGUudGNwVHlwZSAmJiBjYW5kaWRhdGUucHJvdG9jb2wudG9Mb3dlckNhc2UoKSA9PT0gJ3RjcCcpIHtcbiAgICBzZHAucHVzaCgndGNwdHlwZScpO1xuICAgIHNkcC5wdXNoKGNhbmRpZGF0ZS50Y3BUeXBlKTtcbiAgfVxuICBpZiAoY2FuZGlkYXRlLnVzZXJuYW1lRnJhZ21lbnQgfHwgY2FuZGlkYXRlLnVmcmFnKSB7XG4gICAgc2RwLnB1c2goJ3VmcmFnJyk7XG4gICAgc2RwLnB1c2goY2FuZGlkYXRlLnVzZXJuYW1lRnJhZ21lbnQgfHwgY2FuZGlkYXRlLnVmcmFnKTtcbiAgfVxuICByZXR1cm4gJ2NhbmRpZGF0ZTonICsgc2RwLmpvaW4oJyAnKTtcbn07XG5cbi8vIFBhcnNlcyBhbiBpY2Utb3B0aW9ucyBsaW5lLCByZXR1cm5zIGFuIGFycmF5IG9mIG9wdGlvbiB0YWdzLlxuLy8gYT1pY2Utb3B0aW9uczpmb28gYmFyXG5TRFBVdGlscy5wYXJzZUljZU9wdGlvbnMgPSBmdW5jdGlvbihsaW5lKSB7XG4gIHJldHVybiBsaW5lLnN1YnN0cigxNCkuc3BsaXQoJyAnKTtcbn1cblxuLy8gUGFyc2VzIGFuIHJ0cG1hcCBsaW5lLCByZXR1cm5zIFJUQ1J0cENvZGRlY1BhcmFtZXRlcnMuIFNhbXBsZSBpbnB1dDpcbi8vIGE9cnRwbWFwOjExMSBvcHVzLzQ4MDAwLzJcblNEUFV0aWxzLnBhcnNlUnRwTWFwID0gZnVuY3Rpb24obGluZSkge1xuICB2YXIgcGFydHMgPSBsaW5lLnN1YnN0cig5KS5zcGxpdCgnICcpO1xuICB2YXIgcGFyc2VkID0ge1xuICAgIHBheWxvYWRUeXBlOiBwYXJzZUludChwYXJ0cy5zaGlmdCgpLCAxMCkgLy8gd2FzOiBpZFxuICB9O1xuXG4gIHBhcnRzID0gcGFydHNbMF0uc3BsaXQoJy8nKTtcblxuICBwYXJzZWQubmFtZSA9IHBhcnRzWzBdO1xuICBwYXJzZWQuY2xvY2tSYXRlID0gcGFyc2VJbnQocGFydHNbMV0sIDEwKTsgLy8gd2FzOiBjbG9ja3JhdGVcbiAgLy8gd2FzOiBjaGFubmVsc1xuICBwYXJzZWQubnVtQ2hhbm5lbHMgPSBwYXJ0cy5sZW5ndGggPT09IDMgPyBwYXJzZUludChwYXJ0c1syXSwgMTApIDogMTtcbiAgcmV0dXJuIHBhcnNlZDtcbn07XG5cbi8vIEdlbmVyYXRlIGFuIGE9cnRwbWFwIGxpbmUgZnJvbSBSVENSdHBDb2RlY0NhcGFiaWxpdHkgb3Jcbi8vIFJUQ1J0cENvZGVjUGFyYW1ldGVycy5cblNEUFV0aWxzLndyaXRlUnRwTWFwID0gZnVuY3Rpb24oY29kZWMpIHtcbiAgdmFyIHB0ID0gY29kZWMucGF5bG9hZFR5cGU7XG4gIGlmIChjb2RlYy5wcmVmZXJyZWRQYXlsb2FkVHlwZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcHQgPSBjb2RlYy5wcmVmZXJyZWRQYXlsb2FkVHlwZTtcbiAgfVxuICByZXR1cm4gJ2E9cnRwbWFwOicgKyBwdCArICcgJyArIGNvZGVjLm5hbWUgKyAnLycgKyBjb2RlYy5jbG9ja1JhdGUgK1xuICAgICAgKGNvZGVjLm51bUNoYW5uZWxzICE9PSAxID8gJy8nICsgY29kZWMubnVtQ2hhbm5lbHMgOiAnJykgKyAnXFxyXFxuJztcbn07XG5cbi8vIFBhcnNlcyBhbiBhPWV4dG1hcCBsaW5lIChoZWFkZXJleHRlbnNpb24gZnJvbSBSRkMgNTI4NSkuIFNhbXBsZSBpbnB1dDpcbi8vIGE9ZXh0bWFwOjIgdXJuOmlldGY6cGFyYW1zOnJ0cC1oZHJleHQ6dG9mZnNldFxuLy8gYT1leHRtYXA6Mi9zZW5kb25seSB1cm46aWV0ZjpwYXJhbXM6cnRwLWhkcmV4dDp0b2Zmc2V0XG5TRFBVdGlscy5wYXJzZUV4dG1hcCA9IGZ1bmN0aW9uKGxpbmUpIHtcbiAgdmFyIHBhcnRzID0gbGluZS5zdWJzdHIoOSkuc3BsaXQoJyAnKTtcbiAgcmV0dXJuIHtcbiAgICBpZDogcGFyc2VJbnQocGFydHNbMF0sIDEwKSxcbiAgICBkaXJlY3Rpb246IHBhcnRzWzBdLmluZGV4T2YoJy8nKSA+IDAgPyBwYXJ0c1swXS5zcGxpdCgnLycpWzFdIDogJ3NlbmRyZWN2JyxcbiAgICB1cmk6IHBhcnRzWzFdXG4gIH07XG59O1xuXG4vLyBHZW5lcmF0ZXMgYT1leHRtYXAgbGluZSBmcm9tIFJUQ1J0cEhlYWRlckV4dGVuc2lvblBhcmFtZXRlcnMgb3Jcbi8vIFJUQ1J0cEhlYWRlckV4dGVuc2lvbi5cblNEUFV0aWxzLndyaXRlRXh0bWFwID0gZnVuY3Rpb24oaGVhZGVyRXh0ZW5zaW9uKSB7XG4gIHJldHVybiAnYT1leHRtYXA6JyArIChoZWFkZXJFeHRlbnNpb24uaWQgfHwgaGVhZGVyRXh0ZW5zaW9uLnByZWZlcnJlZElkKSArXG4gICAgICAoaGVhZGVyRXh0ZW5zaW9uLmRpcmVjdGlvbiAmJiBoZWFkZXJFeHRlbnNpb24uZGlyZWN0aW9uICE9PSAnc2VuZHJlY3YnXG4gICAgICAgICAgPyAnLycgKyBoZWFkZXJFeHRlbnNpb24uZGlyZWN0aW9uXG4gICAgICAgICAgOiAnJykgK1xuICAgICAgJyAnICsgaGVhZGVyRXh0ZW5zaW9uLnVyaSArICdcXHJcXG4nO1xufTtcblxuLy8gUGFyc2VzIGFuIGZ0bXAgbGluZSwgcmV0dXJucyBkaWN0aW9uYXJ5LiBTYW1wbGUgaW5wdXQ6XG4vLyBhPWZtdHA6OTYgdmJyPW9uO2NuZz1vblxuLy8gQWxzbyBkZWFscyB3aXRoIHZicj1vbjsgY25nPW9uXG5TRFBVdGlscy5wYXJzZUZtdHAgPSBmdW5jdGlvbihsaW5lKSB7XG4gIHZhciBwYXJzZWQgPSB7fTtcbiAgdmFyIGt2O1xuICB2YXIgcGFydHMgPSBsaW5lLnN1YnN0cihsaW5lLmluZGV4T2YoJyAnKSArIDEpLnNwbGl0KCc7Jyk7XG4gIGZvciAodmFyIGogPSAwOyBqIDwgcGFydHMubGVuZ3RoOyBqKyspIHtcbiAgICBrdiA9IHBhcnRzW2pdLnRyaW0oKS5zcGxpdCgnPScpO1xuICAgIHBhcnNlZFtrdlswXS50cmltKCldID0ga3ZbMV07XG4gIH1cbiAgcmV0dXJuIHBhcnNlZDtcbn07XG5cbi8vIEdlbmVyYXRlcyBhbiBhPWZ0bXAgbGluZSBmcm9tIFJUQ1J0cENvZGVjQ2FwYWJpbGl0eSBvciBSVENSdHBDb2RlY1BhcmFtZXRlcnMuXG5TRFBVdGlscy53cml0ZUZtdHAgPSBmdW5jdGlvbihjb2RlYykge1xuICB2YXIgbGluZSA9ICcnO1xuICB2YXIgcHQgPSBjb2RlYy5wYXlsb2FkVHlwZTtcbiAgaWYgKGNvZGVjLnByZWZlcnJlZFBheWxvYWRUeXBlICE9PSB1bmRlZmluZWQpIHtcbiAgICBwdCA9IGNvZGVjLnByZWZlcnJlZFBheWxvYWRUeXBlO1xuICB9XG4gIGlmIChjb2RlYy5wYXJhbWV0ZXJzICYmIE9iamVjdC5rZXlzKGNvZGVjLnBhcmFtZXRlcnMpLmxlbmd0aCkge1xuICAgIHZhciBwYXJhbXMgPSBbXTtcbiAgICBPYmplY3Qua2V5cyhjb2RlYy5wYXJhbWV0ZXJzKS5mb3JFYWNoKGZ1bmN0aW9uKHBhcmFtKSB7XG4gICAgICBwYXJhbXMucHVzaChwYXJhbSArICc9JyArIGNvZGVjLnBhcmFtZXRlcnNbcGFyYW1dKTtcbiAgICB9KTtcbiAgICBsaW5lICs9ICdhPWZtdHA6JyArIHB0ICsgJyAnICsgcGFyYW1zLmpvaW4oJzsnKSArICdcXHJcXG4nO1xuICB9XG4gIHJldHVybiBsaW5lO1xufTtcblxuLy8gUGFyc2VzIGFuIHJ0Y3AtZmIgbGluZSwgcmV0dXJucyBSVENQUnRjcEZlZWRiYWNrIG9iamVjdC4gU2FtcGxlIGlucHV0OlxuLy8gYT1ydGNwLWZiOjk4IG5hY2sgcnBzaVxuU0RQVXRpbHMucGFyc2VSdGNwRmIgPSBmdW5jdGlvbihsaW5lKSB7XG4gIHZhciBwYXJ0cyA9IGxpbmUuc3Vic3RyKGxpbmUuaW5kZXhPZignICcpICsgMSkuc3BsaXQoJyAnKTtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBwYXJ0cy5zaGlmdCgpLFxuICAgIHBhcmFtZXRlcjogcGFydHMuam9pbignICcpXG4gIH07XG59O1xuLy8gR2VuZXJhdGUgYT1ydGNwLWZiIGxpbmVzIGZyb20gUlRDUnRwQ29kZWNDYXBhYmlsaXR5IG9yIFJUQ1J0cENvZGVjUGFyYW1ldGVycy5cblNEUFV0aWxzLndyaXRlUnRjcEZiID0gZnVuY3Rpb24oY29kZWMpIHtcbiAgdmFyIGxpbmVzID0gJyc7XG4gIHZhciBwdCA9IGNvZGVjLnBheWxvYWRUeXBlO1xuICBpZiAoY29kZWMucHJlZmVycmVkUGF5bG9hZFR5cGUgIT09IHVuZGVmaW5lZCkge1xuICAgIHB0ID0gY29kZWMucHJlZmVycmVkUGF5bG9hZFR5cGU7XG4gIH1cbiAgaWYgKGNvZGVjLnJ0Y3BGZWVkYmFjayAmJiBjb2RlYy5ydGNwRmVlZGJhY2subGVuZ3RoKSB7XG4gICAgLy8gRklYTUU6IHNwZWNpYWwgaGFuZGxpbmcgZm9yIHRyci1pbnQ/XG4gICAgY29kZWMucnRjcEZlZWRiYWNrLmZvckVhY2goZnVuY3Rpb24oZmIpIHtcbiAgICAgIGxpbmVzICs9ICdhPXJ0Y3AtZmI6JyArIHB0ICsgJyAnICsgZmIudHlwZSArXG4gICAgICAoZmIucGFyYW1ldGVyICYmIGZiLnBhcmFtZXRlci5sZW5ndGggPyAnICcgKyBmYi5wYXJhbWV0ZXIgOiAnJykgK1xuICAgICAgICAgICdcXHJcXG4nO1xuICAgIH0pO1xuICB9XG4gIHJldHVybiBsaW5lcztcbn07XG5cbi8vIFBhcnNlcyBhbiBSRkMgNTU3NiBzc3JjIG1lZGlhIGF0dHJpYnV0ZS4gU2FtcGxlIGlucHV0OlxuLy8gYT1zc3JjOjM3MzU5Mjg1NTkgY25hbWU6c29tZXRoaW5nXG5TRFBVdGlscy5wYXJzZVNzcmNNZWRpYSA9IGZ1bmN0aW9uKGxpbmUpIHtcbiAgdmFyIHNwID0gbGluZS5pbmRleE9mKCcgJyk7XG4gIHZhciBwYXJ0cyA9IHtcbiAgICBzc3JjOiBwYXJzZUludChsaW5lLnN1YnN0cig3LCBzcCAtIDcpLCAxMClcbiAgfTtcbiAgdmFyIGNvbG9uID0gbGluZS5pbmRleE9mKCc6Jywgc3ApO1xuICBpZiAoY29sb24gPiAtMSkge1xuICAgIHBhcnRzLmF0dHJpYnV0ZSA9IGxpbmUuc3Vic3RyKHNwICsgMSwgY29sb24gLSBzcCAtIDEpO1xuICAgIHBhcnRzLnZhbHVlID0gbGluZS5zdWJzdHIoY29sb24gKyAxKTtcbiAgfSBlbHNlIHtcbiAgICBwYXJ0cy5hdHRyaWJ1dGUgPSBsaW5lLnN1YnN0cihzcCArIDEpO1xuICB9XG4gIHJldHVybiBwYXJ0cztcbn07XG5cbi8vIEV4dHJhY3RzIHRoZSBNSUQgKFJGQyA1ODg4KSBmcm9tIGEgbWVkaWEgc2VjdGlvbi5cbi8vIHJldHVybnMgdGhlIE1JRCBvciB1bmRlZmluZWQgaWYgbm8gbWlkIGxpbmUgd2FzIGZvdW5kLlxuU0RQVXRpbHMuZ2V0TWlkID0gZnVuY3Rpb24obWVkaWFTZWN0aW9uKSB7XG4gIHZhciBtaWQgPSBTRFBVdGlscy5tYXRjaFByZWZpeChtZWRpYVNlY3Rpb24sICdhPW1pZDonKVswXTtcbiAgaWYgKG1pZCkge1xuICAgIHJldHVybiBtaWQuc3Vic3RyKDYpO1xuICB9XG59XG5cblNEUFV0aWxzLnBhcnNlRmluZ2VycHJpbnQgPSBmdW5jdGlvbihsaW5lKSB7XG4gIHZhciBwYXJ0cyA9IGxpbmUuc3Vic3RyKDE0KS5zcGxpdCgnICcpO1xuICByZXR1cm4ge1xuICAgIGFsZ29yaXRobTogcGFydHNbMF0udG9Mb3dlckNhc2UoKSwgLy8gYWxnb3JpdGhtIGlzIGNhc2Utc2Vuc2l0aXZlIGluIEVkZ2UuXG4gICAgdmFsdWU6IHBhcnRzWzFdXG4gIH07XG59O1xuXG4vLyBFeHRyYWN0cyBEVExTIHBhcmFtZXRlcnMgZnJvbSBTRFAgbWVkaWEgc2VjdGlvbiBvciBzZXNzaW9ucGFydC5cbi8vIEZJWE1FOiBmb3IgY29uc2lzdGVuY3kgd2l0aCBvdGhlciBmdW5jdGlvbnMgdGhpcyBzaG91bGQgb25seVxuLy8gICBnZXQgdGhlIGZpbmdlcnByaW50IGxpbmUgYXMgaW5wdXQuIFNlZSBhbHNvIGdldEljZVBhcmFtZXRlcnMuXG5TRFBVdGlscy5nZXREdGxzUGFyYW1ldGVycyA9IGZ1bmN0aW9uKG1lZGlhU2VjdGlvbiwgc2Vzc2lvbnBhcnQpIHtcbiAgdmFyIGxpbmVzID0gU0RQVXRpbHMubWF0Y2hQcmVmaXgobWVkaWFTZWN0aW9uICsgc2Vzc2lvbnBhcnQsXG4gICAgICAnYT1maW5nZXJwcmludDonKTtcbiAgLy8gTm90ZTogYT1zZXR1cCBsaW5lIGlzIGlnbm9yZWQgc2luY2Ugd2UgdXNlIHRoZSAnYXV0bycgcm9sZS5cbiAgLy8gTm90ZTI6ICdhbGdvcml0aG0nIGlzIG5vdCBjYXNlIHNlbnNpdGl2ZSBleGNlcHQgaW4gRWRnZS5cbiAgcmV0dXJuIHtcbiAgICByb2xlOiAnYXV0bycsXG4gICAgZmluZ2VycHJpbnRzOiBsaW5lcy5tYXAoU0RQVXRpbHMucGFyc2VGaW5nZXJwcmludClcbiAgfTtcbn07XG5cbi8vIFNlcmlhbGl6ZXMgRFRMUyBwYXJhbWV0ZXJzIHRvIFNEUC5cblNEUFV0aWxzLndyaXRlRHRsc1BhcmFtZXRlcnMgPSBmdW5jdGlvbihwYXJhbXMsIHNldHVwVHlwZSkge1xuICB2YXIgc2RwID0gJ2E9c2V0dXA6JyArIHNldHVwVHlwZSArICdcXHJcXG4nO1xuICBwYXJhbXMuZmluZ2VycHJpbnRzLmZvckVhY2goZnVuY3Rpb24oZnApIHtcbiAgICBzZHAgKz0gJ2E9ZmluZ2VycHJpbnQ6JyArIGZwLmFsZ29yaXRobSArICcgJyArIGZwLnZhbHVlICsgJ1xcclxcbic7XG4gIH0pO1xuICByZXR1cm4gc2RwO1xufTtcbi8vIFBhcnNlcyBJQ0UgaW5mb3JtYXRpb24gZnJvbSBTRFAgbWVkaWEgc2VjdGlvbiBvciBzZXNzaW9ucGFydC5cbi8vIEZJWE1FOiBmb3IgY29uc2lzdGVuY3kgd2l0aCBvdGhlciBmdW5jdGlvbnMgdGhpcyBzaG91bGQgb25seVxuLy8gICBnZXQgdGhlIGljZS11ZnJhZyBhbmQgaWNlLXB3ZCBsaW5lcyBhcyBpbnB1dC5cblNEUFV0aWxzLmdldEljZVBhcmFtZXRlcnMgPSBmdW5jdGlvbihtZWRpYVNlY3Rpb24sIHNlc3Npb25wYXJ0KSB7XG4gIHZhciBsaW5lcyA9IFNEUFV0aWxzLnNwbGl0TGluZXMobWVkaWFTZWN0aW9uKTtcbiAgLy8gU2VhcmNoIGluIHNlc3Npb24gcGFydCwgdG9vLlxuICBsaW5lcyA9IGxpbmVzLmNvbmNhdChTRFBVdGlscy5zcGxpdExpbmVzKHNlc3Npb25wYXJ0KSk7XG4gIHZhciBpY2VQYXJhbWV0ZXJzID0ge1xuICAgIHVzZXJuYW1lRnJhZ21lbnQ6IGxpbmVzLmZpbHRlcihmdW5jdGlvbihsaW5lKSB7XG4gICAgICByZXR1cm4gbGluZS5pbmRleE9mKCdhPWljZS11ZnJhZzonKSA9PT0gMDtcbiAgICB9KVswXS5zdWJzdHIoMTIpLFxuICAgIHBhc3N3b3JkOiBsaW5lcy5maWx0ZXIoZnVuY3Rpb24obGluZSkge1xuICAgICAgcmV0dXJuIGxpbmUuaW5kZXhPZignYT1pY2UtcHdkOicpID09PSAwO1xuICAgIH0pWzBdLnN1YnN0cigxMClcbiAgfTtcbiAgcmV0dXJuIGljZVBhcmFtZXRlcnM7XG59O1xuXG4vLyBTZXJpYWxpemVzIElDRSBwYXJhbWV0ZXJzIHRvIFNEUC5cblNEUFV0aWxzLndyaXRlSWNlUGFyYW1ldGVycyA9IGZ1bmN0aW9uKHBhcmFtcykge1xuICByZXR1cm4gJ2E9aWNlLXVmcmFnOicgKyBwYXJhbXMudXNlcm5hbWVGcmFnbWVudCArICdcXHJcXG4nICtcbiAgICAgICdhPWljZS1wd2Q6JyArIHBhcmFtcy5wYXNzd29yZCArICdcXHJcXG4nO1xufTtcblxuLy8gUGFyc2VzIHRoZSBTRFAgbWVkaWEgc2VjdGlvbiBhbmQgcmV0dXJucyBSVENSdHBQYXJhbWV0ZXJzLlxuU0RQVXRpbHMucGFyc2VSdHBQYXJhbWV0ZXJzID0gZnVuY3Rpb24obWVkaWFTZWN0aW9uKSB7XG4gIHZhciBkZXNjcmlwdGlvbiA9IHtcbiAgICBjb2RlY3M6IFtdLFxuICAgIGhlYWRlckV4dGVuc2lvbnM6IFtdLFxuICAgIGZlY01lY2hhbmlzbXM6IFtdLFxuICAgIHJ0Y3A6IFtdXG4gIH07XG4gIHZhciBsaW5lcyA9IFNEUFV0aWxzLnNwbGl0TGluZXMobWVkaWFTZWN0aW9uKTtcbiAgdmFyIG1saW5lID0gbGluZXNbMF0uc3BsaXQoJyAnKTtcbiAgZm9yICh2YXIgaSA9IDM7IGkgPCBtbGluZS5sZW5ndGg7IGkrKykgeyAvLyBmaW5kIGFsbCBjb2RlY3MgZnJvbSBtbGluZVszLi5dXG4gICAgdmFyIHB0ID0gbWxpbmVbaV07XG4gICAgdmFyIHJ0cG1hcGxpbmUgPSBTRFBVdGlscy5tYXRjaFByZWZpeChcbiAgICAgICAgbWVkaWFTZWN0aW9uLCAnYT1ydHBtYXA6JyArIHB0ICsgJyAnKVswXTtcbiAgICBpZiAocnRwbWFwbGluZSkge1xuICAgICAgdmFyIGNvZGVjID0gU0RQVXRpbHMucGFyc2VSdHBNYXAocnRwbWFwbGluZSk7XG4gICAgICB2YXIgZm10cHMgPSBTRFBVdGlscy5tYXRjaFByZWZpeChcbiAgICAgICAgICBtZWRpYVNlY3Rpb24sICdhPWZtdHA6JyArIHB0ICsgJyAnKTtcbiAgICAgIC8vIE9ubHkgdGhlIGZpcnN0IGE9Zm10cDo8cHQ+IGlzIGNvbnNpZGVyZWQuXG4gICAgICBjb2RlYy5wYXJhbWV0ZXJzID0gZm10cHMubGVuZ3RoID8gU0RQVXRpbHMucGFyc2VGbXRwKGZtdHBzWzBdKSA6IHt9O1xuICAgICAgY29kZWMucnRjcEZlZWRiYWNrID0gU0RQVXRpbHMubWF0Y2hQcmVmaXgoXG4gICAgICAgICAgbWVkaWFTZWN0aW9uLCAnYT1ydGNwLWZiOicgKyBwdCArICcgJylcbiAgICAgICAgLm1hcChTRFBVdGlscy5wYXJzZVJ0Y3BGYik7XG4gICAgICBkZXNjcmlwdGlvbi5jb2RlY3MucHVzaChjb2RlYyk7XG4gICAgICAvLyBwYXJzZSBGRUMgbWVjaGFuaXNtcyBmcm9tIHJ0cG1hcCBsaW5lcy5cbiAgICAgIHN3aXRjaCAoY29kZWMubmFtZS50b1VwcGVyQ2FzZSgpKSB7XG4gICAgICAgIGNhc2UgJ1JFRCc6XG4gICAgICAgIGNhc2UgJ1VMUEZFQyc6XG4gICAgICAgICAgZGVzY3JpcHRpb24uZmVjTWVjaGFuaXNtcy5wdXNoKGNvZGVjLm5hbWUudG9VcHBlckNhc2UoKSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6IC8vIG9ubHkgUkVEIGFuZCBVTFBGRUMgYXJlIHJlY29nbml6ZWQgYXMgRkVDIG1lY2hhbmlzbXMuXG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIFNEUFV0aWxzLm1hdGNoUHJlZml4KG1lZGlhU2VjdGlvbiwgJ2E9ZXh0bWFwOicpLmZvckVhY2goZnVuY3Rpb24obGluZSkge1xuICAgIGRlc2NyaXB0aW9uLmhlYWRlckV4dGVuc2lvbnMucHVzaChTRFBVdGlscy5wYXJzZUV4dG1hcChsaW5lKSk7XG4gIH0pO1xuICAvLyBGSVhNRTogcGFyc2UgcnRjcC5cbiAgcmV0dXJuIGRlc2NyaXB0aW9uO1xufTtcblxuLy8gR2VuZXJhdGVzIHBhcnRzIG9mIHRoZSBTRFAgbWVkaWEgc2VjdGlvbiBkZXNjcmliaW5nIHRoZSBjYXBhYmlsaXRpZXMgL1xuLy8gcGFyYW1ldGVycy5cblNEUFV0aWxzLndyaXRlUnRwRGVzY3JpcHRpb24gPSBmdW5jdGlvbihraW5kLCBjYXBzKSB7XG4gIHZhciBzZHAgPSAnJztcblxuICAvLyBCdWlsZCB0aGUgbWxpbmUuXG4gIHNkcCArPSAnbT0nICsga2luZCArICcgJztcbiAgc2RwICs9IGNhcHMuY29kZWNzLmxlbmd0aCA+IDAgPyAnOScgOiAnMCc7IC8vIHJlamVjdCBpZiBubyBjb2RlY3MuXG4gIHNkcCArPSAnIFVEUC9UTFMvUlRQL1NBVlBGICc7XG4gIHNkcCArPSBjYXBzLmNvZGVjcy5tYXAoZnVuY3Rpb24oY29kZWMpIHtcbiAgICBpZiAoY29kZWMucHJlZmVycmVkUGF5bG9hZFR5cGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIGNvZGVjLnByZWZlcnJlZFBheWxvYWRUeXBlO1xuICAgIH1cbiAgICByZXR1cm4gY29kZWMucGF5bG9hZFR5cGU7XG4gIH0pLmpvaW4oJyAnKSArICdcXHJcXG4nO1xuXG4gIHNkcCArPSAnYz1JTiBJUDQgMC4wLjAuMFxcclxcbic7XG4gIHNkcCArPSAnYT1ydGNwOjkgSU4gSVA0IDAuMC4wLjBcXHJcXG4nO1xuXG4gIC8vIEFkZCBhPXJ0cG1hcCBsaW5lcyBmb3IgZWFjaCBjb2RlYy4gQWxzbyBmbXRwIGFuZCBydGNwLWZiLlxuICBjYXBzLmNvZGVjcy5mb3JFYWNoKGZ1bmN0aW9uKGNvZGVjKSB7XG4gICAgc2RwICs9IFNEUFV0aWxzLndyaXRlUnRwTWFwKGNvZGVjKTtcbiAgICBzZHAgKz0gU0RQVXRpbHMud3JpdGVGbXRwKGNvZGVjKTtcbiAgICBzZHAgKz0gU0RQVXRpbHMud3JpdGVSdGNwRmIoY29kZWMpO1xuICB9KTtcbiAgdmFyIG1heHB0aW1lID0gMDtcbiAgY2Fwcy5jb2RlY3MuZm9yRWFjaChmdW5jdGlvbihjb2RlYykge1xuICAgIGlmIChjb2RlYy5tYXhwdGltZSA+IG1heHB0aW1lKSB7XG4gICAgICBtYXhwdGltZSA9IGNvZGVjLm1heHB0aW1lO1xuICAgIH1cbiAgfSk7XG4gIGlmIChtYXhwdGltZSA+IDApIHtcbiAgICBzZHAgKz0gJ2E9bWF4cHRpbWU6JyArIG1heHB0aW1lICsgJ1xcclxcbic7XG4gIH1cbiAgc2RwICs9ICdhPXJ0Y3AtbXV4XFxyXFxuJztcblxuICBjYXBzLmhlYWRlckV4dGVuc2lvbnMuZm9yRWFjaChmdW5jdGlvbihleHRlbnNpb24pIHtcbiAgICBzZHAgKz0gU0RQVXRpbHMud3JpdGVFeHRtYXAoZXh0ZW5zaW9uKTtcbiAgfSk7XG4gIC8vIEZJWE1FOiB3cml0ZSBmZWNNZWNoYW5pc21zLlxuICByZXR1cm4gc2RwO1xufTtcblxuLy8gUGFyc2VzIHRoZSBTRFAgbWVkaWEgc2VjdGlvbiBhbmQgcmV0dXJucyBhbiBhcnJheSBvZlxuLy8gUlRDUnRwRW5jb2RpbmdQYXJhbWV0ZXJzLlxuU0RQVXRpbHMucGFyc2VSdHBFbmNvZGluZ1BhcmFtZXRlcnMgPSBmdW5jdGlvbihtZWRpYVNlY3Rpb24pIHtcbiAgdmFyIGVuY29kaW5nUGFyYW1ldGVycyA9IFtdO1xuICB2YXIgZGVzY3JpcHRpb24gPSBTRFBVdGlscy5wYXJzZVJ0cFBhcmFtZXRlcnMobWVkaWFTZWN0aW9uKTtcbiAgdmFyIGhhc1JlZCA9IGRlc2NyaXB0aW9uLmZlY01lY2hhbmlzbXMuaW5kZXhPZignUkVEJykgIT09IC0xO1xuICB2YXIgaGFzVWxwZmVjID0gZGVzY3JpcHRpb24uZmVjTWVjaGFuaXNtcy5pbmRleE9mKCdVTFBGRUMnKSAhPT0gLTE7XG5cbiAgLy8gZmlsdGVyIGE9c3NyYzouLi4gY25hbWU6LCBpZ25vcmUgUGxhbkItbXNpZFxuICB2YXIgc3NyY3MgPSBTRFBVdGlscy5tYXRjaFByZWZpeChtZWRpYVNlY3Rpb24sICdhPXNzcmM6JylcbiAgLm1hcChmdW5jdGlvbihsaW5lKSB7XG4gICAgcmV0dXJuIFNEUFV0aWxzLnBhcnNlU3NyY01lZGlhKGxpbmUpO1xuICB9KVxuICAuZmlsdGVyKGZ1bmN0aW9uKHBhcnRzKSB7XG4gICAgcmV0dXJuIHBhcnRzLmF0dHJpYnV0ZSA9PT0gJ2NuYW1lJztcbiAgfSk7XG4gIHZhciBwcmltYXJ5U3NyYyA9IHNzcmNzLmxlbmd0aCA+IDAgJiYgc3NyY3NbMF0uc3NyYztcbiAgdmFyIHNlY29uZGFyeVNzcmM7XG5cbiAgdmFyIGZsb3dzID0gU0RQVXRpbHMubWF0Y2hQcmVmaXgobWVkaWFTZWN0aW9uLCAnYT1zc3JjLWdyb3VwOkZJRCcpXG4gIC5tYXAoZnVuY3Rpb24obGluZSkge1xuICAgIHZhciBwYXJ0cyA9IGxpbmUuc3BsaXQoJyAnKTtcbiAgICBwYXJ0cy5zaGlmdCgpO1xuICAgIHJldHVybiBwYXJ0cy5tYXAoZnVuY3Rpb24ocGFydCkge1xuICAgICAgcmV0dXJuIHBhcnNlSW50KHBhcnQsIDEwKTtcbiAgICB9KTtcbiAgfSk7XG4gIGlmIChmbG93cy5sZW5ndGggPiAwICYmIGZsb3dzWzBdLmxlbmd0aCA+IDEgJiYgZmxvd3NbMF1bMF0gPT09IHByaW1hcnlTc3JjKSB7XG4gICAgc2Vjb25kYXJ5U3NyYyA9IGZsb3dzWzBdWzFdO1xuICB9XG5cbiAgZGVzY3JpcHRpb24uY29kZWNzLmZvckVhY2goZnVuY3Rpb24oY29kZWMpIHtcbiAgICBpZiAoY29kZWMubmFtZS50b1VwcGVyQ2FzZSgpID09PSAnUlRYJyAmJiBjb2RlYy5wYXJhbWV0ZXJzLmFwdCkge1xuICAgICAgdmFyIGVuY1BhcmFtID0ge1xuICAgICAgICBzc3JjOiBwcmltYXJ5U3NyYyxcbiAgICAgICAgY29kZWNQYXlsb2FkVHlwZTogcGFyc2VJbnQoY29kZWMucGFyYW1ldGVycy5hcHQsIDEwKSxcbiAgICAgICAgcnR4OiB7XG4gICAgICAgICAgc3NyYzogc2Vjb25kYXJ5U3NyY1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgZW5jb2RpbmdQYXJhbWV0ZXJzLnB1c2goZW5jUGFyYW0pO1xuICAgICAgaWYgKGhhc1JlZCkge1xuICAgICAgICBlbmNQYXJhbSA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoZW5jUGFyYW0pKTtcbiAgICAgICAgZW5jUGFyYW0uZmVjID0ge1xuICAgICAgICAgIHNzcmM6IHNlY29uZGFyeVNzcmMsXG4gICAgICAgICAgbWVjaGFuaXNtOiBoYXNVbHBmZWMgPyAncmVkK3VscGZlYycgOiAncmVkJ1xuICAgICAgICB9O1xuICAgICAgICBlbmNvZGluZ1BhcmFtZXRlcnMucHVzaChlbmNQYXJhbSk7XG4gICAgICB9XG4gICAgfVxuICB9KTtcbiAgaWYgKGVuY29kaW5nUGFyYW1ldGVycy5sZW5ndGggPT09IDAgJiYgcHJpbWFyeVNzcmMpIHtcbiAgICBlbmNvZGluZ1BhcmFtZXRlcnMucHVzaCh7XG4gICAgICBzc3JjOiBwcmltYXJ5U3NyY1xuICAgIH0pO1xuICB9XG5cbiAgLy8gd2Ugc3VwcG9ydCBib3RoIGI9QVMgYW5kIGI9VElBUyBidXQgaW50ZXJwcmV0IEFTIGFzIFRJQVMuXG4gIHZhciBiYW5kd2lkdGggPSBTRFBVdGlscy5tYXRjaFByZWZpeChtZWRpYVNlY3Rpb24sICdiPScpO1xuICBpZiAoYmFuZHdpZHRoLmxlbmd0aCkge1xuICAgIGlmIChiYW5kd2lkdGhbMF0uaW5kZXhPZignYj1USUFTOicpID09PSAwKSB7XG4gICAgICBiYW5kd2lkdGggPSBwYXJzZUludChiYW5kd2lkdGhbMF0uc3Vic3RyKDcpLCAxMCk7XG4gICAgfSBlbHNlIGlmIChiYW5kd2lkdGhbMF0uaW5kZXhPZignYj1BUzonKSA9PT0gMCkge1xuICAgICAgLy8gdXNlIGZvcm11bGEgZnJvbSBKU0VQIHRvIGNvbnZlcnQgYj1BUyB0byBUSUFTIHZhbHVlLlxuICAgICAgYmFuZHdpZHRoID0gcGFyc2VJbnQoYmFuZHdpZHRoWzBdLnN1YnN0cig1KSwgMTApICogMTAwMCAqIDAuOTVcbiAgICAgICAgICAtICg1MCAqIDQwICogOCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGJhbmR3aWR0aCA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgZW5jb2RpbmdQYXJhbWV0ZXJzLmZvckVhY2goZnVuY3Rpb24ocGFyYW1zKSB7XG4gICAgICBwYXJhbXMubWF4Qml0cmF0ZSA9IGJhbmR3aWR0aDtcbiAgICB9KTtcbiAgfVxuICByZXR1cm4gZW5jb2RpbmdQYXJhbWV0ZXJzO1xufTtcblxuLy8gcGFyc2VzIGh0dHA6Ly9kcmFmdC5vcnRjLm9yZy8jcnRjcnRjcHBhcmFtZXRlcnMqXG5TRFBVdGlscy5wYXJzZVJ0Y3BQYXJhbWV0ZXJzID0gZnVuY3Rpb24obWVkaWFTZWN0aW9uKSB7XG4gIHZhciBydGNwUGFyYW1ldGVycyA9IHt9O1xuXG4gIHZhciBjbmFtZTtcbiAgLy8gR2V0cyB0aGUgZmlyc3QgU1NSQy4gTm90ZSB0aGF0IHdpdGggUlRYIHRoZXJlIG1pZ2h0IGJlIG11bHRpcGxlXG4gIC8vIFNTUkNzLlxuICB2YXIgcmVtb3RlU3NyYyA9IFNEUFV0aWxzLm1hdGNoUHJlZml4KG1lZGlhU2VjdGlvbiwgJ2E9c3NyYzonKVxuICAgICAgLm1hcChmdW5jdGlvbihsaW5lKSB7XG4gICAgICAgIHJldHVybiBTRFBVdGlscy5wYXJzZVNzcmNNZWRpYShsaW5lKTtcbiAgICAgIH0pXG4gICAgICAuZmlsdGVyKGZ1bmN0aW9uKG9iaikge1xuICAgICAgICByZXR1cm4gb2JqLmF0dHJpYnV0ZSA9PT0gJ2NuYW1lJztcbiAgICAgIH0pWzBdO1xuICBpZiAocmVtb3RlU3NyYykge1xuICAgIHJ0Y3BQYXJhbWV0ZXJzLmNuYW1lID0gcmVtb3RlU3NyYy52YWx1ZTtcbiAgICBydGNwUGFyYW1ldGVycy5zc3JjID0gcmVtb3RlU3NyYy5zc3JjO1xuICB9XG5cbiAgLy8gRWRnZSB1c2VzIHRoZSBjb21wb3VuZCBhdHRyaWJ1dGUgaW5zdGVhZCBvZiByZWR1Y2VkU2l6ZVxuICAvLyBjb21wb3VuZCBpcyAhcmVkdWNlZFNpemVcbiAgdmFyIHJzaXplID0gU0RQVXRpbHMubWF0Y2hQcmVmaXgobWVkaWFTZWN0aW9uLCAnYT1ydGNwLXJzaXplJyk7XG4gIHJ0Y3BQYXJhbWV0ZXJzLnJlZHVjZWRTaXplID0gcnNpemUubGVuZ3RoID4gMDtcbiAgcnRjcFBhcmFtZXRlcnMuY29tcG91bmQgPSByc2l6ZS5sZW5ndGggPT09IDA7XG5cbiAgLy8gcGFyc2VzIHRoZSBydGNwLW11eCBhdHRy0ZZidXRlLlxuICAvLyBOb3RlIHRoYXQgRWRnZSBkb2VzIG5vdCBzdXBwb3J0IHVubXV4ZWQgUlRDUC5cbiAgdmFyIG11eCA9IFNEUFV0aWxzLm1hdGNoUHJlZml4KG1lZGlhU2VjdGlvbiwgJ2E9cnRjcC1tdXgnKTtcbiAgcnRjcFBhcmFtZXRlcnMubXV4ID0gbXV4Lmxlbmd0aCA+IDA7XG5cbiAgcmV0dXJuIHJ0Y3BQYXJhbWV0ZXJzO1xufTtcblxuLy8gcGFyc2VzIGVpdGhlciBhPW1zaWQ6IG9yIGE9c3NyYzouLi4gbXNpZCBsaW5lcyBhbmQgcmV0dXJuc1xuLy8gdGhlIGlkIG9mIHRoZSBNZWRpYVN0cmVhbSBhbmQgTWVkaWFTdHJlYW1UcmFjay5cblNEUFV0aWxzLnBhcnNlTXNpZCA9IGZ1bmN0aW9uKG1lZGlhU2VjdGlvbikge1xuICB2YXIgcGFydHM7XG4gIHZhciBzcGVjID0gU0RQVXRpbHMubWF0Y2hQcmVmaXgobWVkaWFTZWN0aW9uLCAnYT1tc2lkOicpO1xuICBpZiAoc3BlYy5sZW5ndGggPT09IDEpIHtcbiAgICBwYXJ0cyA9IHNwZWNbMF0uc3Vic3RyKDcpLnNwbGl0KCcgJyk7XG4gICAgcmV0dXJuIHtzdHJlYW06IHBhcnRzWzBdLCB0cmFjazogcGFydHNbMV19O1xuICB9XG4gIHZhciBwbGFuQiA9IFNEUFV0aWxzLm1hdGNoUHJlZml4KG1lZGlhU2VjdGlvbiwgJ2E9c3NyYzonKVxuICAubWFwKGZ1bmN0aW9uKGxpbmUpIHtcbiAgICByZXR1cm4gU0RQVXRpbHMucGFyc2VTc3JjTWVkaWEobGluZSk7XG4gIH0pXG4gIC5maWx0ZXIoZnVuY3Rpb24ocGFydHMpIHtcbiAgICByZXR1cm4gcGFydHMuYXR0cmlidXRlID09PSAnbXNpZCc7XG4gIH0pO1xuICBpZiAocGxhbkIubGVuZ3RoID4gMCkge1xuICAgIHBhcnRzID0gcGxhbkJbMF0udmFsdWUuc3BsaXQoJyAnKTtcbiAgICByZXR1cm4ge3N0cmVhbTogcGFydHNbMF0sIHRyYWNrOiBwYXJ0c1sxXX07XG4gIH1cbn07XG5cbi8vIEdlbmVyYXRlIGEgc2Vzc2lvbiBJRCBmb3IgU0RQLlxuLy8gaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL2RyYWZ0LWlldGYtcnRjd2ViLWpzZXAtMjAjc2VjdGlvbi01LjIuMVxuLy8gcmVjb21tZW5kcyB1c2luZyBhIGNyeXB0b2dyYXBoaWNhbGx5IHJhbmRvbSArdmUgNjQtYml0IHZhbHVlXG4vLyBidXQgcmlnaHQgbm93IHRoaXMgc2hvdWxkIGJlIGFjY2VwdGFibGUgYW5kIHdpdGhpbiB0aGUgcmlnaHQgcmFuZ2VcblNEUFV0aWxzLmdlbmVyYXRlU2Vzc2lvbklkID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKCkuc3Vic3RyKDIsIDIxKTtcbn07XG5cbi8vIFdyaXRlIGJvaWxkZXIgcGxhdGUgZm9yIHN0YXJ0IG9mIFNEUFxuLy8gc2Vzc0lkIGFyZ3VtZW50IGlzIG9wdGlvbmFsIC0gaWYgbm90IHN1cHBsaWVkIGl0IHdpbGxcbi8vIGJlIGdlbmVyYXRlZCByYW5kb21seVxuLy8gc2Vzc1ZlcnNpb24gaXMgb3B0aW9uYWwgYW5kIGRlZmF1bHRzIHRvIDJcblNEUFV0aWxzLndyaXRlU2Vzc2lvbkJvaWxlcnBsYXRlID0gZnVuY3Rpb24oc2Vzc0lkLCBzZXNzVmVyKSB7XG4gIHZhciBzZXNzaW9uSWQ7XG4gIHZhciB2ZXJzaW9uID0gc2Vzc1ZlciAhPT0gdW5kZWZpbmVkID8gc2Vzc1ZlciA6IDI7XG4gIGlmIChzZXNzSWQpIHtcbiAgICBzZXNzaW9uSWQgPSBzZXNzSWQ7XG4gIH0gZWxzZSB7XG4gICAgc2Vzc2lvbklkID0gU0RQVXRpbHMuZ2VuZXJhdGVTZXNzaW9uSWQoKTtcbiAgfVxuICAvLyBGSVhNRTogc2Vzcy1pZCBzaG91bGQgYmUgYW4gTlRQIHRpbWVzdGFtcC5cbiAgcmV0dXJuICd2PTBcXHJcXG4nICtcbiAgICAgICdvPXRoaXNpc2FkYXB0ZXJvcnRjICcgKyBzZXNzaW9uSWQgKyAnICcgKyB2ZXJzaW9uICsgJyBJTiBJUDQgMTI3LjAuMC4xXFxyXFxuJyArXG4gICAgICAncz0tXFxyXFxuJyArXG4gICAgICAndD0wIDBcXHJcXG4nO1xufTtcblxuU0RQVXRpbHMud3JpdGVNZWRpYVNlY3Rpb24gPSBmdW5jdGlvbih0cmFuc2NlaXZlciwgY2FwcywgdHlwZSwgc3RyZWFtKSB7XG4gIHZhciBzZHAgPSBTRFBVdGlscy53cml0ZVJ0cERlc2NyaXB0aW9uKHRyYW5zY2VpdmVyLmtpbmQsIGNhcHMpO1xuXG4gIC8vIE1hcCBJQ0UgcGFyYW1ldGVycyAodWZyYWcsIHB3ZCkgdG8gU0RQLlxuICBzZHAgKz0gU0RQVXRpbHMud3JpdGVJY2VQYXJhbWV0ZXJzKFxuICAgICAgdHJhbnNjZWl2ZXIuaWNlR2F0aGVyZXIuZ2V0TG9jYWxQYXJhbWV0ZXJzKCkpO1xuXG4gIC8vIE1hcCBEVExTIHBhcmFtZXRlcnMgdG8gU0RQLlxuICBzZHAgKz0gU0RQVXRpbHMud3JpdGVEdGxzUGFyYW1ldGVycyhcbiAgICAgIHRyYW5zY2VpdmVyLmR0bHNUcmFuc3BvcnQuZ2V0TG9jYWxQYXJhbWV0ZXJzKCksXG4gICAgICB0eXBlID09PSAnb2ZmZXInID8gJ2FjdHBhc3MnIDogJ2FjdGl2ZScpO1xuXG4gIHNkcCArPSAnYT1taWQ6JyArIHRyYW5zY2VpdmVyLm1pZCArICdcXHJcXG4nO1xuXG4gIGlmICh0cmFuc2NlaXZlci5kaXJlY3Rpb24pIHtcbiAgICBzZHAgKz0gJ2E9JyArIHRyYW5zY2VpdmVyLmRpcmVjdGlvbiArICdcXHJcXG4nO1xuICB9IGVsc2UgaWYgKHRyYW5zY2VpdmVyLnJ0cFNlbmRlciAmJiB0cmFuc2NlaXZlci5ydHBSZWNlaXZlcikge1xuICAgIHNkcCArPSAnYT1zZW5kcmVjdlxcclxcbic7XG4gIH0gZWxzZSBpZiAodHJhbnNjZWl2ZXIucnRwU2VuZGVyKSB7XG4gICAgc2RwICs9ICdhPXNlbmRvbmx5XFxyXFxuJztcbiAgfSBlbHNlIGlmICh0cmFuc2NlaXZlci5ydHBSZWNlaXZlcikge1xuICAgIHNkcCArPSAnYT1yZWN2b25seVxcclxcbic7XG4gIH0gZWxzZSB7XG4gICAgc2RwICs9ICdhPWluYWN0aXZlXFxyXFxuJztcbiAgfVxuXG4gIGlmICh0cmFuc2NlaXZlci5ydHBTZW5kZXIpIHtcbiAgICAvLyBzcGVjLlxuICAgIHZhciBtc2lkID0gJ21zaWQ6JyArIHN0cmVhbS5pZCArICcgJyArXG4gICAgICAgIHRyYW5zY2VpdmVyLnJ0cFNlbmRlci50cmFjay5pZCArICdcXHJcXG4nO1xuICAgIHNkcCArPSAnYT0nICsgbXNpZDtcblxuICAgIC8vIGZvciBDaHJvbWUuXG4gICAgc2RwICs9ICdhPXNzcmM6JyArIHRyYW5zY2VpdmVyLnNlbmRFbmNvZGluZ1BhcmFtZXRlcnNbMF0uc3NyYyArXG4gICAgICAgICcgJyArIG1zaWQ7XG4gICAgaWYgKHRyYW5zY2VpdmVyLnNlbmRFbmNvZGluZ1BhcmFtZXRlcnNbMF0ucnR4KSB7XG4gICAgICBzZHAgKz0gJ2E9c3NyYzonICsgdHJhbnNjZWl2ZXIuc2VuZEVuY29kaW5nUGFyYW1ldGVyc1swXS5ydHguc3NyYyArXG4gICAgICAgICAgJyAnICsgbXNpZDtcbiAgICAgIHNkcCArPSAnYT1zc3JjLWdyb3VwOkZJRCAnICtcbiAgICAgICAgICB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzWzBdLnNzcmMgKyAnICcgK1xuICAgICAgICAgIHRyYW5zY2VpdmVyLnNlbmRFbmNvZGluZ1BhcmFtZXRlcnNbMF0ucnR4LnNzcmMgK1xuICAgICAgICAgICdcXHJcXG4nO1xuICAgIH1cbiAgfVxuICAvLyBGSVhNRTogdGhpcyBzaG91bGQgYmUgd3JpdHRlbiBieSB3cml0ZVJ0cERlc2NyaXB0aW9uLlxuICBzZHAgKz0gJ2E9c3NyYzonICsgdHJhbnNjZWl2ZXIuc2VuZEVuY29kaW5nUGFyYW1ldGVyc1swXS5zc3JjICtcbiAgICAgICcgY25hbWU6JyArIFNEUFV0aWxzLmxvY2FsQ05hbWUgKyAnXFxyXFxuJztcbiAgaWYgKHRyYW5zY2VpdmVyLnJ0cFNlbmRlciAmJiB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzWzBdLnJ0eCkge1xuICAgIHNkcCArPSAnYT1zc3JjOicgKyB0cmFuc2NlaXZlci5zZW5kRW5jb2RpbmdQYXJhbWV0ZXJzWzBdLnJ0eC5zc3JjICtcbiAgICAgICAgJyBjbmFtZTonICsgU0RQVXRpbHMubG9jYWxDTmFtZSArICdcXHJcXG4nO1xuICB9XG4gIHJldHVybiBzZHA7XG59O1xuXG4vLyBHZXRzIHRoZSBkaXJlY3Rpb24gZnJvbSB0aGUgbWVkaWFTZWN0aW9uIG9yIHRoZSBzZXNzaW9ucGFydC5cblNEUFV0aWxzLmdldERpcmVjdGlvbiA9IGZ1bmN0aW9uKG1lZGlhU2VjdGlvbiwgc2Vzc2lvbnBhcnQpIHtcbiAgLy8gTG9vayBmb3Igc2VuZHJlY3YsIHNlbmRvbmx5LCByZWN2b25seSwgaW5hY3RpdmUsIGRlZmF1bHQgdG8gc2VuZHJlY3YuXG4gIHZhciBsaW5lcyA9IFNEUFV0aWxzLnNwbGl0TGluZXMobWVkaWFTZWN0aW9uKTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgIHN3aXRjaCAobGluZXNbaV0pIHtcbiAgICAgIGNhc2UgJ2E9c2VuZHJlY3YnOlxuICAgICAgY2FzZSAnYT1zZW5kb25seSc6XG4gICAgICBjYXNlICdhPXJlY3Zvbmx5JzpcbiAgICAgIGNhc2UgJ2E9aW5hY3RpdmUnOlxuICAgICAgICByZXR1cm4gbGluZXNbaV0uc3Vic3RyKDIpO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgLy8gRklYTUU6IFdoYXQgc2hvdWxkIGhhcHBlbiBoZXJlP1xuICAgIH1cbiAgfVxuICBpZiAoc2Vzc2lvbnBhcnQpIHtcbiAgICByZXR1cm4gU0RQVXRpbHMuZ2V0RGlyZWN0aW9uKHNlc3Npb25wYXJ0KTtcbiAgfVxuICByZXR1cm4gJ3NlbmRyZWN2Jztcbn07XG5cblNEUFV0aWxzLmdldEtpbmQgPSBmdW5jdGlvbihtZWRpYVNlY3Rpb24pIHtcbiAgdmFyIGxpbmVzID0gU0RQVXRpbHMuc3BsaXRMaW5lcyhtZWRpYVNlY3Rpb24pO1xuICB2YXIgbWxpbmUgPSBsaW5lc1swXS5zcGxpdCgnICcpO1xuICByZXR1cm4gbWxpbmVbMF0uc3Vic3RyKDIpO1xufTtcblxuU0RQVXRpbHMuaXNSZWplY3RlZCA9IGZ1bmN0aW9uKG1lZGlhU2VjdGlvbikge1xuICByZXR1cm4gbWVkaWFTZWN0aW9uLnNwbGl0KCcgJywgMilbMV0gPT09ICcwJztcbn07XG5cblNEUFV0aWxzLnBhcnNlTUxpbmUgPSBmdW5jdGlvbihtZWRpYVNlY3Rpb24pIHtcbiAgdmFyIGxpbmVzID0gU0RQVXRpbHMuc3BsaXRMaW5lcyhtZWRpYVNlY3Rpb24pO1xuICB2YXIgcGFydHMgPSBsaW5lc1swXS5zdWJzdHIoMikuc3BsaXQoJyAnKTtcbiAgcmV0dXJuIHtcbiAgICBraW5kOiBwYXJ0c1swXSxcbiAgICBwb3J0OiBwYXJzZUludChwYXJ0c1sxXSwgMTApLFxuICAgIHByb3RvY29sOiBwYXJ0c1syXSxcbiAgICBmbXQ6IHBhcnRzLnNsaWNlKDMpLmpvaW4oJyAnKVxuICB9O1xufTtcblxuU0RQVXRpbHMucGFyc2VPTGluZSA9IGZ1bmN0aW9uKG1lZGlhU2VjdGlvbikge1xuICB2YXIgbGluZSA9IFNEUFV0aWxzLm1hdGNoUHJlZml4KG1lZGlhU2VjdGlvbiwgJ289JylbMF07XG4gIHZhciBwYXJ0cyA9IGxpbmUuc3Vic3RyKDIpLnNwbGl0KCcgJyk7XG4gIHJldHVybiB7XG4gICAgdXNlcm5hbWU6IHBhcnRzWzBdLFxuICAgIHNlc3Npb25JZDogcGFydHNbMV0sXG4gICAgc2Vzc2lvblZlcnNpb246IHBhcnNlSW50KHBhcnRzWzJdLCAxMCksXG4gICAgbmV0VHlwZTogcGFydHNbM10sXG4gICAgYWRkcmVzc1R5cGU6IHBhcnRzWzRdLFxuICAgIGFkZHJlc3M6IHBhcnRzWzVdLFxuICB9O1xufVxuXG4vLyBFeHBvc2UgcHVibGljIG1ldGhvZHMuXG5pZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcpIHtcbiAgbW9kdWxlLmV4cG9ydHMgPSBTRFBVdGlscztcbn1cbiIsIi8qKlxuICogVUFQYXJzZXIuanMgdjAuNy4xN1xuICogTGlnaHR3ZWlnaHQgSmF2YVNjcmlwdC1iYXNlZCBVc2VyLUFnZW50IHN0cmluZyBwYXJzZXJcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9mYWlzYWxtYW4vdWEtcGFyc2VyLWpzXG4gKlxuICogQ29weXJpZ2h0IMKpIDIwMTItMjAxNiBGYWlzYWwgU2FsbWFuIDxmeXpsbWFuQGdtYWlsLmNvbT5cbiAqIER1YWwgbGljZW5zZWQgdW5kZXIgR1BMdjIgJiBNSVRcbiAqL1xuXG4oZnVuY3Rpb24gKHdpbmRvdywgdW5kZWZpbmVkKSB7XG5cbiAgICAndXNlIHN0cmljdCc7XG5cbiAgICAvLy8vLy8vLy8vLy8vL1xuICAgIC8vIENvbnN0YW50c1xuICAgIC8vLy8vLy8vLy8vLy9cblxuXG4gICAgdmFyIExJQlZFUlNJT04gID0gJzAuNy4xNycsXG4gICAgICAgIEVNUFRZICAgICAgID0gJycsXG4gICAgICAgIFVOS05PV04gICAgID0gJz8nLFxuICAgICAgICBGVU5DX1RZUEUgICA9ICdmdW5jdGlvbicsXG4gICAgICAgIFVOREVGX1RZUEUgID0gJ3VuZGVmaW5lZCcsXG4gICAgICAgIE9CSl9UWVBFICAgID0gJ29iamVjdCcsXG4gICAgICAgIFNUUl9UWVBFICAgID0gJ3N0cmluZycsXG4gICAgICAgIE1BSk9SICAgICAgID0gJ21ham9yJywgLy8gZGVwcmVjYXRlZFxuICAgICAgICBNT0RFTCAgICAgICA9ICdtb2RlbCcsXG4gICAgICAgIE5BTUUgICAgICAgID0gJ25hbWUnLFxuICAgICAgICBUWVBFICAgICAgICA9ICd0eXBlJyxcbiAgICAgICAgVkVORE9SICAgICAgPSAndmVuZG9yJyxcbiAgICAgICAgVkVSU0lPTiAgICAgPSAndmVyc2lvbicsXG4gICAgICAgIEFSQ0hJVEVDVFVSRT0gJ2FyY2hpdGVjdHVyZScsXG4gICAgICAgIENPTlNPTEUgICAgID0gJ2NvbnNvbGUnLFxuICAgICAgICBNT0JJTEUgICAgICA9ICdtb2JpbGUnLFxuICAgICAgICBUQUJMRVQgICAgICA9ICd0YWJsZXQnLFxuICAgICAgICBTTUFSVFRWICAgICA9ICdzbWFydHR2JyxcbiAgICAgICAgV0VBUkFCTEUgICAgPSAnd2VhcmFibGUnLFxuICAgICAgICBFTUJFRERFRCAgICA9ICdlbWJlZGRlZCc7XG5cblxuICAgIC8vLy8vLy8vLy8vXG4gICAgLy8gSGVscGVyXG4gICAgLy8vLy8vLy8vL1xuXG5cbiAgICB2YXIgdXRpbCA9IHtcbiAgICAgICAgZXh0ZW5kIDogZnVuY3Rpb24gKHJlZ2V4ZXMsIGV4dGVuc2lvbnMpIHtcbiAgICAgICAgICAgIHZhciBtYXJnZWRSZWdleGVzID0ge307XG4gICAgICAgICAgICBmb3IgKHZhciBpIGluIHJlZ2V4ZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXh0ZW5zaW9uc1tpXSAmJiBleHRlbnNpb25zW2ldLmxlbmd0aCAlIDIgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgbWFyZ2VkUmVnZXhlc1tpXSA9IGV4dGVuc2lvbnNbaV0uY29uY2F0KHJlZ2V4ZXNbaV0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG1hcmdlZFJlZ2V4ZXNbaV0gPSByZWdleGVzW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtYXJnZWRSZWdleGVzO1xuICAgICAgICB9LFxuICAgICAgICBoYXMgOiBmdW5jdGlvbiAoc3RyMSwgc3RyMikge1xuICAgICAgICAgIGlmICh0eXBlb2Ygc3RyMSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgcmV0dXJuIHN0cjIudG9Mb3dlckNhc2UoKS5pbmRleE9mKHN0cjEudG9Mb3dlckNhc2UoKSkgIT09IC0xO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBsb3dlcml6ZSA6IGZ1bmN0aW9uIChzdHIpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHIudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgfSxcbiAgICAgICAgbWFqb3IgOiBmdW5jdGlvbiAodmVyc2lvbikge1xuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZih2ZXJzaW9uKSA9PT0gU1RSX1RZUEUgPyB2ZXJzaW9uLnJlcGxhY2UoL1teXFxkXFwuXS9nLCcnKS5zcGxpdChcIi5cIilbMF0gOiB1bmRlZmluZWQ7XG4gICAgICAgIH0sXG4gICAgICAgIHRyaW0gOiBmdW5jdGlvbiAoc3RyKSB7XG4gICAgICAgICAgcmV0dXJuIHN0ci5yZXBsYWNlKC9eW1xcc1xcdUZFRkZcXHhBMF0rfFtcXHNcXHVGRUZGXFx4QTBdKyQvZywgJycpO1xuICAgICAgICB9XG4gICAgfTtcblxuXG4gICAgLy8vLy8vLy8vLy8vLy8vXG4gICAgLy8gTWFwIGhlbHBlclxuICAgIC8vLy8vLy8vLy8vLy8vXG5cblxuICAgIHZhciBtYXBwZXIgPSB7XG5cbiAgICAgICAgcmd4IDogZnVuY3Rpb24gKHVhLCBhcnJheXMpIHtcblxuICAgICAgICAgICAgLy92YXIgcmVzdWx0ID0ge30sXG4gICAgICAgICAgICB2YXIgaSA9IDAsIGosIGssIHAsIHEsIG1hdGNoZXMsIG1hdGNoOy8vLCBhcmdzID0gYXJndW1lbnRzO1xuXG4gICAgICAgICAgICAvKi8vIGNvbnN0cnVjdCBvYmplY3QgYmFyZWJvbmVzXG4gICAgICAgICAgICBmb3IgKHAgPSAwOyBwIDwgYXJnc1sxXS5sZW5ndGg7IHArKykge1xuICAgICAgICAgICAgICAgIHEgPSBhcmdzWzFdW3BdO1xuICAgICAgICAgICAgICAgIHJlc3VsdFt0eXBlb2YgcSA9PT0gT0JKX1RZUEUgPyBxWzBdIDogcV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9Ki9cblxuICAgICAgICAgICAgLy8gbG9vcCB0aHJvdWdoIGFsbCByZWdleGVzIG1hcHNcbiAgICAgICAgICAgIHdoaWxlIChpIDwgYXJyYXlzLmxlbmd0aCAmJiAhbWF0Y2hlcykge1xuXG4gICAgICAgICAgICAgICAgdmFyIHJlZ2V4ID0gYXJyYXlzW2ldLCAgICAgICAvLyBldmVuIHNlcXVlbmNlICgwLDIsNCwuLilcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSBhcnJheXNbaSArIDFdOyAgIC8vIG9kZCBzZXF1ZW5jZSAoMSwzLDUsLi4pXG4gICAgICAgICAgICAgICAgaiA9IGsgPSAwO1xuXG4gICAgICAgICAgICAgICAgLy8gdHJ5IG1hdGNoaW5nIHVhc3RyaW5nIHdpdGggcmVnZXhlc1xuICAgICAgICAgICAgICAgIHdoaWxlIChqIDwgcmVnZXgubGVuZ3RoICYmICFtYXRjaGVzKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcyA9IHJlZ2V4W2orK10uZXhlYyh1YSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhbWF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChwID0gMDsgcCA8IHByb3BzLmxlbmd0aDsgcCsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2ggPSBtYXRjaGVzWysra107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcSA9IHByb3BzW3BdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNoZWNrIGlmIGdpdmVuIHByb3BlcnR5IGlzIGFjdHVhbGx5IGFycmF5XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBxID09PSBPQkpfVFlQRSAmJiBxLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHEubGVuZ3RoID09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgcVsxXSA9PSBGVU5DX1RZUEUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhc3NpZ24gbW9kaWZpZWQgbWF0Y2hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzW3FbMF1dID0gcVsxXS5jYWxsKHRoaXMsIG1hdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXNzaWduIGdpdmVuIHZhbHVlLCBpZ25vcmUgcmVnZXggbWF0Y2hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzW3FbMF1dID0gcVsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChxLmxlbmd0aCA9PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjaGVjayB3aGV0aGVyIGZ1bmN0aW9uIG9yIHJlZ2V4XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHFbMV0gPT09IEZVTkNfVFlQRSAmJiAhKHFbMV0uZXhlYyAmJiBxWzFdLnRlc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY2FsbCBmdW5jdGlvbiAodXN1YWxseSBzdHJpbmcgbWFwcGVyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNbcVswXV0gPSBtYXRjaCA/IHFbMV0uY2FsbCh0aGlzLCBtYXRjaCwgcVsyXSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNhbml0aXplIG1hdGNoIHVzaW5nIGdpdmVuIHJlZ2V4XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1txWzBdXSA9IG1hdGNoID8gbWF0Y2gucmVwbGFjZShxWzFdLCBxWzJdKSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChxLmxlbmd0aCA9PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1txWzBdXSA9IG1hdGNoID8gcVszXS5jYWxsKHRoaXMsIG1hdGNoLnJlcGxhY2UocVsxXSwgcVsyXSkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1txXSA9IG1hdGNoID8gbWF0Y2ggOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGkgKz0gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKHRoaXMpO1xuICAgICAgICAgICAgLy9yZXR1cm4gdGhpcztcbiAgICAgICAgfSxcblxuICAgICAgICBzdHIgOiBmdW5jdGlvbiAoc3RyLCBtYXApIHtcblxuICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBtYXApIHtcbiAgICAgICAgICAgICAgICAvLyBjaGVjayBpZiBhcnJheVxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWFwW2ldID09PSBPQkpfVFlQRSAmJiBtYXBbaV0ubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1hcFtpXS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHV0aWwuaGFzKG1hcFtpXVtqXSwgc3RyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoaSA9PT0gVU5LTk9XTikgPyB1bmRlZmluZWQgOiBpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh1dGlsLmhhcyhtYXBbaV0sIHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChpID09PSBVTktOT1dOKSA/IHVuZGVmaW5lZCA6IGk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHN0cjtcbiAgICAgICAgfVxuICAgIH07XG5cblxuICAgIC8vLy8vLy8vLy8vLy8vL1xuICAgIC8vIFN0cmluZyBtYXBcbiAgICAvLy8vLy8vLy8vLy8vL1xuXG5cbiAgICB2YXIgbWFwcyA9IHtcblxuICAgICAgICBicm93c2VyIDoge1xuICAgICAgICAgICAgb2xkc2FmYXJpIDoge1xuICAgICAgICAgICAgICAgIHZlcnNpb24gOiB7XG4gICAgICAgICAgICAgICAgICAgICcxLjAnICAgOiAnLzgnLFxuICAgICAgICAgICAgICAgICAgICAnMS4yJyAgIDogJy8xJyxcbiAgICAgICAgICAgICAgICAgICAgJzEuMycgICA6ICcvMycsXG4gICAgICAgICAgICAgICAgICAgICcyLjAnICAgOiAnLzQxMicsXG4gICAgICAgICAgICAgICAgICAgICcyLjAuMicgOiAnLzQxNicsXG4gICAgICAgICAgICAgICAgICAgICcyLjAuMycgOiAnLzQxNycsXG4gICAgICAgICAgICAgICAgICAgICcyLjAuNCcgOiAnLzQxOScsXG4gICAgICAgICAgICAgICAgICAgICc/JyAgICAgOiAnLydcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgZGV2aWNlIDoge1xuICAgICAgICAgICAgYW1hem9uIDoge1xuICAgICAgICAgICAgICAgIG1vZGVsIDoge1xuICAgICAgICAgICAgICAgICAgICAnRmlyZSBQaG9uZScgOiBbJ1NEJywgJ0tGJ11cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc3ByaW50IDoge1xuICAgICAgICAgICAgICAgIG1vZGVsIDoge1xuICAgICAgICAgICAgICAgICAgICAnRXZvIFNoaWZ0IDRHJyA6ICc3MzczS1QnXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB2ZW5kb3IgOiB7XG4gICAgICAgICAgICAgICAgICAgICdIVEMnICAgICAgIDogJ0FQQScsXG4gICAgICAgICAgICAgICAgICAgICdTcHJpbnQnICAgIDogJ1NwcmludCdcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgb3MgOiB7XG4gICAgICAgICAgICB3aW5kb3dzIDoge1xuICAgICAgICAgICAgICAgIHZlcnNpb24gOiB7XG4gICAgICAgICAgICAgICAgICAgICdNRScgICAgICAgIDogJzQuOTAnLFxuICAgICAgICAgICAgICAgICAgICAnTlQgMy4xMScgICA6ICdOVDMuNTEnLFxuICAgICAgICAgICAgICAgICAgICAnTlQgNC4wJyAgICA6ICdOVDQuMCcsXG4gICAgICAgICAgICAgICAgICAgICcyMDAwJyAgICAgIDogJ05UIDUuMCcsXG4gICAgICAgICAgICAgICAgICAgICdYUCcgICAgICAgIDogWydOVCA1LjEnLCAnTlQgNS4yJ10sXG4gICAgICAgICAgICAgICAgICAgICdWaXN0YScgICAgIDogJ05UIDYuMCcsXG4gICAgICAgICAgICAgICAgICAgICc3JyAgICAgICAgIDogJ05UIDYuMScsXG4gICAgICAgICAgICAgICAgICAgICc4JyAgICAgICAgIDogJ05UIDYuMicsXG4gICAgICAgICAgICAgICAgICAgICc4LjEnICAgICAgIDogJ05UIDYuMycsXG4gICAgICAgICAgICAgICAgICAgICcxMCcgICAgICAgIDogWydOVCA2LjQnLCAnTlQgMTAuMCddLFxuICAgICAgICAgICAgICAgICAgICAnUlQnICAgICAgICA6ICdBUk0nXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuXG4gICAgLy8vLy8vLy8vLy8vLy9cbiAgICAvLyBSZWdleCBtYXBcbiAgICAvLy8vLy8vLy8vLy8vXG5cblxuICAgIHZhciByZWdleGVzID0ge1xuXG4gICAgICAgIGJyb3dzZXIgOiBbW1xuXG4gICAgICAgICAgICAvLyBQcmVzdG8gYmFzZWRcbiAgICAgICAgICAgIC8ob3BlcmFcXHNtaW5pKVxcLyhbXFx3XFwuLV0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhIE1pbmlcbiAgICAgICAgICAgIC8ob3BlcmFcXHNbbW9iaWxldGFiXSspLit2ZXJzaW9uXFwvKFtcXHdcXC4tXSspL2ksICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhIE1vYmkvVGFibGV0XG4gICAgICAgICAgICAvKG9wZXJhKS4rdmVyc2lvblxcLyhbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhID4gOS44MFxuICAgICAgICAgICAgLyhvcGVyYSlbXFwvXFxzXSsoW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3BlcmEgPCA5LjgwXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhvcGlvcylbXFwvXFxzXSsoW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3BlcmEgbWluaSBvbiBpcGhvbmUgPj0gOC4wXG4gICAgICAgICAgICBdLCBbW05BTUUsICdPcGVyYSBNaW5pJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC9cXHMob3ByKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhIFdlYmtpdFxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnT3BlcmEnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLy8gTWl4ZWRcbiAgICAgICAgICAgIC8oa2luZGxlKVxcLyhbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gS2luZGxlXG4gICAgICAgICAgICAvKGx1bmFzY2FwZXxtYXh0aG9ufG5ldGZyb250fGphc21pbmV8YmxhemVyKVtcXC9cXHNdPyhbXFx3XFwuXSspKi9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBMdW5hc2NhcGUvTWF4dGhvbi9OZXRmcm9udC9KYXNtaW5lL0JsYXplclxuXG4gICAgICAgICAgICAvLyBUcmlkZW50IGJhc2VkXG4gICAgICAgICAgICAvKGF2YW50XFxzfGllbW9iaWxlfHNsaW18YmFpZHUpKD86YnJvd3Nlcik/W1xcL1xcc10/KFtcXHdcXC5dKikvaSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXZhbnQvSUVNb2JpbGUvU2xpbUJyb3dzZXIvQmFpZHVcbiAgICAgICAgICAgIC8oPzptc3xcXCgpKGllKVxccyhbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEludGVybmV0IEV4cGxvcmVyXG5cbiAgICAgICAgICAgIC8vIFdlYmtpdC9LSFRNTCBiYXNlZFxuICAgICAgICAgICAgLyhyZWtvbnEpXFwvKFtcXHdcXC5dKykqL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZWtvbnFcbiAgICAgICAgICAgIC8oY2hyb21pdW18ZmxvY2t8cm9ja21lbHR8bWlkb3JpfGVwaXBoYW55fHNpbGt8c2t5ZmlyZXxvdmlicm93c2VyfGJvbHR8aXJvbnx2aXZhbGRpfGlyaWRpdW18cGhhbnRvbWpzfGJvd3NlcilcXC8oW1xcd1xcLi1dKykvaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDaHJvbWl1bS9GbG9jay9Sb2NrTWVsdC9NaWRvcmkvRXBpcGhhbnkvU2lsay9Ta3lmaXJlL0JvbHQvSXJvbi9JcmlkaXVtL1BoYW50b21KUy9Cb3dzZXJcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKHRyaWRlbnQpLitydls6XFxzXShbXFx3XFwuXSspLitsaWtlXFxzZ2Vja28vaSAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJRTExXG4gICAgICAgICAgICBdLCBbW05BTUUsICdJRSddLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKGVkZ2UpXFwvKChcXGQrKT9bXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNaWNyb3NvZnQgRWRnZVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oeWFicm93c2VyKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gWWFuZGV4XG4gICAgICAgICAgICBdLCBbW05BTUUsICdZYW5kZXgnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhwdWZmaW4pXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBQdWZmaW5cbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ1B1ZmZpbiddLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKCg/OltcXHNcXC9dKXVjP1xccz9icm93c2VyfCg/Omp1Yy4rKXVjd2ViKVtcXC9cXHNdPyhbXFx3XFwuXSspL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVUNCcm93c2VyXG4gICAgICAgICAgICBdLCBbW05BTUUsICdVQ0Jyb3dzZXInXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhjb21vZG9fZHJhZ29uKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDb21vZG8gRHJhZ29uXG4gICAgICAgICAgICBdLCBbW05BTUUsIC9fL2csICcgJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8obWljcm9tZXNzZW5nZXIpXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2VDaGF0XG4gICAgICAgICAgICBdLCBbW05BTUUsICdXZUNoYXQnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhRUSlcXC8oW1xcZFxcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBRUSwgYWthIFNob3VRXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgL20/KHFxYnJvd3NlcilbXFwvXFxzXT8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUVFCcm93c2VyXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgL3hpYW9taVxcL21pdWlicm93c2VyXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTUlVSSBCcm93c2VyXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgW05BTUUsICdNSVVJIEJyb3dzZXInXV0sIFtcblxuICAgICAgICAgICAgLztmYmF2XFwvKFtcXHdcXC5dKyk7L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGYWNlYm9vayBBcHAgZm9yIGlPUyAmIEFuZHJvaWRcbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBbTkFNRSwgJ0ZhY2Vib29rJ11dLCBbXG5cbiAgICAgICAgICAgIC9oZWFkbGVzc2Nocm9tZSg/OlxcLyhbXFx3XFwuXSspfFxccykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENocm9tZSBIZWFkbGVzc1xuICAgICAgICAgICAgXSwgW1ZFUlNJT04sIFtOQU1FLCAnQ2hyb21lIEhlYWRsZXNzJ11dLCBbXG5cbiAgICAgICAgICAgIC9cXHN3dlxcKS4rKGNocm9tZSlcXC8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDaHJvbWUgV2ViVmlld1xuICAgICAgICAgICAgXSwgW1tOQU1FLCAvKC4rKS8sICckMSBXZWJWaWV3J10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oKD86b2N1bHVzfHNhbXN1bmcpYnJvd3NlcilcXC8oW1xcd1xcLl0rKS9pXG4gICAgICAgICAgICBdLCBbW05BTUUsIC8oLisoPzpnfHVzKSkoLispLywgJyQxICQyJ10sIFZFUlNJT05dLCBbICAgICAgICAgICAgICAgIC8vIE9jdWx1cyAvIFNhbXN1bmcgQnJvd3NlclxuXG4gICAgICAgICAgICAvYW5kcm9pZC4rdmVyc2lvblxcLyhbXFx3XFwuXSspXFxzKyg/Om1vYmlsZVxccz9zYWZhcml8c2FmYXJpKSovaSAgICAgICAgLy8gQW5kcm9pZCBCcm93c2VyXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgW05BTUUsICdBbmRyb2lkIEJyb3dzZXInXV0sIFtcblxuICAgICAgICAgICAgLyhjaHJvbWV8b21uaXdlYnxhcm9yYXxbdGl6ZW5va2FdezV9XFxzP2Jyb3dzZXIpXFwvdj8oW1xcd1xcLl0rKS9pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENocm9tZS9PbW5pV2ViL0Fyb3JhL1RpemVuL05va2lhXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhkb2xmaW4pXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2xwaGluXG4gICAgICAgICAgICBdLCBbW05BTUUsICdEb2xwaGluJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oKD86YW5kcm9pZC4rKWNybW98Y3Jpb3MpXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hyb21lIGZvciBBbmRyb2lkL2lPU1xuICAgICAgICAgICAgXSwgW1tOQU1FLCAnQ2hyb21lJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oY29hc3QpXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3BlcmEgQ29hc3RcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ09wZXJhIENvYXN0J10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC9meGlvc1xcLyhbXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCBmb3IgaU9TXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgW05BTUUsICdGaXJlZm94J11dLCBbXG5cbiAgICAgICAgICAgIC92ZXJzaW9uXFwvKFtcXHdcXC5dKykuKz9tb2JpbGVcXC9cXHcrXFxzKHNhZmFyaSkvaSAgICAgICAgICAgICAgICAgICAgICAgLy8gTW9iaWxlIFNhZmFyaVxuICAgICAgICAgICAgXSwgW1ZFUlNJT04sIFtOQU1FLCAnTW9iaWxlIFNhZmFyaSddXSwgW1xuXG4gICAgICAgICAgICAvdmVyc2lvblxcLyhbXFx3XFwuXSspLis/KG1vYmlsZVxccz9zYWZhcml8c2FmYXJpKS9pICAgICAgICAgICAgICAgICAgICAvLyBTYWZhcmkgJiBTYWZhcmkgTW9iaWxlXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgTkFNRV0sIFtcblxuICAgICAgICAgICAgL3dlYmtpdC4rPyhnc2EpXFwvKFtcXHdcXC5dKykuKz8obW9iaWxlXFxzP3NhZmFyaXxzYWZhcmkpKFxcL1tcXHdcXC5dKykvaSAgLy8gR29vZ2xlIFNlYXJjaCBBcHBsaWFuY2Ugb24gaU9TXG4gICAgICAgICAgICBdLCBbW05BTUUsICdHU0EnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgL3dlYmtpdC4rPyhtb2JpbGVcXHM/c2FmYXJpfHNhZmFyaSkoXFwvW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgLy8gU2FmYXJpIDwgMy4wXG4gICAgICAgICAgICBdLCBbTkFNRSwgW1ZFUlNJT04sIG1hcHBlci5zdHIsIG1hcHMuYnJvd3Nlci5vbGRzYWZhcmkudmVyc2lvbl1dLCBbXG5cbiAgICAgICAgICAgIC8oa29ucXVlcm9yKVxcLyhbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gS29ucXVlcm9yXG4gICAgICAgICAgICAvKHdlYmtpdHxraHRtbClcXC8oW1xcd1xcLl0rKS9pXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLy8gR2Vja28gYmFzZWRcbiAgICAgICAgICAgIC8obmF2aWdhdG9yfG5ldHNjYXBlKVxcLyhbXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTmV0c2NhcGVcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ05ldHNjYXBlJ10sIFZFUlNJT05dLCBbXG4gICAgICAgICAgICAvKHN3aWZ0Zm94KS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN3aWZ0Zm94XG4gICAgICAgICAgICAvKGljZWRyYWdvbnxpY2V3ZWFzZWx8Y2FtaW5vfGNoaW1lcmF8ZmVubmVjfG1hZW1vXFxzYnJvd3NlcnxtaW5pbW98Y29ua2Vyb3IpW1xcL1xcc10/KFtcXHdcXC5cXCtdKykvaSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWNlRHJhZ29uL0ljZXdlYXNlbC9DYW1pbm8vQ2hpbWVyYS9GZW5uZWMvTWFlbW8vTWluaW1vL0Nvbmtlcm9yXG4gICAgICAgICAgICAvKGZpcmVmb3h8c2VhbW9ua2V5fGstbWVsZW9ufGljZWNhdHxpY2VhcGV8ZmlyZWJpcmR8cGhvZW5peClcXC8oW1xcd1xcLi1dKykvaSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveC9TZWFNb25rZXkvSy1NZWxlb24vSWNlQ2F0L0ljZUFwZS9GaXJlYmlyZC9QaG9lbml4XG4gICAgICAgICAgICAvKG1vemlsbGEpXFwvKFtcXHdcXC5dKykuK3J2XFw6LitnZWNrb1xcL1xcZCsvaSwgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1vemlsbGFcblxuICAgICAgICAgICAgLy8gT3RoZXJcbiAgICAgICAgICAgIC8ocG9sYXJpc3xseW54fGRpbGxvfGljYWJ8ZG9yaXN8YW1heWF8dzNtfG5ldHN1cmZ8c2xlaXBuaXIpW1xcL1xcc10/KFtcXHdcXC5dKykvaSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUG9sYXJpcy9MeW54L0RpbGxvL2lDYWIvRG9yaXMvQW1heWEvdzNtL05ldFN1cmYvU2xlaXBuaXJcbiAgICAgICAgICAgIC8obGlua3MpXFxzXFwoKFtcXHdcXC5dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExpbmtzXG4gICAgICAgICAgICAvKGdvYnJvd3NlcilcXC8/KFtcXHdcXC5dKykqL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdvQnJvd3NlclxuICAgICAgICAgICAgLyhpY2VcXHM/YnJvd3NlcilcXC92PyhbXFx3XFwuX10rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSUNFIEJyb3dzZXJcbiAgICAgICAgICAgIC8obW9zYWljKVtcXC9cXHNdKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1vc2FpY1xuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dXG5cbiAgICAgICAgICAgIC8qIC8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgICAgICAgICAgLy8gTWVkaWEgcGxheWVycyBCRUdJTlxuICAgICAgICAgICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG5cbiAgICAgICAgICAgICwgW1xuXG4gICAgICAgICAgICAvKGFwcGxlKD86Y29yZW1lZGlhfCkpXFwvKChcXGQrKVtcXHdcXC5fXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBHZW5lcmljIEFwcGxlIENvcmVNZWRpYVxuICAgICAgICAgICAgLyhjb3JlbWVkaWEpIHYoKFxcZCspW1xcd1xcLl9dKykvaVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oYXF1YWx1bmd8bHlzc25hfGJzcGxheWVyKVxcLygoXFxkKyk/W1xcd1xcLi1dKykvaSAgICAgICAgICAgICAgICAgICAgIC8vIEFxdWFsdW5nL0x5c3NuYS9CU1BsYXllclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oYXJlc3xvc3Nwcm94eSlcXHMoKFxcZCspW1xcd1xcLi1dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFyZXMvT1NTUHJveHlcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKGF1ZGFjaW91c3xhdWRpbXVzaWNzdHJlYW18YW1hcm9rfGJhc3N8Y29yZXxkYWx2aWt8Z25vbWVtcGxheWVyfG11c2ljIG9uIGNvbnNvbGV8bnNwbGF5ZXJ8cHNwLWludGVybmV0cmFkaW9wbGF5ZXJ8dmlkZW9zKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBdWRhY2lvdXMvQXVkaU11c2ljU3RyZWFtL0FtYXJvay9CQVNTL09wZW5DT1JFL0RhbHZpay9Hbm9tZU1wbGF5ZXIvTW9DXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5TUGxheWVyL1BTUC1JbnRlcm5ldFJhZGlvUGxheWVyL1ZpZGVvc1xuICAgICAgICAgICAgLyhjbGVtZW50aW5lfG11c2ljIHBsYXllciBkYWVtb24pXFxzKChcXGQrKVtcXHdcXC4tXSspL2ksICAgICAgICAgICAgICAgLy8gQ2xlbWVudGluZS9NUERcbiAgICAgICAgICAgIC8obGcgcGxheWVyfG5leHBsYXllcilcXHMoKFxcZCspW1xcZFxcLl0rKS9pLFxuICAgICAgICAgICAgL3BsYXllclxcLyhuZXhwbGF5ZXJ8bGcgcGxheWVyKVxccygoXFxkKylbXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgIC8vIE5leFBsYXllci9MRyBQbGF5ZXJcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuICAgICAgICAgICAgLyhuZXhwbGF5ZXIpXFxzKChcXGQrKVtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTmV4cGxheWVyXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhmbHJwKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRmxpcCBQbGF5ZXJcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0ZsaXAgUGxheWVyJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oZnN0cmVhbXxuYXRpdmVob3N0fHF1ZXJ5c2Vla3NwaWRlcnxpYS1hcmNoaXZlcnxmYWNlYm9va2V4dGVybmFsaGl0KS9pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZTdHJlYW0vTmF0aXZlSG9zdC9RdWVyeVNlZWtTcGlkZXIvSUEgQXJjaGl2ZXIvZmFjZWJvb2tleHRlcm5hbGhpdFxuICAgICAgICAgICAgXSwgW05BTUVdLCBbXG5cbiAgICAgICAgICAgIC8oZ3N0cmVhbWVyKSBzb3VwaHR0cHNyYyAoPzpcXChbXlxcKV0rXFwpKXswLDF9IGxpYnNvdXBcXC8oKFxcZCspW1xcd1xcLi1dKykvaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBHc3RyZWFtZXJcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKGh0YyBzdHJlYW1pbmcgcGxheWVyKVxcc1tcXHdfXStcXHNcXC9cXHMoKFxcZCspW1xcZFxcLl0rKS9pLCAgICAgICAgICAgICAgLy8gSFRDIFN0cmVhbWluZyBQbGF5ZXJcbiAgICAgICAgICAgIC8oamF2YXxweXRob24tdXJsbGlifHB5dGhvbi1yZXF1ZXN0c3x3Z2V0fGxpYmN1cmwpXFwvKChcXGQrKVtcXHdcXC4tX10rKS9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBKYXZhL3VybGxpYi9yZXF1ZXN0cy93Z2V0L2NVUkxcbiAgICAgICAgICAgIC8obGF2ZikoKFxcZCspW1xcZFxcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTGF2ZiAoRkZNUEVHKVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oaHRjX29uZV9zKVxcLygoXFxkKylbXFxkXFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEhUQyBPbmUgU1xuICAgICAgICAgICAgXSwgW1tOQU1FLCAvXy9nLCAnICddLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKG1wbGF5ZXIpKD86XFxzfFxcLykoPzooPzpzaGVycHlhLSl7MCwxfXN2bikoPzotfFxccykoclxcZCsoPzotXFxkK1tcXHdcXC4tXSspezAsMX0pL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTVBsYXllciBTVk5cbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKG1wbGF5ZXIpKD86XFxzfFxcL3xbdW5rb3ctXSspKChcXGQrKVtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgICAgLy8gTVBsYXllclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8obXBsYXllcikvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTVBsYXllciAobm8gb3RoZXIgaW5mbylcbiAgICAgICAgICAgIC8oeW91cm11emUpL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gWW91ck11emVcbiAgICAgICAgICAgIC8obWVkaWEgcGxheWVyIGNsYXNzaWN8bmVybyBzaG93dGltZSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWVkaWEgUGxheWVyIENsYXNzaWMvTmVybyBTaG93VGltZVxuICAgICAgICAgICAgXSwgW05BTUVdLCBbXG5cbiAgICAgICAgICAgIC8obmVybyAoPzpob21lfHNjb3V0KSlcXC8oKFxcZCspW1xcd1xcLi1dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5lcm8gSG9tZS9OZXJvIFNjb3V0XG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhub2tpYVxcZCspXFwvKChcXGQrKVtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5va2lhXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgL1xccyhzb25nYmlyZClcXC8oKFxcZCspW1xcd1xcLi1dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvbmdiaXJkL1BoaWxpcHMtU29uZ2JpcmRcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKHdpbmFtcCkzIHZlcnNpb24gKChcXGQrKVtcXHdcXC4tXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpbmFtcFxuICAgICAgICAgICAgLyh3aW5hbXApXFxzKChcXGQrKVtcXHdcXC4tXSspL2ksXG4gICAgICAgICAgICAvKHdpbmFtcCltcGVnXFwvKChcXGQrKVtcXHdcXC4tXSspL2lcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKG9jbXMtYm90fHRhcGlucmFkaW98dHVuZWluIHJhZGlvfHVua25vd258d2luYW1wfGlubGlnaHQgcmFkaW8pL2kgIC8vIE9DTVMtYm90L3RhcCBpbiByYWRpby90dW5laW4vdW5rbm93bi93aW5hbXAgKG5vIG90aGVyIGluZm8pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlubGlnaHQgcmFkaW9cbiAgICAgICAgICAgIF0sIFtOQU1FXSwgW1xuXG4gICAgICAgICAgICAvKHF1aWNrdGltZXxybWF8cmFkaW9hcHB8cmFkaW9jbGllbnRhcHBsaWNhdGlvbnxzb3VuZHRhcHx0b3RlbXxzdGFnZWZyaWdodHxzdHJlYW1pdW0pXFwvKChcXGQrKVtcXHdcXC4tXSspL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUXVpY2tUaW1lL1JlYWxNZWRpYS9SYWRpb0FwcC9SYWRpb0NsaWVudEFwcGxpY2F0aW9uL1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTb3VuZFRhcC9Ub3RlbS9TdGFnZWZyaWdodC9TdHJlYW1pdW1cbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKHNtcCkoKFxcZCspW1xcZFxcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNNUFxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8odmxjKSBtZWRpYSBwbGF5ZXIgLSB2ZXJzaW9uICgoXFxkKylbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgLy8gVkxDIFZpZGVvbGFuXG4gICAgICAgICAgICAvKHZsYylcXC8oKFxcZCspW1xcd1xcLi1dKykvaSxcbiAgICAgICAgICAgIC8oeGJtY3xndmZzfHhpbmV8eG1tc3xpcmFwcClcXC8oKFxcZCspW1xcd1xcLi1dKykvaSwgICAgICAgICAgICAgICAgICAgIC8vIFhCTUMvZ3Zmcy9YaW5lL1hNTVMvaXJhcHBcbiAgICAgICAgICAgIC8oZm9vYmFyMjAwMClcXC8oKFxcZCspW1xcZFxcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZvb2JhcjIwMDBcbiAgICAgICAgICAgIC8oaXR1bmVzKVxcLygoXFxkKylbXFxkXFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlUdW5lc1xuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8od21wbGF5ZXIpXFwvKChcXGQrKVtcXHdcXC4tXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpbmRvd3MgTWVkaWEgUGxheWVyXG4gICAgICAgICAgICAvKHdpbmRvd3MtbWVkaWEtcGxheWVyKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pXG4gICAgICAgICAgICBdLCBbW05BTUUsIC8tL2csICcgJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC93aW5kb3dzXFwvKChcXGQrKVtcXHdcXC4tXSspIHVwbnBcXC9bXFxkXFwuXSsgZGxuYWRvY1xcL1tcXGRcXC5dKyAoaG9tZSBtZWRpYSBzZXJ2ZXIpL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2luZG93cyBNZWRpYSBTZXJ2ZXJcbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBbTkFNRSwgJ1dpbmRvd3MnXV0sIFtcblxuICAgICAgICAgICAgLyhjb21cXC5yaXNldXByYWRpb2FsYXJtKVxcLygoXFxkKylbXFxkXFwuXSopL2kgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJpc2VVUCBSYWRpbyBBbGFybVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8ocmFkLmlvKVxccygoXFxkKylbXFxkXFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJhZC5pb1xuICAgICAgICAgICAgLyhyYWRpby4oPzpkZXxhdHxmcikpXFxzKChcXGQrKVtcXGRcXC5dKykvaVxuICAgICAgICAgICAgXSwgW1tOQU1FLCAncmFkLmlvJ10sIFZFUlNJT05dXG5cbiAgICAgICAgICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgICAgICAgICAgIC8vIE1lZGlhIHBsYXllcnMgRU5EXG4gICAgICAgICAgICAvLy8vLy8vLy8vLy8vLy8vLy8vLyovXG5cbiAgICAgICAgXSxcblxuICAgICAgICBjcHUgOiBbW1xuXG4gICAgICAgICAgICAvKD86KGFtZHx4KD86KD86ODZ8NjQpW18tXSk/fHdvd3x3aW4pNjQpWztcXCldL2kgICAgICAgICAgICAgICAgICAgICAvLyBBTUQ2NFxuICAgICAgICAgICAgXSwgW1tBUkNISVRFQ1RVUkUsICdhbWQ2NCddXSwgW1xuXG4gICAgICAgICAgICAvKGlhMzIoPz07KSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElBMzIgKHF1aWNrdGltZSlcbiAgICAgICAgICAgIF0sIFtbQVJDSElURUNUVVJFLCB1dGlsLmxvd2VyaXplXV0sIFtcblxuICAgICAgICAgICAgLygoPzppWzM0Nl18eCk4NilbO1xcKV0vaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSUEzMlxuICAgICAgICAgICAgXSwgW1tBUkNISVRFQ1RVUkUsICdpYTMyJ11dLCBbXG5cbiAgICAgICAgICAgIC8vIFBvY2tldFBDIG1pc3Rha2VubHkgaWRlbnRpZmllZCBhcyBQb3dlclBDXG4gICAgICAgICAgICAvd2luZG93c1xccyhjZXxtb2JpbGUpO1xcc3BwYzsvaVxuICAgICAgICAgICAgXSwgW1tBUkNISVRFQ1RVUkUsICdhcm0nXV0sIFtcblxuICAgICAgICAgICAgLygoPzpwcGN8cG93ZXJwYykoPzo2NCk/KSg/Olxcc21hY3w7fFxcKSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBvd2VyUENcbiAgICAgICAgICAgIF0sIFtbQVJDSElURUNUVVJFLCAvb3dlci8sICcnLCB1dGlsLmxvd2VyaXplXV0sIFtcblxuICAgICAgICAgICAgLyhzdW40XFx3KVs7XFwpXS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNQQVJDXG4gICAgICAgICAgICBdLCBbW0FSQ0hJVEVDVFVSRSwgJ3NwYXJjJ11dLCBbXG5cbiAgICAgICAgICAgIC8oKD86YXZyMzJ8aWE2NCg/PTspKXw2OGsoPz1cXCkpfGFybSg/OjY0fCg/PXZcXGQrOykpfCg/PWF0bWVsXFxzKWF2cnwoPzppcml4fG1pcHN8c3BhcmMpKD86NjQpPyg/PTspfHBhLXJpc2MpL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSUE2NCwgNjhLLCBBUk0vNjQsIEFWUi8zMiwgSVJJWC82NCwgTUlQUy82NCwgU1BBUkMvNjQsIFBBLVJJU0NcbiAgICAgICAgICAgIF0sIFtbQVJDSElURUNUVVJFLCB1dGlsLmxvd2VyaXplXV1cbiAgICAgICAgXSxcblxuICAgICAgICBkZXZpY2UgOiBbW1xuXG4gICAgICAgICAgICAvXFwoKGlwYWR8cGxheWJvb2spO1tcXHdcXHNcXCk7LV0rKHJpbXxhcHBsZSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpUGFkL1BsYXlCb29rXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFZFTkRPUiwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hcHBsZWNvcmVtZWRpYVxcL1tcXHdcXC5dKyBcXCgoaXBhZCkvICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlQYWRcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0FwcGxlJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvKGFwcGxlXFxzezAsMX10dikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBcHBsZSBUVlxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0FwcGxlIFRWJ10sIFtWRU5ET1IsICdBcHBsZSddXSwgW1xuXG4gICAgICAgICAgICAvKGFyY2hvcylcXHMoZ2FtZXBhZDI/KS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBcmNob3NcbiAgICAgICAgICAgIC8oaHApLisodG91Y2hwYWQpL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSFAgVG91Y2hQYWRcbiAgICAgICAgICAgIC8oaHApLisodGFibGV0KS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSFAgVGFibGV0XG4gICAgICAgICAgICAvKGtpbmRsZSlcXC8oW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEtpbmRsZVxuICAgICAgICAgICAgL1xccyhub29rKVtcXHdcXHNdK2J1aWxkXFwvKFxcdyspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5vb2tcbiAgICAgICAgICAgIC8oZGVsbClcXHMoc3RyZWFba3ByXFxzXFxkXSpbXFxka29dKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIERlbGwgU3RyZWFrXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC8oa2ZbQS16XSspXFxzYnVpbGRcXC9bXFx3XFwuXSsuKnNpbGtcXC8vaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBLaW5kbGUgRmlyZSBIRFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnQW1hem9uJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhzZHxrZilbMDM0OWhpam9yc3R1d10rXFxzYnVpbGRcXC9bXFx3XFwuXSsuKnNpbGtcXC8vaSAgICAgICAgICAgICAgICAgIC8vIEZpcmUgUGhvbmVcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsIG1hcHBlci5zdHIsIG1hcHMuZGV2aWNlLmFtYXpvbi5tb2RlbF0sIFtWRU5ET1IsICdBbWF6b24nXSwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC9cXCgoaXBbaG9uZWR8XFxzXFx3Kl0rKTsuKyhhcHBsZSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaVBvZC9pUGhvbmVcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgVkVORE9SLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC9cXCgoaXBbaG9uZWR8XFxzXFx3Kl0rKTsvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaVBvZC9pUGhvbmVcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0FwcGxlJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKGJsYWNrYmVycnkpW1xccy1dPyhcXHcrKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQmxhY2tCZXJyeVxuICAgICAgICAgICAgLyhibGFja2JlcnJ5fGJlbnF8cGFsbSg/PVxcLSl8c29ueWVyaWNzc29ufGFjZXJ8YXN1c3xkZWxsfG1laXp1fG1vdG9yb2xhfHBvbHl0cm9uKVtcXHNfLV0/KFtcXHctXSspKi9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBCZW5RL1BhbG0vU29ueS1Fcmljc3Nvbi9BY2VyL0FzdXMvRGVsbC9NZWl6dS9Nb3Rvcm9sYS9Qb2x5dHJvblxuICAgICAgICAgICAgLyhocClcXHMoW1xcd1xcc10rXFx3KS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSFAgaVBBUVxuICAgICAgICAgICAgLyhhc3VzKS0/KFxcdyspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXN1c1xuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgL1xcKGJiMTA7XFxzKFxcdyspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBCbGFja0JlcnJ5IDEwXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdCbGFja0JlcnJ5J10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBc3VzIFRhYmxldHNcbiAgICAgICAgICAgIC9hbmRyb2lkLisodHJhbnNmb1twcmltZVxcc117NCwxMH1cXHNcXHcrfGVlZXBjfHNsaWRlclxcc1xcdyt8bmV4dXMgN3xwYWRmb25lKS9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdBc3VzJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvKHNvbnkpXFxzKHRhYmxldFxcc1twc10pXFxzYnVpbGRcXC8vaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29ueVxuICAgICAgICAgICAgLyhzb255KT8oPzpzZ3AuKylcXHNidWlsZFxcLy9pXG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ1NvbnknXSwgW01PREVMLCAnWHBlcmlhIFRhYmxldCddLCBbVFlQRSwgVEFCTEVUXV0sIFtcbiAgICAgICAgICAgIC9hbmRyb2lkLitcXHMoW2MtZ11cXGR7NH18c29bLWxdXFx3KylcXHNidWlsZFxcLy9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTb255J10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvXFxzKG91eWEpXFxzL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3V5YVxuICAgICAgICAgICAgLyhuaW50ZW5kbylcXHMoW3dpZHMzdV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTmludGVuZG9cbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgQ09OU09MRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLis7XFxzKHNoaWVsZClcXHNidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOdmlkaWFcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ052aWRpYSddLCBbVFlQRSwgQ09OU09MRV1dLCBbXG5cbiAgICAgICAgICAgIC8ocGxheXN0YXRpb25cXHNbMzRwb3J0YWJsZXZpXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBsYXlzdGF0aW9uXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTb255J10sIFtUWVBFLCBDT05TT0xFXV0sIFtcblxuICAgICAgICAgICAgLyhzcHJpbnRcXHMoXFx3KykpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNwcmludCBQaG9uZXNcbiAgICAgICAgICAgIF0sIFtbVkVORE9SLCBtYXBwZXIuc3RyLCBtYXBzLmRldmljZS5zcHJpbnQudmVuZG9yXSwgW01PREVMLCBtYXBwZXIuc3RyLCBtYXBzLmRldmljZS5zcHJpbnQubW9kZWxdLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhsZW5vdm8pXFxzPyhTKD86NTAwMHw2MDAwKSsoPzpbLV1bXFx3K10pKS9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExlbm92byB0YWJsZXRzXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC8oaHRjKVs7X1xccy1dKyhbXFx3XFxzXSsoPz1cXCkpfFxcdyspKi9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIVENcbiAgICAgICAgICAgIC8oenRlKS0oXFx3KykqL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFpURVxuICAgICAgICAgICAgLyhhbGNhdGVsfGdlZWtzcGhvbmV8bGVub3ZvfG5leGlhbnxwYW5hc29uaWN8KD89O1xccylzb255KVtfXFxzLV0/KFtcXHctXSspKi9pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFsY2F0ZWwvR2Vla3NQaG9uZS9MZW5vdm8vTmV4aWFuL1BhbmFzb25pYy9Tb255XG4gICAgICAgICAgICBdLCBbVkVORE9SLCBbTU9ERUwsIC9fL2csICcgJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKG5leHVzXFxzOSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIVEMgTmV4dXMgOVxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnSFRDJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvZFxcL2h1YXdlaShbXFx3XFxzLV0rKVs7XFwpXS9pLFxuICAgICAgICAgICAgLyhuZXh1c1xcczZwKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSHVhd2VpXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdIdWF3ZWknXSwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC8obWljcm9zb2Z0KTtcXHMobHVtaWFbXFxzXFx3XSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWljcm9zb2Z0IEx1bWlhXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC9bXFxzXFwoO10oeGJveCg/Olxcc29uZSk/KVtcXHNcXCk7XS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNaWNyb3NvZnQgWGJveFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnTWljcm9zb2Z0J10sIFtUWVBFLCBDT05TT0xFXV0sIFtcbiAgICAgICAgICAgIC8oa2luXFwuW29uZXR3XXszfSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1pY3Jvc29mdCBLaW5cbiAgICAgICAgICAgIF0sIFtbTU9ERUwsIC9cXC4vZywgJyAnXSwgW1ZFTkRPUiwgJ01pY3Jvc29mdCddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNb3Rvcm9sYVxuICAgICAgICAgICAgL1xccyhtaWxlc3RvbmV8ZHJvaWQoPzpbMi00eF18XFxzKD86YmlvbmljfHgyfHByb3xyYXpyKSk/KDo/XFxzNGcpPylbXFx3XFxzXStidWlsZFxcLy9pLFxuICAgICAgICAgICAgL21vdFtcXHMtXT8oXFx3KykqL2ksXG4gICAgICAgICAgICAvKFhUXFxkezMsNH0pIGJ1aWxkXFwvL2ksXG4gICAgICAgICAgICAvKG5leHVzXFxzNikvaVxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnTW90b3JvbGEnXSwgW1RZUEUsIE1PQklMRV1dLCBbXG4gICAgICAgICAgICAvYW5kcm9pZC4rXFxzKG16NjBcXGR8eG9vbVtcXHMyXXswLDJ9KVxcc2J1aWxkXFwvL2lcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ01vdG9yb2xhJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvaGJidHZcXC9cXGQrXFwuXFxkK1xcLlxcZCtcXHMrXFwoW1xcd1xcc10qO1xccyooXFx3W147XSopOyhbXjtdKikvaSAgICAgICAgICAgIC8vIEhiYlRWIGRldmljZXNcbiAgICAgICAgICAgIF0sIFtbVkVORE9SLCB1dGlsLnRyaW1dLCBbTU9ERUwsIHV0aWwudHJpbV0sIFtUWVBFLCBTTUFSVFRWXV0sIFtcblxuICAgICAgICAgICAgL2hiYnR2LittYXBsZTsoXFxkKykvaVxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgL14vLCAnU21hcnRUViddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgU01BUlRUVl1dLCBbXG5cbiAgICAgICAgICAgIC9cXChkdHZbXFwpO10uKyhhcXVvcykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTaGFycFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnU2hhcnAnXSwgW1RZUEUsIFNNQVJUVFZdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rKChzY2gtaVs4OV0wXFxkfHNody1tMzgwc3xndC1wXFxkezR9fGd0LW5cXGQrfHNnaC10OFs1Nl05fG5leHVzIDEwKSkvaSxcbiAgICAgICAgICAgIC8oKFNNLVRcXHcrKSkvaVxuICAgICAgICAgICAgXSwgW1tWRU5ET1IsICdTYW1zdW5nJ10sIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFsgICAgICAgICAgICAgICAgICAvLyBTYW1zdW5nXG4gICAgICAgICAgICAvc21hcnQtdHYuKyhzYW1zdW5nKS9pXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBbVFlQRSwgU01BUlRUVl0sIE1PREVMXSwgW1xuICAgICAgICAgICAgLygoc1tjZ3BdaC1cXHcrfGd0LVxcdyt8Z2FsYXh5XFxzbmV4dXN8c20tXFx3W1xcd1xcZF0rKSkvaSxcbiAgICAgICAgICAgIC8oc2FtW3N1bmddKilbXFxzLV0qKFxcdystP1tcXHctXSopKi9pLFxuICAgICAgICAgICAgL3NlYy0oKHNnaFxcdyspKS9pXG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ1NhbXN1bmcnXSwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvc2llLShcXHcrKSovaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTaWVtZW5zXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTaWVtZW5zJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKG1hZW1vfG5va2lhKS4qKG45MDB8bHVtaWFcXHNcXGQrKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm9raWFcbiAgICAgICAgICAgIC8obm9raWEpW1xcc18tXT8oW1xcdy1dKykqL2lcbiAgICAgICAgICAgIF0sIFtbVkVORE9SLCAnTm9raWEnXSwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZFxcczNcXC5bXFxzXFx3Oy1dezEwfShhXFxkezN9KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWNlclxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnQWNlciddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKyhbdmxda1xcLT9cXGR7M30pXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBMRyBUYWJsZXRcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0xHJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgL2FuZHJvaWRcXHMzXFwuW1xcc1xcdzstXXsxMH0obGc/KS0oWzA2Y3Y5XXszLDR9KS9pICAgICAgICAgICAgICAgICAgICAgLy8gTEcgVGFibGV0XG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ0xHJ10sIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFtcbiAgICAgICAgICAgIC8obGcpIG5ldGNhc3RcXC50di9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExHIFNtYXJ0VFZcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgU01BUlRUVl1dLCBbXG4gICAgICAgICAgICAvKG5leHVzXFxzWzQ1XSkvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBMR1xuICAgICAgICAgICAgL2xnW2U7XFxzXFwvLV0rKFxcdyspKi9pLFxuICAgICAgICAgICAgL2FuZHJvaWQuK2xnKFxcLT9bXFxkXFx3XSspXFxzK2J1aWxkL2lcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0xHJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rKGlkZWF0YWJbYS16MC05XFwtXFxzXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTGVub3ZvXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdMZW5vdm8nXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9saW51eDsuKygoam9sbGEpKTsvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSm9sbGFcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLygocGViYmxlKSlhcHBcXC9bXFxkXFwuXStcXHMvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUGViYmxlXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIFdFQVJBQkxFXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKztcXHMob3BwbylcXHM/KFtcXHdcXHNdKylcXHNidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9QUE9cbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgL2Nya2V5L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBHb29nbGUgQ2hyb21lY2FzdFxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0Nocm9tZWNhc3QnXSwgW1ZFTkRPUiwgJ0dvb2dsZSddXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rO1xccyhnbGFzcylcXHNcXGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdvb2dsZSBHbGFzc1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnR29vZ2xlJ10sIFtUWVBFLCBXRUFSQUJMRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLis7XFxzKHBpeGVsIGMpXFxzL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBHb29nbGUgUGl4ZWwgQ1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnR29vZ2xlJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rO1xccyhwaXhlbCB4bHxwaXhlbClcXHMvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR29vZ2xlIFBpeGVsXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdHb29nbGUnXSwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLisoXFx3KylcXHMrYnVpbGRcXC9obVxcMS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFhpYW9taSBIb25nbWkgJ251bWVyaWMnIG1vZGVsc1xuICAgICAgICAgICAgL2FuZHJvaWQuKyhobVtcXHNcXC1fXSpub3RlP1tcXHNfXSooPzpcXGRcXHcpPylcXHMrYnVpbGQvaSwgICAgICAgICAgICAgICAvLyBYaWFvbWkgSG9uZ21pXG4gICAgICAgICAgICAvYW5kcm9pZC4rKG1pW1xcc1xcLV9dKig/Om9uZXxvbmVbXFxzX11wbHVzfG5vdGUgbHRlKT9bXFxzX10qKD86XFxkXFx3KT8pXFxzK2J1aWxkL2ksICAgIC8vIFhpYW9taSBNaVxuICAgICAgICAgICAgL2FuZHJvaWQuKyhyZWRtaVtcXHNcXC1fXSooPzpub3RlKT8oPzpbXFxzX10qW1xcd1xcc10rKT8pXFxzK2J1aWxkL2kgICAgICAvLyBSZWRtaSBQaG9uZXNcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsIC9fL2csICcgJ10sIFtWRU5ET1IsICdYaWFvbWknXSwgW1RZUEUsIE1PQklMRV1dLCBbXG4gICAgICAgICAgICAvYW5kcm9pZC4rKG1pW1xcc1xcLV9dKig/OnBhZCk/KD86W1xcc19dKltcXHdcXHNdKyk/KVxccytidWlsZC9pICAgICAgICAgIC8vIE1pIFBhZCB0YWJsZXRzXG4gICAgICAgICAgICBdLFtbTU9ERUwsIC9fL2csICcgJ10sIFtWRU5ET1IsICdYaWFvbWknXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG4gICAgICAgICAgICAvYW5kcm9pZC4rO1xccyhtWzEtNV1cXHNub3RlKVxcc2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1laXp1IFRhYmxldFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnTWVpenUnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLithMDAwKDEpXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9uZVBsdXNcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ09uZVBsdXMnXSwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKFJDVFtcXGRcXHddKylcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSQ0EgVGFibGV0c1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnUkNBJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKihWZW51ZVtcXGRcXHNdKilcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRGVsbCBWZW51ZSBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdEZWxsJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKihRW1R8TV1bXFxkXFx3XSspXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVmVyaXpvbiBUYWJsZXRcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ1Zlcml6b24nXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMrKEJhcm5lc1smXFxzXStOb2JsZVxccyt8Qk5bUlRdKShWPy4qKVxccytidWlsZC9pICAgICAvLyBCYXJuZXMgJiBOb2JsZSBUYWJsZXRcbiAgICAgICAgICAgIF0sIFtbVkVORE9SLCAnQmFybmVzICYgTm9ibGUnXSwgTU9ERUwsIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKyhUTVxcZHszfS4qXFxiKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQmFybmVzICYgTm9ibGUgVGFibGV0XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdOdVZpc2lvbiddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooenRlKT8uKyhrXFxkezJ9KVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgLy8gWlRFIEsgU2VyaWVzIFRhYmxldFxuICAgICAgICAgICAgXSwgW1tWRU5ET1IsICdaVEUnXSwgTU9ERUwsIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKihnZW5cXGR7M30pXFxzK2J1aWxkLio0OWgvaSAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTd2lzcyBHRU4gTW9iaWxlXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTd2lzcyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooenVyXFxkezN9KVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3dpc3MgWlVSIFRhYmxldFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnU3dpc3MnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKChaZWtpKT9UQi4qXFxiKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFpla2kgVGFibGV0c1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnWmVraSddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgLyhhbmRyb2lkKS4rWztcXC9dXFxzKyhbWVJdXFxkezJ9eD8uKilcXHMrYnVpbGQvaSxcbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMrKERyYWdvbltcXC1cXHNdK1RvdWNoXFxzK3xEVCkoLispXFxzK2J1aWxkL2kgICAgICAgICAgLy8gRHJhZ29uIFRvdWNoIFRhYmxldFxuICAgICAgICAgICAgXSwgW1tWRU5ET1IsICdEcmFnb24gVG91Y2gnXSwgTU9ERUwsIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKihOUy0/LispXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluc2lnbmlhIFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0luc2lnbmlhJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKigoTlh8TmV4dCktPy4rKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5leHRCb29rIFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ05leHRCb29rJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKihYdHJlbWVcXF8/KT8oVigxWzA0NV18MlswMTVdfDMwfDQwfDYwfDdbMDVdfDkwKSlcXHMrYnVpbGQvaVxuICAgICAgICAgICAgXSwgW1tWRU5ET1IsICdWb2ljZSddLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbICAgICAgICAgICAgICAgICAgICAvLyBWb2ljZSBYdHJlbWUgUGhvbmVzXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKExWVEVMXFwtPyk/KFYxWzEyXSlcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgIC8vIEx2VGVsIFBob25lc1xuICAgICAgICAgICAgXSwgW1tWRU5ET1IsICdMdlRlbCddLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKFYoMTAwTUR8NzAwTkF8NzAxMXw5MTdHKS4qXFxiKVxccytidWlsZC9pICAgICAgICAgIC8vIEVudml6ZW4gVGFibGV0c1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnRW52aXplbiddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooTGVbXFxzXFwtXStQYW4pW1xcc1xcLV0rKC4qXFxiKVxccytidWlsZC9pICAgICAgICAgICAgIC8vIExlIFBhbiBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKFRyaW9bXFxzXFwtXSouKilcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYWNoU3BlZWQgVGFibGV0c1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnTWFjaFNwZWVkJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKihUcmluaXR5KVtcXC1cXHNdKihUXFxkezN9KVxccytidWlsZC9pICAgICAgICAgICAgICAgIC8vIFRyaW5pdHkgVGFibGV0c1xuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKlRVXygxNDkxKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJvdG9yIFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ1JvdG9yJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rKEtTKC4rKSlcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBbWF6b24gS2luZGxlIFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0FtYXpvbiddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKyhHaWdhc2V0KVtcXHNcXC1dKyhRLispXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBHaWdhc2V0IFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL1xccyh0YWJsZXR8dGFiKVs7XFwvXS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVuaWRlbnRpZmlhYmxlIFRhYmxldFxuICAgICAgICAgICAgL1xccyhtb2JpbGUpKD86WztcXC9dfFxcc3NhZmFyaSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBVbmlkZW50aWZpYWJsZSBNb2JpbGVcbiAgICAgICAgICAgIF0sIFtbVFlQRSwgdXRpbC5sb3dlcml6ZV0sIFZFTkRPUiwgTU9ERUxdLCBbXG5cbiAgICAgICAgICAgIC8oYW5kcm9pZC4rKVs7XFwvXS4rYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdlbmVyaWMgQW5kcm9pZCBEZXZpY2VcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0dlbmVyaWMnXV1cblxuXG4gICAgICAgIC8qLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgICAgICAgICAgIC8vIFRPRE86IG1vdmUgdG8gc3RyaW5nIG1hcFxuICAgICAgICAgICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG4gICAgICAgICAgICAvKEM2NjAzKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvbnkgWHBlcmlhIFogQzY2MDNcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdYcGVyaWEgWiBDNjYwMyddLCBbVkVORE9SLCAnU29ueSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oQzY5MDMpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29ueSBYcGVyaWEgWiAxXG4gICAgICAgICAgICBdLCBbW01PREVMLCAnWHBlcmlhIFogMSddLCBbVkVORE9SLCAnU29ueSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhTTS1HOTAwW0Z8SF0pL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYW1zdW5nIEdhbGF4eSBTNVxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBTNSddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oU00tRzcxMDIpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZyBHYWxheHkgR3JhbmQgMlxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBHcmFuZCAyJ10sIFtWRU5ET1IsICdTYW1zdW5nJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhTTS1HNTMwSCkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYW1zdW5nIEdhbGF4eSBHcmFuZCBQcmltZVxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBHcmFuZCBQcmltZSddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oU00tRzMxM0haKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZyBHYWxheHkgVlxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBWJ10sIFtWRU5ET1IsICdTYW1zdW5nJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhTTS1UODA1KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYW1zdW5nIEdhbGF4eSBUYWIgUyAxMC41XG4gICAgICAgICAgICBdLCBbW01PREVMLCAnR2FsYXh5IFRhYiBTIDEwLjUnXSwgW1ZFTkRPUiwgJ1NhbXN1bmcnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG4gICAgICAgICAgICAvKFNNLUc4MDBGKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNhbXN1bmcgR2FsYXh5IFM1IE1pbmlcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdHYWxheHkgUzUgTWluaSddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oU00tVDMxMSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZyBHYWxheHkgVGFiIDMgOC4wXG4gICAgICAgICAgICBdLCBbW01PREVMLCAnR2FsYXh5IFRhYiAzIDguMCddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgLyhUM0MpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZHZhbiBWYW5kcm9pZCBUM0NcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0FkdmFuJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhBRFZBTiBUMUpcXCspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWR2YW4gVmFuZHJvaWQgVDFKK1xuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ1ZhbmRyb2lkIFQxSisnXSwgW1ZFTkRPUiwgJ0FkdmFuJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhBRFZBTiBTNEEpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZHZhbiBWYW5kcm9pZCBTNEFcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdWYW5kcm9pZCBTNEEnXSwgW1ZFTkRPUiwgJ0FkdmFuJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKFY5NzJNKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFpURSBWOTcyTVxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnWlRFJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKGktbW9iaWxlKVxccyhJUVxcc1tcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpLW1vYmlsZSBJUVxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhJUTYuMykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpLW1vYmlsZSBJUSBJUSA2LjNcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdJUSA2LjMnXSwgW1ZFTkRPUiwgJ2ktbW9iaWxlJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhpLW1vYmlsZSlcXHMoaS1zdHlsZVxcc1tcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaS1tb2JpbGUgaS1TVFlMRVxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhpLVNUWUxFMi4xKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpLW1vYmlsZSBpLVNUWUxFIDIuMVxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ2ktU1RZTEUgMi4xJ10sIFtWRU5ET1IsICdpLW1vYmlsZSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhtb2JpaXN0YXIgdG91Y2ggTEFJIDUxMikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtb2JpaXN0YXIgdG91Y2ggTEFJIDUxMlxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ1RvdWNoIExBSSA1MTInXSwgW1ZFTkRPUiwgJ21vYmlpc3RhciddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLy8vLy8vLy8vLy8vL1xuICAgICAgICAgICAgLy8gRU5EIFRPRE9cbiAgICAgICAgICAgIC8vLy8vLy8vLy8vKi9cblxuICAgICAgICBdLFxuXG4gICAgICAgIGVuZ2luZSA6IFtbXG5cbiAgICAgICAgICAgIC93aW5kb3dzLitcXHNlZGdlXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEVkZ2VIVE1MXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgW05BTUUsICdFZGdlSFRNTCddXSwgW1xuXG4gICAgICAgICAgICAvKHByZXN0bylcXC8oW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFByZXN0b1xuICAgICAgICAgICAgLyh3ZWJraXR8dHJpZGVudHxuZXRmcm9udHxuZXRzdXJmfGFtYXlhfGx5bnh8dzNtKVxcLyhbXFx3XFwuXSspL2ksICAgICAvLyBXZWJLaXQvVHJpZGVudC9OZXRGcm9udC9OZXRTdXJmL0FtYXlhL0x5bngvdzNtXG4gICAgICAgICAgICAvKGtodG1sfHRhc21hbnxsaW5rcylbXFwvXFxzXVxcKD8oW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gS0hUTUwvVGFzbWFuL0xpbmtzXG4gICAgICAgICAgICAvKGljYWIpW1xcL1xcc10oWzIzXVxcLltcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaUNhYlxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC9ydlxcOihbXFx3XFwuXSspLiooZ2Vja28pL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR2Vja29cbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBOQU1FXVxuICAgICAgICBdLFxuXG4gICAgICAgIG9zIDogW1tcblxuICAgICAgICAgICAgLy8gV2luZG93cyBiYXNlZFxuICAgICAgICAgICAgL21pY3Jvc29mdFxccyh3aW5kb3dzKVxccyh2aXN0YXx4cCkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpbmRvd3MgKGlUdW5lcylcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuICAgICAgICAgICAgLyh3aW5kb3dzKVxcc250XFxzNlxcLjI7XFxzKGFybSkvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2luZG93cyBSVFxuICAgICAgICAgICAgLyh3aW5kb3dzXFxzcGhvbmUoPzpcXHNvcykqKVtcXHNcXC9dPyhbXFxkXFwuXFxzXStcXHcpKi9pLCAgICAgICAgICAgICAgICAgIC8vIFdpbmRvd3MgUGhvbmVcbiAgICAgICAgICAgIC8od2luZG93c1xcc21vYmlsZXx3aW5kb3dzKVtcXHNcXC9dPyhbbnRjZVxcZFxcLlxcc10rXFx3KS9pXG4gICAgICAgICAgICBdLCBbTkFNRSwgW1ZFUlNJT04sIG1hcHBlci5zdHIsIG1hcHMub3Mud2luZG93cy52ZXJzaW9uXV0sIFtcbiAgICAgICAgICAgIC8od2luKD89M3w5fG4pfHdpblxcczl4XFxzKShbbnRcXGRcXC5dKykvaVxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnV2luZG93cyddLCBbVkVSU0lPTiwgbWFwcGVyLnN0ciwgbWFwcy5vcy53aW5kb3dzLnZlcnNpb25dXSwgW1xuXG4gICAgICAgICAgICAvLyBNb2JpbGUvRW1iZWRkZWQgT1NcbiAgICAgICAgICAgIC9cXCgoYmIpKDEwKTsvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJsYWNrQmVycnkgMTBcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0JsYWNrQmVycnknXSwgVkVSU0lPTl0sIFtcbiAgICAgICAgICAgIC8oYmxhY2tiZXJyeSlcXHcqXFwvPyhbXFx3XFwuXSspKi9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJsYWNrYmVycnlcbiAgICAgICAgICAgIC8odGl6ZW4pW1xcL1xcc10oW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRpemVuXG4gICAgICAgICAgICAvKGFuZHJvaWR8d2Vib3N8cGFsbVxcc29zfHFueHxiYWRhfHJpbVxcc3RhYmxldFxcc29zfG1lZWdvfGNvbnRpa2kpW1xcL1xccy1dPyhbXFx3XFwuXSspKi9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBbmRyb2lkL1dlYk9TL1BhbG0vUU5YL0JhZGEvUklNL01lZUdvL0NvbnRpa2lcbiAgICAgICAgICAgIC9saW51eDsuKyhzYWlsZmlzaCk7L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2FpbGZpc2ggT1NcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuICAgICAgICAgICAgLyhzeW1iaWFuXFxzP29zfHN5bWJvc3xzNjAoPz07KSlbXFwvXFxzLV0/KFtcXHdcXC5dKykqL2kgICAgICAgICAgICAgICAgIC8vIFN5bWJpYW5cbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ1N5bWJpYW4nXSwgVkVSU0lPTl0sIFtcbiAgICAgICAgICAgIC9cXCgoc2VyaWVzNDApOy9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNlcmllcyA0MFxuICAgICAgICAgICAgXSwgW05BTUVdLCBbXG4gICAgICAgICAgICAvbW96aWxsYS4rXFwobW9iaWxlOy4rZ2Vja28uK2ZpcmVmb3gvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94IE9TXG4gICAgICAgICAgICBdLCBbW05BTUUsICdGaXJlZm94IE9TJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8vIENvbnNvbGVcbiAgICAgICAgICAgIC8obmludGVuZG98cGxheXN0YXRpb24pXFxzKFt3aWRzMzRwb3J0YWJsZXZ1XSspL2ksICAgICAgICAgICAgICAgICAgIC8vIE5pbnRlbmRvL1BsYXlzdGF0aW9uXG5cbiAgICAgICAgICAgIC8vIEdOVS9MaW51eCBiYXNlZFxuICAgICAgICAgICAgLyhtaW50KVtcXC9cXHNcXChdPyhcXHcrKSovaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWludFxuICAgICAgICAgICAgLyhtYWdlaWF8dmVjdG9ybGludXgpWztcXHNdL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWFnZWlhL1ZlY3RvckxpbnV4XG4gICAgICAgICAgICAvKGpvbGl8W2t4bG5dP3VidW50dXxkZWJpYW58W29wZW5dKnN1c2V8Z2VudG9vfCg/PVxccylhcmNofHNsYWNrd2FyZXxmZWRvcmF8bWFuZHJpdmF8Y2VudG9zfHBjbGludXhvc3xyZWRoYXR8emVud2Fsa3xsaW5wdXMpW1xcL1xccy1dPyg/IWNocm9tKShbXFx3XFwuLV0rKSovaSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSm9saS9VYnVudHUvRGViaWFuL1NVU0UvR2VudG9vL0FyY2gvU2xhY2t3YXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZlZG9yYS9NYW5kcml2YS9DZW50T1MvUENMaW51eE9TL1JlZEhhdC9aZW53YWxrL0xpbnB1c1xuICAgICAgICAgICAgLyhodXJkfGxpbnV4KVxccz8oW1xcd1xcLl0rKSovaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIdXJkL0xpbnV4XG4gICAgICAgICAgICAvKGdudSlcXHM/KFtcXHdcXC5dKykqL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdOVVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oY3JvcylcXHNbXFx3XStcXHMoW1xcd1xcLl0rXFx3KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hyb21pdW0gT1NcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0Nocm9taXVtIE9TJ10sIFZFUlNJT05dLFtcblxuICAgICAgICAgICAgLy8gU29sYXJpc1xuICAgICAgICAgICAgLyhzdW5vcylcXHM/KFtcXHdcXC5dK1xcZCkqL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29sYXJpc1xuICAgICAgICAgICAgXSwgW1tOQU1FLCAnU29sYXJpcyddLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvLyBCU0QgYmFzZWRcbiAgICAgICAgICAgIC9cXHMoW2ZyZW50b3BjLV17MCw0fWJzZHxkcmFnb25mbHkpXFxzPyhbXFx3XFwuXSspKi9pICAgICAgICAgICAgICAgICAgIC8vIEZyZWVCU0QvTmV0QlNEL09wZW5CU0QvUEMtQlNEL0RyYWdvbkZseVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLFtcblxuICAgICAgICAgICAgLyhoYWlrdSlcXHMoXFx3KykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSGFpa3VcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSxbXG5cbiAgICAgICAgICAgIC9jZm5ldHdvcmtcXC8uK2Rhcndpbi9pLFxuICAgICAgICAgICAgL2lwW2hvbmVhZF0rKD86Lipvc1xccyhbXFx3XSspXFxzbGlrZVxcc21hY3w7XFxzb3BlcmEpL2kgICAgICAgICAgICAgICAgIC8vIGlPU1xuICAgICAgICAgICAgXSwgW1tWRVJTSU9OLCAvXy9nLCAnLiddLCBbTkFNRSwgJ2lPUyddXSwgW1xuXG4gICAgICAgICAgICAvKG1hY1xcc29zXFxzeClcXHM/KFtcXHdcXHNcXC5dK1xcdykqL2ksXG4gICAgICAgICAgICAvKG1hY2ludG9zaHxtYWMoPz1fcG93ZXJwYylcXHMpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYWMgT1NcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ01hYyBPUyddLCBbVkVSU0lPTiwgL18vZywgJy4nXV0sIFtcblxuICAgICAgICAgICAgLy8gT3RoZXJcbiAgICAgICAgICAgIC8oKD86b3Blbik/c29sYXJpcylbXFwvXFxzLV0/KFtcXHdcXC5dKykqL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvbGFyaXNcbiAgICAgICAgICAgIC8oYWl4KVxccygoXFxkKSg/PVxcLnxcXCl8XFxzKVtcXHdcXC5dKikqL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFJWFxuICAgICAgICAgICAgLyhwbGFuXFxzOXxtaW5peHxiZW9zfG9zXFwvMnxhbWlnYW9zfG1vcnBob3N8cmlzY1xcc29zfG9wZW52bXMpL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBsYW45L01pbml4L0JlT1MvT1MyL0FtaWdhT1MvTW9ycGhPUy9SSVNDT1MvT3BlblZNU1xuICAgICAgICAgICAgLyh1bml4KVxccz8oW1xcd1xcLl0rKSovaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBVTklYXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl1cbiAgICAgICAgXVxuICAgIH07XG5cblxuICAgIC8vLy8vLy8vLy8vLy8vLy8vXG4gICAgLy8gQ29uc3RydWN0b3JcbiAgICAvLy8vLy8vLy8vLy8vLy8vXG4gICAgLypcbiAgICB2YXIgQnJvd3NlciA9IGZ1bmN0aW9uIChuYW1lLCB2ZXJzaW9uKSB7XG4gICAgICAgIHRoaXNbTkFNRV0gPSBuYW1lO1xuICAgICAgICB0aGlzW1ZFUlNJT05dID0gdmVyc2lvbjtcbiAgICB9O1xuICAgIHZhciBDUFUgPSBmdW5jdGlvbiAoYXJjaCkge1xuICAgICAgICB0aGlzW0FSQ0hJVEVDVFVSRV0gPSBhcmNoO1xuICAgIH07XG4gICAgdmFyIERldmljZSA9IGZ1bmN0aW9uICh2ZW5kb3IsIG1vZGVsLCB0eXBlKSB7XG4gICAgICAgIHRoaXNbVkVORE9SXSA9IHZlbmRvcjtcbiAgICAgICAgdGhpc1tNT0RFTF0gPSBtb2RlbDtcbiAgICAgICAgdGhpc1tUWVBFXSA9IHR5cGU7XG4gICAgfTtcbiAgICB2YXIgRW5naW5lID0gQnJvd3NlcjtcbiAgICB2YXIgT1MgPSBCcm93c2VyO1xuICAgICovXG4gICAgdmFyIFVBUGFyc2VyID0gZnVuY3Rpb24gKHVhc3RyaW5nLCBleHRlbnNpb25zKSB7XG5cbiAgICAgICAgaWYgKHR5cGVvZiB1YXN0cmluZyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGV4dGVuc2lvbnMgPSB1YXN0cmluZztcbiAgICAgICAgICAgIHVhc3RyaW5nID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFVBUGFyc2VyKSkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBVQVBhcnNlcih1YXN0cmluZywgZXh0ZW5zaW9ucykuZ2V0UmVzdWx0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdWEgPSB1YXN0cmluZyB8fCAoKHdpbmRvdyAmJiB3aW5kb3cubmF2aWdhdG9yICYmIHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50KSA/IHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50IDogRU1QVFkpO1xuICAgICAgICB2YXIgcmd4bWFwID0gZXh0ZW5zaW9ucyA/IHV0aWwuZXh0ZW5kKHJlZ2V4ZXMsIGV4dGVuc2lvbnMpIDogcmVnZXhlcztcbiAgICAgICAgLy92YXIgYnJvd3NlciA9IG5ldyBCcm93c2VyKCk7XG4gICAgICAgIC8vdmFyIGNwdSA9IG5ldyBDUFUoKTtcbiAgICAgICAgLy92YXIgZGV2aWNlID0gbmV3IERldmljZSgpO1xuICAgICAgICAvL3ZhciBlbmdpbmUgPSBuZXcgRW5naW5lKCk7XG4gICAgICAgIC8vdmFyIG9zID0gbmV3IE9TKCk7XG5cbiAgICAgICAgdGhpcy5nZXRCcm93c2VyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGJyb3dzZXIgPSB7IG5hbWU6IHVuZGVmaW5lZCwgdmVyc2lvbjogdW5kZWZpbmVkIH07XG4gICAgICAgICAgICBtYXBwZXIucmd4LmNhbGwoYnJvd3NlciwgdWEsIHJneG1hcC5icm93c2VyKTtcbiAgICAgICAgICAgIGJyb3dzZXIubWFqb3IgPSB1dGlsLm1ham9yKGJyb3dzZXIudmVyc2lvbik7IC8vIGRlcHJlY2F0ZWRcbiAgICAgICAgICAgIHJldHVybiBicm93c2VyO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldENQVSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBjcHUgPSB7IGFyY2hpdGVjdHVyZTogdW5kZWZpbmVkIH07XG4gICAgICAgICAgICBtYXBwZXIucmd4LmNhbGwoY3B1LCB1YSwgcmd4bWFwLmNwdSk7XG4gICAgICAgICAgICByZXR1cm4gY3B1O1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldERldmljZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBkZXZpY2UgPSB7IHZlbmRvcjogdW5kZWZpbmVkLCBtb2RlbDogdW5kZWZpbmVkLCB0eXBlOiB1bmRlZmluZWQgfTtcbiAgICAgICAgICAgIG1hcHBlci5yZ3guY2FsbChkZXZpY2UsIHVhLCByZ3htYXAuZGV2aWNlKTtcbiAgICAgICAgICAgIHJldHVybiBkZXZpY2U7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ2V0RW5naW5lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGVuZ2luZSA9IHsgbmFtZTogdW5kZWZpbmVkLCB2ZXJzaW9uOiB1bmRlZmluZWQgfTtcbiAgICAgICAgICAgIG1hcHBlci5yZ3guY2FsbChlbmdpbmUsIHVhLCByZ3htYXAuZW5naW5lKTtcbiAgICAgICAgICAgIHJldHVybiBlbmdpbmU7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ2V0T1MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgb3MgPSB7IG5hbWU6IHVuZGVmaW5lZCwgdmVyc2lvbjogdW5kZWZpbmVkIH07XG4gICAgICAgICAgICBtYXBwZXIucmd4LmNhbGwob3MsIHVhLCByZ3htYXAub3MpO1xuICAgICAgICAgICAgcmV0dXJuIG9zO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldFJlc3VsdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgdWEgICAgICA6IHRoaXMuZ2V0VUEoKSxcbiAgICAgICAgICAgICAgICBicm93c2VyIDogdGhpcy5nZXRCcm93c2VyKCksXG4gICAgICAgICAgICAgICAgZW5naW5lICA6IHRoaXMuZ2V0RW5naW5lKCksXG4gICAgICAgICAgICAgICAgb3MgICAgICA6IHRoaXMuZ2V0T1MoKSxcbiAgICAgICAgICAgICAgICBkZXZpY2UgIDogdGhpcy5nZXREZXZpY2UoKSxcbiAgICAgICAgICAgICAgICBjcHUgICAgIDogdGhpcy5nZXRDUFUoKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5nZXRVQSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB1YTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5zZXRVQSA9IGZ1bmN0aW9uICh1YXN0cmluZykge1xuICAgICAgICAgICAgdWEgPSB1YXN0cmluZztcbiAgICAgICAgICAgIC8vYnJvd3NlciA9IG5ldyBCcm93c2VyKCk7XG4gICAgICAgICAgICAvL2NwdSA9IG5ldyBDUFUoKTtcbiAgICAgICAgICAgIC8vZGV2aWNlID0gbmV3IERldmljZSgpO1xuICAgICAgICAgICAgLy9lbmdpbmUgPSBuZXcgRW5naW5lKCk7XG4gICAgICAgICAgICAvL29zID0gbmV3IE9TKCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIFVBUGFyc2VyLlZFUlNJT04gPSBMSUJWRVJTSU9OO1xuICAgIFVBUGFyc2VyLkJST1dTRVIgPSB7XG4gICAgICAgIE5BTUUgICAgOiBOQU1FLFxuICAgICAgICBNQUpPUiAgIDogTUFKT1IsIC8vIGRlcHJlY2F0ZWRcbiAgICAgICAgVkVSU0lPTiA6IFZFUlNJT05cbiAgICB9O1xuICAgIFVBUGFyc2VyLkNQVSA9IHtcbiAgICAgICAgQVJDSElURUNUVVJFIDogQVJDSElURUNUVVJFXG4gICAgfTtcbiAgICBVQVBhcnNlci5ERVZJQ0UgPSB7XG4gICAgICAgIE1PREVMICAgOiBNT0RFTCxcbiAgICAgICAgVkVORE9SICA6IFZFTkRPUixcbiAgICAgICAgVFlQRSAgICA6IFRZUEUsXG4gICAgICAgIENPTlNPTEUgOiBDT05TT0xFLFxuICAgICAgICBNT0JJTEUgIDogTU9CSUxFLFxuICAgICAgICBTTUFSVFRWIDogU01BUlRUVixcbiAgICAgICAgVEFCTEVUICA6IFRBQkxFVCxcbiAgICAgICAgV0VBUkFCTEU6IFdFQVJBQkxFLFxuICAgICAgICBFTUJFRERFRDogRU1CRURERURcbiAgICB9O1xuICAgIFVBUGFyc2VyLkVOR0lORSA9IHtcbiAgICAgICAgTkFNRSAgICA6IE5BTUUsXG4gICAgICAgIFZFUlNJT04gOiBWRVJTSU9OXG4gICAgfTtcbiAgICBVQVBhcnNlci5PUyA9IHtcbiAgICAgICAgTkFNRSAgICA6IE5BTUUsXG4gICAgICAgIFZFUlNJT04gOiBWRVJTSU9OXG4gICAgfTtcbiAgICAvL1VBUGFyc2VyLlV0aWxzID0gdXRpbDtcblxuICAgIC8vLy8vLy8vLy8vXG4gICAgLy8gRXhwb3J0XG4gICAgLy8vLy8vLy8vL1xuXG5cbiAgICAvLyBjaGVjayBqcyBlbnZpcm9ubWVudFxuICAgIGlmICh0eXBlb2YoZXhwb3J0cykgIT09IFVOREVGX1RZUEUpIHtcbiAgICAgICAgLy8gbm9kZWpzIGVudlxuICAgICAgICBpZiAodHlwZW9mIG1vZHVsZSAhPT0gVU5ERUZfVFlQRSAmJiBtb2R1bGUuZXhwb3J0cykge1xuICAgICAgICAgICAgZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0gVUFQYXJzZXI7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVE9ETzogdGVzdCEhISEhISEhXG4gICAgICAgIC8qXG4gICAgICAgIGlmIChyZXF1aXJlICYmIHJlcXVpcmUubWFpbiA9PT0gbW9kdWxlICYmIHByb2Nlc3MpIHtcbiAgICAgICAgICAgIC8vIGNsaVxuICAgICAgICAgICAgdmFyIGpzb25pemUgPSBmdW5jdGlvbiAoYXJyKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlcyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgaW4gYXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlcy5wdXNoKG5ldyBVQVBhcnNlcihhcnJbaV0pLmdldFJlc3VsdCgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcHJvY2Vzcy5zdGRvdXQud3JpdGUoSlNPTi5zdHJpbmdpZnkocmVzLCBudWxsLCAyKSArICdcXG4nKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAocHJvY2Vzcy5zdGRpbi5pc1RUWSkge1xuICAgICAgICAgICAgICAgIC8vIHZpYSBhcmdzXG4gICAgICAgICAgICAgICAganNvbml6ZShwcm9jZXNzLmFyZ3Yuc2xpY2UoMikpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyB2aWEgcGlwZVxuICAgICAgICAgICAgICAgIHZhciBzdHIgPSAnJztcbiAgICAgICAgICAgICAgICBwcm9jZXNzLnN0ZGluLm9uKCdyZWFkYWJsZScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmVhZCA9IHByb2Nlc3Muc3RkaW4ucmVhZCgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVhZCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyICs9IHJlYWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBwcm9jZXNzLnN0ZGluLm9uKCdlbmQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGpzb25pemUoc3RyLnJlcGxhY2UoL1xcbiQvLCAnJykuc3BsaXQoJ1xcbicpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAqL1xuICAgICAgICBleHBvcnRzLlVBUGFyc2VyID0gVUFQYXJzZXI7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gcmVxdWlyZWpzIGVudiAob3B0aW9uYWwpXG4gICAgICAgIGlmICh0eXBlb2YoZGVmaW5lKSA9PT0gRlVOQ19UWVBFICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgICAgIGRlZmluZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFVBUGFyc2VyO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAod2luZG93KSB7XG4gICAgICAgICAgICAvLyBicm93c2VyIGVudlxuICAgICAgICAgICAgd2luZG93LlVBUGFyc2VyID0gVUFQYXJzZXI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBqUXVlcnkvWmVwdG8gc3BlY2lmaWMgKG9wdGlvbmFsKVxuICAgIC8vIE5vdGU6XG4gICAgLy8gICBJbiBBTUQgZW52IHRoZSBnbG9iYWwgc2NvcGUgc2hvdWxkIGJlIGtlcHQgY2xlYW4sIGJ1dCBqUXVlcnkgaXMgYW4gZXhjZXB0aW9uLlxuICAgIC8vICAgalF1ZXJ5IGFsd2F5cyBleHBvcnRzIHRvIGdsb2JhbCBzY29wZSwgdW5sZXNzIGpRdWVyeS5ub0NvbmZsaWN0KHRydWUpIGlzIHVzZWQsXG4gICAgLy8gICBhbmQgd2Ugc2hvdWxkIGNhdGNoIHRoYXQuXG4gICAgdmFyICQgPSB3aW5kb3cgJiYgKHdpbmRvdy5qUXVlcnkgfHwgd2luZG93LlplcHRvKTtcbiAgICBpZiAodHlwZW9mICQgIT09IFVOREVGX1RZUEUpIHtcbiAgICAgICAgdmFyIHBhcnNlciA9IG5ldyBVQVBhcnNlcigpO1xuICAgICAgICAkLnVhID0gcGFyc2VyLmdldFJlc3VsdCgpO1xuICAgICAgICAkLnVhLmdldCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZXIuZ2V0VUEoKTtcbiAgICAgICAgfTtcbiAgICAgICAgJC51YS5zZXQgPSBmdW5jdGlvbiAodWFzdHJpbmcpIHtcbiAgICAgICAgICAgIHBhcnNlci5zZXRVQSh1YXN0cmluZyk7XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gcGFyc2VyLmdldFJlc3VsdCgpO1xuICAgICAgICAgICAgZm9yICh2YXIgcHJvcCBpbiByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAkLnVhW3Byb3BdID0gcmVzdWx0W3Byb3BdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxufSkodHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcgPyB3aW5kb3cgOiB0aGlzKTtcbiIsInZhciB2MSA9IHJlcXVpcmUoJy4vdjEnKTtcbnZhciB2NCA9IHJlcXVpcmUoJy4vdjQnKTtcblxudmFyIHV1aWQgPSB2NDtcbnV1aWQudjEgPSB2MTtcbnV1aWQudjQgPSB2NDtcblxubW9kdWxlLmV4cG9ydHMgPSB1dWlkO1xuIiwiLyoqXG4gKiBDb252ZXJ0IGFycmF5IG9mIDE2IGJ5dGUgdmFsdWVzIHRvIFVVSUQgc3RyaW5nIGZvcm1hdCBvZiB0aGUgZm9ybTpcbiAqIFhYWFhYWFhYLVhYWFgtWFhYWC1YWFhYLVhYWFhYWFhYWFhYWFxuICovXG52YXIgYnl0ZVRvSGV4ID0gW107XG5mb3IgKHZhciBpID0gMDsgaSA8IDI1NjsgKytpKSB7XG4gIGJ5dGVUb0hleFtpXSA9IChpICsgMHgxMDApLnRvU3RyaW5nKDE2KS5zdWJzdHIoMSk7XG59XG5cbmZ1bmN0aW9uIGJ5dGVzVG9VdWlkKGJ1Ziwgb2Zmc2V0KSB7XG4gIHZhciBpID0gb2Zmc2V0IHx8IDA7XG4gIHZhciBidGggPSBieXRlVG9IZXg7XG4gIHJldHVybiBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gKyAnLScgK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dICsgJy0nICtcbiAgICAgICAgICBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArICctJyArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gKyAnLScgK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dICtcbiAgICAgICAgICBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYnl0ZXNUb1V1aWQ7XG4iLCIvLyBVbmlxdWUgSUQgY3JlYXRpb24gcmVxdWlyZXMgYSBoaWdoIHF1YWxpdHkgcmFuZG9tICMgZ2VuZXJhdG9yLiAgSW4gdGhlXG4vLyBicm93c2VyIHRoaXMgaXMgYSBsaXR0bGUgY29tcGxpY2F0ZWQgZHVlIHRvIHVua25vd24gcXVhbGl0eSBvZiBNYXRoLnJhbmRvbSgpXG4vLyBhbmQgaW5jb25zaXN0ZW50IHN1cHBvcnQgZm9yIHRoZSBgY3J5cHRvYCBBUEkuICBXZSBkbyB0aGUgYmVzdCB3ZSBjYW4gdmlhXG4vLyBmZWF0dXJlLWRldGVjdGlvblxudmFyIHJuZztcblxudmFyIGNyeXB0byA9IGdsb2JhbC5jcnlwdG8gfHwgZ2xvYmFsLm1zQ3J5cHRvOyAvLyBmb3IgSUUgMTFcbmlmIChjcnlwdG8gJiYgY3J5cHRvLmdldFJhbmRvbVZhbHVlcykge1xuICAvLyBXSEFUV0cgY3J5cHRvIFJORyAtIGh0dHA6Ly93aWtpLndoYXR3Zy5vcmcvd2lraS9DcnlwdG9cbiAgdmFyIHJuZHM4ID0gbmV3IFVpbnQ4QXJyYXkoMTYpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmXG4gIHJuZyA9IGZ1bmN0aW9uIHdoYXR3Z1JORygpIHtcbiAgICBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKHJuZHM4KTtcbiAgICByZXR1cm4gcm5kczg7XG4gIH07XG59XG5cbmlmICghcm5nKSB7XG4gIC8vIE1hdGgucmFuZG9tKCktYmFzZWQgKFJORylcbiAgLy9cbiAgLy8gSWYgYWxsIGVsc2UgZmFpbHMsIHVzZSBNYXRoLnJhbmRvbSgpLiAgSXQncyBmYXN0LCBidXQgaXMgb2YgdW5zcGVjaWZpZWRcbiAgLy8gcXVhbGl0eS5cbiAgdmFyIHJuZHMgPSBuZXcgQXJyYXkoMTYpO1xuICBybmcgPSBmdW5jdGlvbigpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgcjsgaSA8IDE2OyBpKyspIHtcbiAgICAgIGlmICgoaSAmIDB4MDMpID09PSAwKSByID0gTWF0aC5yYW5kb20oKSAqIDB4MTAwMDAwMDAwO1xuICAgICAgcm5kc1tpXSA9IHIgPj4+ICgoaSAmIDB4MDMpIDw8IDMpICYgMHhmZjtcbiAgICB9XG5cbiAgICByZXR1cm4gcm5kcztcbiAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBybmc7XG4iLCJ2YXIgcm5nID0gcmVxdWlyZSgnLi9saWIvcm5nJyk7XG52YXIgYnl0ZXNUb1V1aWQgPSByZXF1aXJlKCcuL2xpYi9ieXRlc1RvVXVpZCcpO1xuXG4vLyAqKmB2MSgpYCAtIEdlbmVyYXRlIHRpbWUtYmFzZWQgVVVJRCoqXG4vL1xuLy8gSW5zcGlyZWQgYnkgaHR0cHM6Ly9naXRodWIuY29tL0xpb3NLL1VVSUQuanNcbi8vIGFuZCBodHRwOi8vZG9jcy5weXRob24ub3JnL2xpYnJhcnkvdXVpZC5odG1sXG5cbi8vIHJhbmRvbSAjJ3Mgd2UgbmVlZCB0byBpbml0IG5vZGUgYW5kIGNsb2Nrc2VxXG52YXIgX3NlZWRCeXRlcyA9IHJuZygpO1xuXG4vLyBQZXIgNC41LCBjcmVhdGUgYW5kIDQ4LWJpdCBub2RlIGlkLCAoNDcgcmFuZG9tIGJpdHMgKyBtdWx0aWNhc3QgYml0ID0gMSlcbnZhciBfbm9kZUlkID0gW1xuICBfc2VlZEJ5dGVzWzBdIHwgMHgwMSxcbiAgX3NlZWRCeXRlc1sxXSwgX3NlZWRCeXRlc1syXSwgX3NlZWRCeXRlc1szXSwgX3NlZWRCeXRlc1s0XSwgX3NlZWRCeXRlc1s1XVxuXTtcblxuLy8gUGVyIDQuMi4yLCByYW5kb21pemUgKDE0IGJpdCkgY2xvY2tzZXFcbnZhciBfY2xvY2tzZXEgPSAoX3NlZWRCeXRlc1s2XSA8PCA4IHwgX3NlZWRCeXRlc1s3XSkgJiAweDNmZmY7XG5cbi8vIFByZXZpb3VzIHV1aWQgY3JlYXRpb24gdGltZVxudmFyIF9sYXN0TVNlY3MgPSAwLCBfbGFzdE5TZWNzID0gMDtcblxuLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9icm9vZmEvbm9kZS11dWlkIGZvciBBUEkgZGV0YWlsc1xuZnVuY3Rpb24gdjEob3B0aW9ucywgYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBidWYgJiYgb2Zmc2V0IHx8IDA7XG4gIHZhciBiID0gYnVmIHx8IFtdO1xuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gIHZhciBjbG9ja3NlcSA9IG9wdGlvbnMuY2xvY2tzZXEgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuY2xvY2tzZXEgOiBfY2xvY2tzZXE7XG5cbiAgLy8gVVVJRCB0aW1lc3RhbXBzIGFyZSAxMDAgbmFuby1zZWNvbmQgdW5pdHMgc2luY2UgdGhlIEdyZWdvcmlhbiBlcG9jaCxcbiAgLy8gKDE1ODItMTAtMTUgMDA6MDApLiAgSlNOdW1iZXJzIGFyZW4ndCBwcmVjaXNlIGVub3VnaCBmb3IgdGhpcywgc29cbiAgLy8gdGltZSBpcyBoYW5kbGVkIGludGVybmFsbHkgYXMgJ21zZWNzJyAoaW50ZWdlciBtaWxsaXNlY29uZHMpIGFuZCAnbnNlY3MnXG4gIC8vICgxMDAtbmFub3NlY29uZHMgb2Zmc2V0IGZyb20gbXNlY3MpIHNpbmNlIHVuaXggZXBvY2gsIDE5NzAtMDEtMDEgMDA6MDAuXG4gIHZhciBtc2VjcyA9IG9wdGlvbnMubXNlY3MgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubXNlY3MgOiBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuICAvLyBQZXIgNC4yLjEuMiwgdXNlIGNvdW50IG9mIHV1aWQncyBnZW5lcmF0ZWQgZHVyaW5nIHRoZSBjdXJyZW50IGNsb2NrXG4gIC8vIGN5Y2xlIHRvIHNpbXVsYXRlIGhpZ2hlciByZXNvbHV0aW9uIGNsb2NrXG4gIHZhciBuc2VjcyA9IG9wdGlvbnMubnNlY3MgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubnNlY3MgOiBfbGFzdE5TZWNzICsgMTtcblxuICAvLyBUaW1lIHNpbmNlIGxhc3QgdXVpZCBjcmVhdGlvbiAoaW4gbXNlY3MpXG4gIHZhciBkdCA9IChtc2VjcyAtIF9sYXN0TVNlY3MpICsgKG5zZWNzIC0gX2xhc3ROU2VjcykvMTAwMDA7XG5cbiAgLy8gUGVyIDQuMi4xLjIsIEJ1bXAgY2xvY2tzZXEgb24gY2xvY2sgcmVncmVzc2lvblxuICBpZiAoZHQgPCAwICYmIG9wdGlvbnMuY2xvY2tzZXEgPT09IHVuZGVmaW5lZCkge1xuICAgIGNsb2Nrc2VxID0gY2xvY2tzZXEgKyAxICYgMHgzZmZmO1xuICB9XG5cbiAgLy8gUmVzZXQgbnNlY3MgaWYgY2xvY2sgcmVncmVzc2VzIChuZXcgY2xvY2tzZXEpIG9yIHdlJ3ZlIG1vdmVkIG9udG8gYSBuZXdcbiAgLy8gdGltZSBpbnRlcnZhbFxuICBpZiAoKGR0IDwgMCB8fCBtc2VjcyA+IF9sYXN0TVNlY3MpICYmIG9wdGlvbnMubnNlY3MgPT09IHVuZGVmaW5lZCkge1xuICAgIG5zZWNzID0gMDtcbiAgfVxuXG4gIC8vIFBlciA0LjIuMS4yIFRocm93IGVycm9yIGlmIHRvbyBtYW55IHV1aWRzIGFyZSByZXF1ZXN0ZWRcbiAgaWYgKG5zZWNzID49IDEwMDAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd1dWlkLnYxKCk6IENhblxcJ3QgY3JlYXRlIG1vcmUgdGhhbiAxME0gdXVpZHMvc2VjJyk7XG4gIH1cblxuICBfbGFzdE1TZWNzID0gbXNlY3M7XG4gIF9sYXN0TlNlY3MgPSBuc2VjcztcbiAgX2Nsb2Nrc2VxID0gY2xvY2tzZXE7XG5cbiAgLy8gUGVyIDQuMS40IC0gQ29udmVydCBmcm9tIHVuaXggZXBvY2ggdG8gR3JlZ29yaWFuIGVwb2NoXG4gIG1zZWNzICs9IDEyMjE5MjkyODAwMDAwO1xuXG4gIC8vIGB0aW1lX2xvd2BcbiAgdmFyIHRsID0gKChtc2VjcyAmIDB4ZmZmZmZmZikgKiAxMDAwMCArIG5zZWNzKSAlIDB4MTAwMDAwMDAwO1xuICBiW2krK10gPSB0bCA+Pj4gMjQgJiAweGZmO1xuICBiW2krK10gPSB0bCA+Pj4gMTYgJiAweGZmO1xuICBiW2krK10gPSB0bCA+Pj4gOCAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRsICYgMHhmZjtcblxuICAvLyBgdGltZV9taWRgXG4gIHZhciB0bWggPSAobXNlY3MgLyAweDEwMDAwMDAwMCAqIDEwMDAwKSAmIDB4ZmZmZmZmZjtcbiAgYltpKytdID0gdG1oID4+PiA4ICYgMHhmZjtcbiAgYltpKytdID0gdG1oICYgMHhmZjtcblxuICAvLyBgdGltZV9oaWdoX2FuZF92ZXJzaW9uYFxuICBiW2krK10gPSB0bWggPj4+IDI0ICYgMHhmIHwgMHgxMDsgLy8gaW5jbHVkZSB2ZXJzaW9uXG4gIGJbaSsrXSA9IHRtaCA+Pj4gMTYgJiAweGZmO1xuXG4gIC8vIGBjbG9ja19zZXFfaGlfYW5kX3Jlc2VydmVkYCAoUGVyIDQuMi4yIC0gaW5jbHVkZSB2YXJpYW50KVxuICBiW2krK10gPSBjbG9ja3NlcSA+Pj4gOCB8IDB4ODA7XG5cbiAgLy8gYGNsb2NrX3NlcV9sb3dgXG4gIGJbaSsrXSA9IGNsb2Nrc2VxICYgMHhmZjtcblxuICAvLyBgbm9kZWBcbiAgdmFyIG5vZGUgPSBvcHRpb25zLm5vZGUgfHwgX25vZGVJZDtcbiAgZm9yICh2YXIgbiA9IDA7IG4gPCA2OyArK24pIHtcbiAgICBiW2kgKyBuXSA9IG5vZGVbbl07XG4gIH1cblxuICByZXR1cm4gYnVmID8gYnVmIDogYnl0ZXNUb1V1aWQoYik7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdjE7XG4iLCJ2YXIgcm5nID0gcmVxdWlyZSgnLi9saWIvcm5nJyk7XG52YXIgYnl0ZXNUb1V1aWQgPSByZXF1aXJlKCcuL2xpYi9ieXRlc1RvVXVpZCcpO1xuXG5mdW5jdGlvbiB2NChvcHRpb25zLCBidWYsIG9mZnNldCkge1xuICB2YXIgaSA9IGJ1ZiAmJiBvZmZzZXQgfHwgMDtcblxuICBpZiAodHlwZW9mKG9wdGlvbnMpID09ICdzdHJpbmcnKSB7XG4gICAgYnVmID0gb3B0aW9ucyA9PSAnYmluYXJ5JyA/IG5ldyBBcnJheSgxNikgOiBudWxsO1xuICAgIG9wdGlvbnMgPSBudWxsO1xuICB9XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gIHZhciBybmRzID0gb3B0aW9ucy5yYW5kb20gfHwgKG9wdGlvbnMucm5nIHx8IHJuZykoKTtcblxuICAvLyBQZXIgNC40LCBzZXQgYml0cyBmb3IgdmVyc2lvbiBhbmQgYGNsb2NrX3NlcV9oaV9hbmRfcmVzZXJ2ZWRgXG4gIHJuZHNbNl0gPSAocm5kc1s2XSAmIDB4MGYpIHwgMHg0MDtcbiAgcm5kc1s4XSA9IChybmRzWzhdICYgMHgzZikgfCAweDgwO1xuXG4gIC8vIENvcHkgYnl0ZXMgdG8gYnVmZmVyLCBpZiBwcm92aWRlZFxuICBpZiAoYnVmKSB7XG4gICAgZm9yICh2YXIgaWkgPSAwOyBpaSA8IDE2OyArK2lpKSB7XG4gICAgICBidWZbaSArIGlpXSA9IHJuZHNbaWldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBidWYgfHwgYnl0ZXNUb1V1aWQocm5kcyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdjQ7XG4iLCIvKlxuICogIENvcHlyaWdodCAoYykgMjAxNiBUaGUgV2ViUlRDIHByb2plY3QgYXV0aG9ycy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiAgVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYSBCU0Qtc3R5bGUgbGljZW5zZVxuICogIHRoYXQgY2FuIGJlIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3Qgb2YgdGhlIHNvdXJjZVxuICogIHRyZWUuXG4gKi9cbiAvKiBlc2xpbnQtZW52IG5vZGUgKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgYWRhcHRlckZhY3RvcnkgPSByZXF1aXJlKCcuL2FkYXB0ZXJfZmFjdG9yeS5qcycpO1xubW9kdWxlLmV4cG9ydHMgPSBhZGFwdGVyRmFjdG9yeSh7d2luZG93OiBnbG9iYWwud2luZG93fSk7XG4iLCIvKlxuICogIENvcHlyaWdodCAoYykgMjAxNiBUaGUgV2ViUlRDIHByb2plY3QgYXV0aG9ycy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiAgVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYSBCU0Qtc3R5bGUgbGljZW5zZVxuICogIHRoYXQgY2FuIGJlIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3Qgb2YgdGhlIHNvdXJjZVxuICogIHRyZWUuXG4gKi9cbiAvKiBlc2xpbnQtZW52IG5vZGUgKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbHMgPSByZXF1aXJlKCcuL3V0aWxzJyk7XG4vLyBTaGltbWluZyBzdGFydHMgaGVyZS5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZGVwZW5kZW5jaWVzLCBvcHRzKSB7XG4gIHZhciB3aW5kb3cgPSBkZXBlbmRlbmNpZXMgJiYgZGVwZW5kZW5jaWVzLndpbmRvdztcblxuICB2YXIgb3B0aW9ucyA9IHtcbiAgICBzaGltQ2hyb21lOiB0cnVlLFxuICAgIHNoaW1GaXJlZm94OiB0cnVlLFxuICAgIHNoaW1FZGdlOiB0cnVlLFxuICAgIHNoaW1TYWZhcmk6IHRydWUsXG4gIH07XG5cbiAgZm9yICh2YXIga2V5IGluIG9wdHMpIHtcbiAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChvcHRzLCBrZXkpKSB7XG4gICAgICBvcHRpb25zW2tleV0gPSBvcHRzW2tleV07XG4gICAgfVxuICB9XG5cbiAgLy8gVXRpbHMuXG4gIHZhciBsb2dnaW5nID0gdXRpbHMubG9nO1xuICB2YXIgYnJvd3NlckRldGFpbHMgPSB1dGlscy5kZXRlY3RCcm93c2VyKHdpbmRvdyk7XG5cbiAgLy8gVW5jb21tZW50IHRoZSBsaW5lIGJlbG93IGlmIHlvdSB3YW50IGxvZ2dpbmcgdG8gb2NjdXIsIGluY2x1ZGluZyBsb2dnaW5nXG4gIC8vIGZvciB0aGUgc3dpdGNoIHN0YXRlbWVudCBiZWxvdy4gQ2FuIGFsc28gYmUgdHVybmVkIG9uIGluIHRoZSBicm93c2VyIHZpYVxuICAvLyBhZGFwdGVyLmRpc2FibGVMb2coZmFsc2UpLCBidXQgdGhlbiBsb2dnaW5nIGZyb20gdGhlIHN3aXRjaCBzdGF0ZW1lbnQgYmVsb3dcbiAgLy8gd2lsbCBub3QgYXBwZWFyLlxuICAvLyByZXF1aXJlKCcuL3V0aWxzJykuZGlzYWJsZUxvZyhmYWxzZSk7XG5cbiAgLy8gQnJvd3NlciBzaGltcy5cbiAgdmFyIGNocm9tZVNoaW0gPSByZXF1aXJlKCcuL2Nocm9tZS9jaHJvbWVfc2hpbScpIHx8IG51bGw7XG4gIHZhciBlZGdlU2hpbSA9IHJlcXVpcmUoJy4vZWRnZS9lZGdlX3NoaW0nKSB8fCBudWxsO1xuICB2YXIgZmlyZWZveFNoaW0gPSByZXF1aXJlKCcuL2ZpcmVmb3gvZmlyZWZveF9zaGltJykgfHwgbnVsbDtcbiAgdmFyIHNhZmFyaVNoaW0gPSByZXF1aXJlKCcuL3NhZmFyaS9zYWZhcmlfc2hpbScpIHx8IG51bGw7XG4gIHZhciBjb21tb25TaGltID0gcmVxdWlyZSgnLi9jb21tb25fc2hpbScpIHx8IG51bGw7XG5cbiAgLy8gRXhwb3J0IHRvIHRoZSBhZGFwdGVyIGdsb2JhbCBvYmplY3QgdmlzaWJsZSBpbiB0aGUgYnJvd3Nlci5cbiAgdmFyIGFkYXB0ZXIgPSB7XG4gICAgYnJvd3NlckRldGFpbHM6IGJyb3dzZXJEZXRhaWxzLFxuICAgIGNvbW1vblNoaW06IGNvbW1vblNoaW0sXG4gICAgZXh0cmFjdFZlcnNpb246IHV0aWxzLmV4dHJhY3RWZXJzaW9uLFxuICAgIGRpc2FibGVMb2c6IHV0aWxzLmRpc2FibGVMb2csXG4gICAgZGlzYWJsZVdhcm5pbmdzOiB1dGlscy5kaXNhYmxlV2FybmluZ3NcbiAgfTtcblxuICAvLyBTaGltIGJyb3dzZXIgaWYgZm91bmQuXG4gIHN3aXRjaCAoYnJvd3NlckRldGFpbHMuYnJvd3Nlcikge1xuICAgIGNhc2UgJ2Nocm9tZSc6XG4gICAgICBpZiAoIWNocm9tZVNoaW0gfHwgIWNocm9tZVNoaW0uc2hpbVBlZXJDb25uZWN0aW9uIHx8XG4gICAgICAgICAgIW9wdGlvbnMuc2hpbUNocm9tZSkge1xuICAgICAgICBsb2dnaW5nKCdDaHJvbWUgc2hpbSBpcyBub3QgaW5jbHVkZWQgaW4gdGhpcyBhZGFwdGVyIHJlbGVhc2UuJyk7XG4gICAgICAgIHJldHVybiBhZGFwdGVyO1xuICAgICAgfVxuICAgICAgbG9nZ2luZygnYWRhcHRlci5qcyBzaGltbWluZyBjaHJvbWUuJyk7XG4gICAgICAvLyBFeHBvcnQgdG8gdGhlIGFkYXB0ZXIgZ2xvYmFsIG9iamVjdCB2aXNpYmxlIGluIHRoZSBicm93c2VyLlxuICAgICAgYWRhcHRlci5icm93c2VyU2hpbSA9IGNocm9tZVNoaW07XG4gICAgICBjb21tb25TaGltLnNoaW1DcmVhdGVPYmplY3RVUkwod2luZG93KTtcblxuICAgICAgY2hyb21lU2hpbS5zaGltR2V0VXNlck1lZGlhKHdpbmRvdyk7XG4gICAgICBjaHJvbWVTaGltLnNoaW1NZWRpYVN0cmVhbSh3aW5kb3cpO1xuICAgICAgY2hyb21lU2hpbS5zaGltU291cmNlT2JqZWN0KHdpbmRvdyk7XG4gICAgICBjaHJvbWVTaGltLnNoaW1QZWVyQ29ubmVjdGlvbih3aW5kb3cpO1xuICAgICAgY2hyb21lU2hpbS5zaGltT25UcmFjayh3aW5kb3cpO1xuICAgICAgY2hyb21lU2hpbS5zaGltQWRkVHJhY2tSZW1vdmVUcmFjayh3aW5kb3cpO1xuICAgICAgY2hyb21lU2hpbS5zaGltR2V0U2VuZGVyc1dpdGhEdG1mKHdpbmRvdyk7XG5cbiAgICAgIGNvbW1vblNoaW0uc2hpbVJUQ0ljZUNhbmRpZGF0ZSh3aW5kb3cpO1xuICAgICAgY29tbW9uU2hpbS5zaGltTWF4TWVzc2FnZVNpemUod2luZG93KTtcbiAgICAgIGNvbW1vblNoaW0uc2hpbVNlbmRUaHJvd1R5cGVFcnJvcih3aW5kb3cpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnZmlyZWZveCc6XG4gICAgICBpZiAoIWZpcmVmb3hTaGltIHx8ICFmaXJlZm94U2hpbS5zaGltUGVlckNvbm5lY3Rpb24gfHxcbiAgICAgICAgICAhb3B0aW9ucy5zaGltRmlyZWZveCkge1xuICAgICAgICBsb2dnaW5nKCdGaXJlZm94IHNoaW0gaXMgbm90IGluY2x1ZGVkIGluIHRoaXMgYWRhcHRlciByZWxlYXNlLicpO1xuICAgICAgICByZXR1cm4gYWRhcHRlcjtcbiAgICAgIH1cbiAgICAgIGxvZ2dpbmcoJ2FkYXB0ZXIuanMgc2hpbW1pbmcgZmlyZWZveC4nKTtcbiAgICAgIC8vIEV4cG9ydCB0byB0aGUgYWRhcHRlciBnbG9iYWwgb2JqZWN0IHZpc2libGUgaW4gdGhlIGJyb3dzZXIuXG4gICAgICBhZGFwdGVyLmJyb3dzZXJTaGltID0gZmlyZWZveFNoaW07XG4gICAgICBjb21tb25TaGltLnNoaW1DcmVhdGVPYmplY3RVUkwod2luZG93KTtcblxuICAgICAgZmlyZWZveFNoaW0uc2hpbUdldFVzZXJNZWRpYSh3aW5kb3cpO1xuICAgICAgZmlyZWZveFNoaW0uc2hpbVNvdXJjZU9iamVjdCh3aW5kb3cpO1xuICAgICAgZmlyZWZveFNoaW0uc2hpbVBlZXJDb25uZWN0aW9uKHdpbmRvdyk7XG4gICAgICBmaXJlZm94U2hpbS5zaGltT25UcmFjayh3aW5kb3cpO1xuICAgICAgZmlyZWZveFNoaW0uc2hpbVJlbW92ZVN0cmVhbSh3aW5kb3cpO1xuXG4gICAgICBjb21tb25TaGltLnNoaW1SVENJY2VDYW5kaWRhdGUod2luZG93KTtcbiAgICAgIGNvbW1vblNoaW0uc2hpbU1heE1lc3NhZ2VTaXplKHdpbmRvdyk7XG4gICAgICBjb21tb25TaGltLnNoaW1TZW5kVGhyb3dUeXBlRXJyb3Iod2luZG93KTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2VkZ2UnOlxuICAgICAgaWYgKCFlZGdlU2hpbSB8fCAhZWRnZVNoaW0uc2hpbVBlZXJDb25uZWN0aW9uIHx8ICFvcHRpb25zLnNoaW1FZGdlKSB7XG4gICAgICAgIGxvZ2dpbmcoJ01TIGVkZ2Ugc2hpbSBpcyBub3QgaW5jbHVkZWQgaW4gdGhpcyBhZGFwdGVyIHJlbGVhc2UuJyk7XG4gICAgICAgIHJldHVybiBhZGFwdGVyO1xuICAgICAgfVxuICAgICAgbG9nZ2luZygnYWRhcHRlci5qcyBzaGltbWluZyBlZGdlLicpO1xuICAgICAgLy8gRXhwb3J0IHRvIHRoZSBhZGFwdGVyIGdsb2JhbCBvYmplY3QgdmlzaWJsZSBpbiB0aGUgYnJvd3Nlci5cbiAgICAgIGFkYXB0ZXIuYnJvd3NlclNoaW0gPSBlZGdlU2hpbTtcbiAgICAgIGNvbW1vblNoaW0uc2hpbUNyZWF0ZU9iamVjdFVSTCh3aW5kb3cpO1xuXG4gICAgICBlZGdlU2hpbS5zaGltR2V0VXNlck1lZGlhKHdpbmRvdyk7XG4gICAgICBlZGdlU2hpbS5zaGltUGVlckNvbm5lY3Rpb24od2luZG93KTtcbiAgICAgIGVkZ2VTaGltLnNoaW1SZXBsYWNlVHJhY2sod2luZG93KTtcblxuICAgICAgLy8gdGhlIGVkZ2Ugc2hpbSBpbXBsZW1lbnRzIHRoZSBmdWxsIFJUQ0ljZUNhbmRpZGF0ZSBvYmplY3QuXG5cbiAgICAgIGNvbW1vblNoaW0uc2hpbU1heE1lc3NhZ2VTaXplKHdpbmRvdyk7XG4gICAgICBjb21tb25TaGltLnNoaW1TZW5kVGhyb3dUeXBlRXJyb3Iod2luZG93KTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3NhZmFyaSc6XG4gICAgICBpZiAoIXNhZmFyaVNoaW0gfHwgIW9wdGlvbnMuc2hpbVNhZmFyaSkge1xuICAgICAgICBsb2dnaW5nKCdTYWZhcmkgc2hpbSBpcyBub3QgaW5jbHVkZWQgaW4gdGhpcyBhZGFwdGVyIHJlbGVhc2UuJyk7XG4gICAgICAgIHJldHVybiBhZGFwdGVyO1xuICAgICAgfVxuICAgICAgbG9nZ2luZygnYWRhcHRlci5qcyBzaGltbWluZyBzYWZhcmkuJyk7XG4gICAgICAvLyBFeHBvcnQgdG8gdGhlIGFkYXB0ZXIgZ2xvYmFsIG9iamVjdCB2aXNpYmxlIGluIHRoZSBicm93c2VyLlxuICAgICAgYWRhcHRlci5icm93c2VyU2hpbSA9IHNhZmFyaVNoaW07XG4gICAgICBjb21tb25TaGltLnNoaW1DcmVhdGVPYmplY3RVUkwod2luZG93KTtcblxuICAgICAgc2FmYXJpU2hpbS5zaGltUlRDSWNlU2VydmVyVXJscyh3aW5kb3cpO1xuICAgICAgc2FmYXJpU2hpbS5zaGltQ2FsbGJhY2tzQVBJKHdpbmRvdyk7XG4gICAgICBzYWZhcmlTaGltLnNoaW1Mb2NhbFN0cmVhbXNBUEkod2luZG93KTtcbiAgICAgIHNhZmFyaVNoaW0uc2hpbVJlbW90ZVN0cmVhbXNBUEkod2luZG93KTtcbiAgICAgIHNhZmFyaVNoaW0uc2hpbVRyYWNrRXZlbnRUcmFuc2NlaXZlcih3aW5kb3cpO1xuICAgICAgc2FmYXJpU2hpbS5zaGltR2V0VXNlck1lZGlhKHdpbmRvdyk7XG4gICAgICBzYWZhcmlTaGltLnNoaW1DcmVhdGVPZmZlckxlZ2FjeSh3aW5kb3cpO1xuXG4gICAgICBjb21tb25TaGltLnNoaW1SVENJY2VDYW5kaWRhdGUod2luZG93KTtcbiAgICAgIGNvbW1vblNoaW0uc2hpbU1heE1lc3NhZ2VTaXplKHdpbmRvdyk7XG4gICAgICBjb21tb25TaGltLnNoaW1TZW5kVGhyb3dUeXBlRXJyb3Iod2luZG93KTtcbiAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICBsb2dnaW5nKCdVbnN1cHBvcnRlZCBicm93c2VyIScpO1xuICAgICAgYnJlYWs7XG4gIH1cblxuICByZXR1cm4gYWRhcHRlcjtcbn07XG4iLCJcbi8qXG4gKiAgQ29weXJpZ2h0IChjKSAyMDE2IFRoZSBXZWJSVEMgcHJvamVjdCBhdXRob3JzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqICBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhIEJTRC1zdHlsZSBsaWNlbnNlXG4gKiAgdGhhdCBjYW4gYmUgZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBvZiB0aGUgc291cmNlXG4gKiAgdHJlZS5cbiAqL1xuIC8qIGVzbGludC1lbnYgbm9kZSAqL1xuJ3VzZSBzdHJpY3QnO1xudmFyIHV0aWxzID0gcmVxdWlyZSgnLi4vdXRpbHMuanMnKTtcbnZhciBsb2dnaW5nID0gdXRpbHMubG9nO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgc2hpbUdldFVzZXJNZWRpYTogcmVxdWlyZSgnLi9nZXR1c2VybWVkaWEnKSxcbiAgc2hpbU1lZGlhU3RyZWFtOiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICB3aW5kb3cuTWVkaWFTdHJlYW0gPSB3aW5kb3cuTWVkaWFTdHJlYW0gfHwgd2luZG93LndlYmtpdE1lZGlhU3RyZWFtO1xuICB9LFxuXG4gIHNoaW1PblRyYWNrOiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcgJiYgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uICYmICEoJ29udHJhY2snIGluXG4gICAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUpKSB7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkod2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSwgJ29udHJhY2snLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuX29udHJhY2s7XG4gICAgICAgIH0sXG4gICAgICAgIHNldDogZnVuY3Rpb24oZikge1xuICAgICAgICAgIGlmICh0aGlzLl9vbnRyYWNrKSB7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RyYWNrJywgdGhpcy5fb250cmFjayk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcigndHJhY2snLCB0aGlzLl9vbnRyYWNrID0gZik7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgdmFyIG9yaWdTZXRSZW1vdGVEZXNjcmlwdGlvbiA9XG4gICAgICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5zZXRSZW1vdGVEZXNjcmlwdGlvbjtcbiAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuc2V0UmVtb3RlRGVzY3JpcHRpb24gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHBjID0gdGhpcztcbiAgICAgICAgaWYgKCFwYy5fb250cmFja3BvbHkpIHtcbiAgICAgICAgICBwYy5fb250cmFja3BvbHkgPSBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICAvLyBvbmFkZHN0cmVhbSBkb2VzIG5vdCBmaXJlIHdoZW4gYSB0cmFjayBpcyBhZGRlZCB0byBhbiBleGlzdGluZ1xuICAgICAgICAgICAgLy8gc3RyZWFtLiBCdXQgc3RyZWFtLm9uYWRkdHJhY2sgaXMgaW1wbGVtZW50ZWQgc28gd2UgdXNlIHRoYXQuXG4gICAgICAgICAgICBlLnN0cmVhbS5hZGRFdmVudExpc3RlbmVyKCdhZGR0cmFjaycsIGZ1bmN0aW9uKHRlKSB7XG4gICAgICAgICAgICAgIHZhciByZWNlaXZlcjtcbiAgICAgICAgICAgICAgaWYgKHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuZ2V0UmVjZWl2ZXJzKSB7XG4gICAgICAgICAgICAgICAgcmVjZWl2ZXIgPSBwYy5nZXRSZWNlaXZlcnMoKS5maW5kKGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiByLnRyYWNrICYmIHIudHJhY2suaWQgPT09IHRlLnRyYWNrLmlkO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY2VpdmVyID0ge3RyYWNrOiB0ZS50cmFja307XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICB2YXIgZXZlbnQgPSBuZXcgRXZlbnQoJ3RyYWNrJyk7XG4gICAgICAgICAgICAgIGV2ZW50LnRyYWNrID0gdGUudHJhY2s7XG4gICAgICAgICAgICAgIGV2ZW50LnJlY2VpdmVyID0gcmVjZWl2ZXI7XG4gICAgICAgICAgICAgIGV2ZW50LnRyYW5zY2VpdmVyID0ge3JlY2VpdmVyOiByZWNlaXZlcn07XG4gICAgICAgICAgICAgIGV2ZW50LnN0cmVhbXMgPSBbZS5zdHJlYW1dO1xuICAgICAgICAgICAgICBwYy5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZS5zdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaChmdW5jdGlvbih0cmFjaykge1xuICAgICAgICAgICAgICB2YXIgcmVjZWl2ZXI7XG4gICAgICAgICAgICAgIGlmICh3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmdldFJlY2VpdmVycykge1xuICAgICAgICAgICAgICAgIHJlY2VpdmVyID0gcGMuZ2V0UmVjZWl2ZXJzKCkuZmluZChmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gci50cmFjayAmJiByLnRyYWNrLmlkID09PSB0cmFjay5pZDtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZWNlaXZlciA9IHt0cmFjazogdHJhY2t9O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHZhciBldmVudCA9IG5ldyBFdmVudCgndHJhY2snKTtcbiAgICAgICAgICAgICAgZXZlbnQudHJhY2sgPSB0cmFjaztcbiAgICAgICAgICAgICAgZXZlbnQucmVjZWl2ZXIgPSByZWNlaXZlcjtcbiAgICAgICAgICAgICAgZXZlbnQudHJhbnNjZWl2ZXIgPSB7cmVjZWl2ZXI6IHJlY2VpdmVyfTtcbiAgICAgICAgICAgICAgZXZlbnQuc3RyZWFtcyA9IFtlLnN0cmVhbV07XG4gICAgICAgICAgICAgIHBjLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfTtcbiAgICAgICAgICBwYy5hZGRFdmVudExpc3RlbmVyKCdhZGRzdHJlYW0nLCBwYy5fb250cmFja3BvbHkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvcmlnU2V0UmVtb3RlRGVzY3JpcHRpb24uYXBwbHkocGMsIGFyZ3VtZW50cyk7XG4gICAgICB9O1xuICAgIH0gZWxzZSBpZiAoISgnUlRDUnRwVHJhbnNjZWl2ZXInIGluIHdpbmRvdykpIHtcbiAgICAgIHV0aWxzLndyYXBQZWVyQ29ubmVjdGlvbkV2ZW50KHdpbmRvdywgJ3RyYWNrJywgZnVuY3Rpb24oZSkge1xuICAgICAgICBpZiAoIWUudHJhbnNjZWl2ZXIpIHtcbiAgICAgICAgICBlLnRyYW5zY2VpdmVyID0ge3JlY2VpdmVyOiBlLnJlY2VpdmVyfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSxcblxuICBzaGltR2V0U2VuZGVyc1dpdGhEdG1mOiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICAvLyBPdmVycmlkZXMgYWRkVHJhY2svcmVtb3ZlVHJhY2ssIGRlcGVuZHMgb24gc2hpbUFkZFRyYWNrUmVtb3ZlVHJhY2suXG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgPT09ICdvYmplY3QnICYmIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiAmJlxuICAgICAgICAhKCdnZXRTZW5kZXJzJyBpbiB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlKSAmJlxuICAgICAgICAnY3JlYXRlRFRNRlNlbmRlcicgaW4gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSkge1xuICAgICAgdmFyIHNoaW1TZW5kZXJXaXRoRHRtZiA9IGZ1bmN0aW9uKHBjLCB0cmFjaykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHRyYWNrOiB0cmFjayxcbiAgICAgICAgICBnZXQgZHRtZigpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9kdG1mID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgaWYgKHRyYWNrLmtpbmQgPT09ICdhdWRpbycpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9kdG1mID0gcGMuY3JlYXRlRFRNRlNlbmRlcih0cmFjayk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZHRtZiA9IG51bGw7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9kdG1mO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgX3BjOiBwY1xuICAgICAgICB9O1xuICAgICAgfTtcblxuICAgICAgLy8gYXVnbWVudCBhZGRUcmFjayB3aGVuIGdldFNlbmRlcnMgaXMgbm90IGF2YWlsYWJsZS5cbiAgICAgIGlmICghd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5nZXRTZW5kZXJzKSB7XG4gICAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuZ2V0U2VuZGVycyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHRoaXMuX3NlbmRlcnMgPSB0aGlzLl9zZW5kZXJzIHx8IFtdO1xuICAgICAgICAgIHJldHVybiB0aGlzLl9zZW5kZXJzLnNsaWNlKCk7IC8vIHJldHVybiBhIGNvcHkgb2YgdGhlIGludGVybmFsIHN0YXRlLlxuICAgICAgICB9O1xuICAgICAgICB2YXIgb3JpZ0FkZFRyYWNrID0gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5hZGRUcmFjaztcbiAgICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5hZGRUcmFjayA9IGZ1bmN0aW9uKHRyYWNrLCBzdHJlYW0pIHtcbiAgICAgICAgICB2YXIgcGMgPSB0aGlzO1xuICAgICAgICAgIHZhciBzZW5kZXIgPSBvcmlnQWRkVHJhY2suYXBwbHkocGMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgaWYgKCFzZW5kZXIpIHtcbiAgICAgICAgICAgIHNlbmRlciA9IHNoaW1TZW5kZXJXaXRoRHRtZihwYywgdHJhY2spO1xuICAgICAgICAgICAgcGMuX3NlbmRlcnMucHVzaChzZW5kZXIpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gc2VuZGVyO1xuICAgICAgICB9O1xuXG4gICAgICAgIHZhciBvcmlnUmVtb3ZlVHJhY2sgPSB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnJlbW92ZVRyYWNrO1xuICAgICAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnJlbW92ZVRyYWNrID0gZnVuY3Rpb24oc2VuZGVyKSB7XG4gICAgICAgICAgdmFyIHBjID0gdGhpcztcbiAgICAgICAgICBvcmlnUmVtb3ZlVHJhY2suYXBwbHkocGMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgdmFyIGlkeCA9IHBjLl9zZW5kZXJzLmluZGV4T2Yoc2VuZGVyKTtcbiAgICAgICAgICBpZiAoaWR4ICE9PSAtMSkge1xuICAgICAgICAgICAgcGMuX3NlbmRlcnMuc3BsaWNlKGlkeCwgMSk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgdmFyIG9yaWdBZGRTdHJlYW0gPSB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmFkZFN0cmVhbTtcbiAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuYWRkU3RyZWFtID0gZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICAgIHZhciBwYyA9IHRoaXM7XG4gICAgICAgIHBjLl9zZW5kZXJzID0gcGMuX3NlbmRlcnMgfHwgW107XG4gICAgICAgIG9yaWdBZGRTdHJlYW0uYXBwbHkocGMsIFtzdHJlYW1dKTtcbiAgICAgICAgc3RyZWFtLmdldFRyYWNrcygpLmZvckVhY2goZnVuY3Rpb24odHJhY2spIHtcbiAgICAgICAgICBwYy5fc2VuZGVycy5wdXNoKHNoaW1TZW5kZXJXaXRoRHRtZihwYywgdHJhY2spKTtcbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgb3JpZ1JlbW92ZVN0cmVhbSA9IHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUucmVtb3ZlU3RyZWFtO1xuICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5yZW1vdmVTdHJlYW0gPSBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgdmFyIHBjID0gdGhpcztcbiAgICAgICAgcGMuX3NlbmRlcnMgPSBwYy5fc2VuZGVycyB8fCBbXTtcbiAgICAgICAgb3JpZ1JlbW92ZVN0cmVhbS5hcHBseShwYywgW3N0cmVhbV0pO1xuXG4gICAgICAgIHN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKGZ1bmN0aW9uKHRyYWNrKSB7XG4gICAgICAgICAgdmFyIHNlbmRlciA9IHBjLl9zZW5kZXJzLmZpbmQoZnVuY3Rpb24ocykge1xuICAgICAgICAgICAgcmV0dXJuIHMudHJhY2sgPT09IHRyYWNrO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIGlmIChzZW5kZXIpIHtcbiAgICAgICAgICAgIHBjLl9zZW5kZXJzLnNwbGljZShwYy5fc2VuZGVycy5pbmRleE9mKHNlbmRlciksIDEpOyAvLyByZW1vdmUgc2VuZGVyXG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgfSBlbHNlIGlmICh0eXBlb2Ygd2luZG93ID09PSAnb2JqZWN0JyAmJiB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24gJiZcbiAgICAgICAgICAgICAgICdnZXRTZW5kZXJzJyBpbiB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlICYmXG4gICAgICAgICAgICAgICAnY3JlYXRlRFRNRlNlbmRlcicgaW4gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSAmJlxuICAgICAgICAgICAgICAgd2luZG93LlJUQ1J0cFNlbmRlciAmJlxuICAgICAgICAgICAgICAgISgnZHRtZicgaW4gd2luZG93LlJUQ1J0cFNlbmRlci5wcm90b3R5cGUpKSB7XG4gICAgICB2YXIgb3JpZ0dldFNlbmRlcnMgPSB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmdldFNlbmRlcnM7XG4gICAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmdldFNlbmRlcnMgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHBjID0gdGhpcztcbiAgICAgICAgdmFyIHNlbmRlcnMgPSBvcmlnR2V0U2VuZGVycy5hcHBseShwYywgW10pO1xuICAgICAgICBzZW5kZXJzLmZvckVhY2goZnVuY3Rpb24oc2VuZGVyKSB7XG4gICAgICAgICAgc2VuZGVyLl9wYyA9IHBjO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHNlbmRlcnM7XG4gICAgICB9O1xuXG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkod2luZG93LlJUQ1J0cFNlbmRlci5wcm90b3R5cGUsICdkdG1mJywge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGlmICh0aGlzLl9kdG1mID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnRyYWNrLmtpbmQgPT09ICdhdWRpbycpIHtcbiAgICAgICAgICAgICAgdGhpcy5fZHRtZiA9IHRoaXMuX3BjLmNyZWF0ZURUTUZTZW5kZXIodGhpcy50cmFjayk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aGlzLl9kdG1mID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHRoaXMuX2R0bWY7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfSxcblxuICBzaGltU291cmNlT2JqZWN0OiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICB2YXIgVVJMID0gd2luZG93ICYmIHdpbmRvdy5VUkw7XG5cbiAgICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGlmICh3aW5kb3cuSFRNTE1lZGlhRWxlbWVudCAmJlxuICAgICAgICAhKCdzcmNPYmplY3QnIGluIHdpbmRvdy5IVE1MTWVkaWFFbGVtZW50LnByb3RvdHlwZSkpIHtcbiAgICAgICAgLy8gU2hpbSB0aGUgc3JjT2JqZWN0IHByb3BlcnR5LCBvbmNlLCB3aGVuIEhUTUxNZWRpYUVsZW1lbnQgaXMgZm91bmQuXG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh3aW5kb3cuSFRNTE1lZGlhRWxlbWVudC5wcm90b3R5cGUsICdzcmNPYmplY3QnLCB7XG4gICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9zcmNPYmplY3Q7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBzZXQ6IGZ1bmN0aW9uKHN0cmVhbSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgLy8gVXNlIF9zcmNPYmplY3QgYXMgYSBwcml2YXRlIHByb3BlcnR5IGZvciB0aGlzIHNoaW1cbiAgICAgICAgICAgIHRoaXMuX3NyY09iamVjdCA9IHN0cmVhbTtcbiAgICAgICAgICAgIGlmICh0aGlzLnNyYykge1xuICAgICAgICAgICAgICBVUkwucmV2b2tlT2JqZWN0VVJMKHRoaXMuc3JjKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFzdHJlYW0pIHtcbiAgICAgICAgICAgICAgdGhpcy5zcmMgPSAnJztcbiAgICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc3JjID0gVVJMLmNyZWF0ZU9iamVjdFVSTChzdHJlYW0pO1xuICAgICAgICAgICAgLy8gV2UgbmVlZCB0byByZWNyZWF0ZSB0aGUgYmxvYiB1cmwgd2hlbiBhIHRyYWNrIGlzIGFkZGVkIG9yXG4gICAgICAgICAgICAvLyByZW1vdmVkLiBEb2luZyBpdCBtYW51YWxseSBzaW5jZSB3ZSB3YW50IHRvIGF2b2lkIGEgcmVjdXJzaW9uLlxuICAgICAgICAgICAgc3RyZWFtLmFkZEV2ZW50TGlzdGVuZXIoJ2FkZHRyYWNrJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgIGlmIChzZWxmLnNyYykge1xuICAgICAgICAgICAgICAgIFVSTC5yZXZva2VPYmplY3RVUkwoc2VsZi5zcmMpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHNlbGYuc3JjID0gVVJMLmNyZWF0ZU9iamVjdFVSTChzdHJlYW0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzdHJlYW0uYWRkRXZlbnRMaXN0ZW5lcigncmVtb3ZldHJhY2snLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgaWYgKHNlbGYuc3JjKSB7XG4gICAgICAgICAgICAgICAgVVJMLnJldm9rZU9iamVjdFVSTChzZWxmLnNyYyk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgc2VsZi5zcmMgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKHN0cmVhbSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfSxcblxuICBzaGltQWRkVHJhY2tSZW1vdmVUcmFja1dpdGhOYXRpdmU6IGZ1bmN0aW9uKHdpbmRvdykge1xuICAgIC8vIHNoaW0gYWRkVHJhY2svcmVtb3ZlVHJhY2sgd2l0aCBuYXRpdmUgdmFyaWFudHMgaW4gb3JkZXIgdG8gbWFrZVxuICAgIC8vIHRoZSBpbnRlcmFjdGlvbnMgd2l0aCBsZWdhY3kgZ2V0TG9jYWxTdHJlYW1zIGJlaGF2ZSBhcyBpbiBvdGhlciBicm93c2Vycy5cbiAgICAvLyBLZWVwcyBhIG1hcHBpbmcgc3RyZWFtLmlkID0+IFtzdHJlYW0sIHJ0cHNlbmRlcnMuLi5dXG4gICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5nZXRMb2NhbFN0cmVhbXMgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBwYyA9IHRoaXM7XG4gICAgICB0aGlzLl9zaGltbWVkTG9jYWxTdHJlYW1zID0gdGhpcy5fc2hpbW1lZExvY2FsU3RyZWFtcyB8fCB7fTtcbiAgICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLl9zaGltbWVkTG9jYWxTdHJlYW1zKS5tYXAoZnVuY3Rpb24oc3RyZWFtSWQpIHtcbiAgICAgICAgcmV0dXJuIHBjLl9zaGltbWVkTG9jYWxTdHJlYW1zW3N0cmVhbUlkXVswXTtcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICB2YXIgb3JpZ0FkZFRyYWNrID0gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5hZGRUcmFjaztcbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmFkZFRyYWNrID0gZnVuY3Rpb24odHJhY2ssIHN0cmVhbSkge1xuICAgICAgaWYgKCFzdHJlYW0pIHtcbiAgICAgICAgcmV0dXJuIG9yaWdBZGRUcmFjay5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgfVxuICAgICAgdGhpcy5fc2hpbW1lZExvY2FsU3RyZWFtcyA9IHRoaXMuX3NoaW1tZWRMb2NhbFN0cmVhbXMgfHwge307XG5cbiAgICAgIHZhciBzZW5kZXIgPSBvcmlnQWRkVHJhY2suYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIGlmICghdGhpcy5fc2hpbW1lZExvY2FsU3RyZWFtc1tzdHJlYW0uaWRdKSB7XG4gICAgICAgIHRoaXMuX3NoaW1tZWRMb2NhbFN0cmVhbXNbc3RyZWFtLmlkXSA9IFtzdHJlYW0sIHNlbmRlcl07XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuX3NoaW1tZWRMb2NhbFN0cmVhbXNbc3RyZWFtLmlkXS5pbmRleE9mKHNlbmRlcikgPT09IC0xKSB7XG4gICAgICAgIHRoaXMuX3NoaW1tZWRMb2NhbFN0cmVhbXNbc3RyZWFtLmlkXS5wdXNoKHNlbmRlcik7XG4gICAgICB9XG4gICAgICByZXR1cm4gc2VuZGVyO1xuICAgIH07XG5cbiAgICB2YXIgb3JpZ0FkZFN0cmVhbSA9IHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuYWRkU3RyZWFtO1xuICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuYWRkU3RyZWFtID0gZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICB2YXIgcGMgPSB0aGlzO1xuICAgICAgdGhpcy5fc2hpbW1lZExvY2FsU3RyZWFtcyA9IHRoaXMuX3NoaW1tZWRMb2NhbFN0cmVhbXMgfHwge307XG5cbiAgICAgIHN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKGZ1bmN0aW9uKHRyYWNrKSB7XG4gICAgICAgIHZhciBhbHJlYWR5RXhpc3RzID0gcGMuZ2V0U2VuZGVycygpLmZpbmQoZnVuY3Rpb24ocykge1xuICAgICAgICAgIHJldHVybiBzLnRyYWNrID09PSB0cmFjaztcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChhbHJlYWR5RXhpc3RzKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IERPTUV4Y2VwdGlvbignVHJhY2sgYWxyZWFkeSBleGlzdHMuJyxcbiAgICAgICAgICAgICAgJ0ludmFsaWRBY2Nlc3NFcnJvcicpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHZhciBleGlzdGluZ1NlbmRlcnMgPSBwYy5nZXRTZW5kZXJzKCk7XG4gICAgICBvcmlnQWRkU3RyZWFtLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICB2YXIgbmV3U2VuZGVycyA9IHBjLmdldFNlbmRlcnMoKS5maWx0ZXIoZnVuY3Rpb24obmV3U2VuZGVyKSB7XG4gICAgICAgIHJldHVybiBleGlzdGluZ1NlbmRlcnMuaW5kZXhPZihuZXdTZW5kZXIpID09PSAtMTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5fc2hpbW1lZExvY2FsU3RyZWFtc1tzdHJlYW0uaWRdID0gW3N0cmVhbV0uY29uY2F0KG5ld1NlbmRlcnMpO1xuICAgIH07XG5cbiAgICB2YXIgb3JpZ1JlbW92ZVN0cmVhbSA9IHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUucmVtb3ZlU3RyZWFtO1xuICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUucmVtb3ZlU3RyZWFtID0gZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICB0aGlzLl9zaGltbWVkTG9jYWxTdHJlYW1zID0gdGhpcy5fc2hpbW1lZExvY2FsU3RyZWFtcyB8fCB7fTtcbiAgICAgIGRlbGV0ZSB0aGlzLl9zaGltbWVkTG9jYWxTdHJlYW1zW3N0cmVhbS5pZF07XG4gICAgICByZXR1cm4gb3JpZ1JlbW92ZVN0cmVhbS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG5cbiAgICB2YXIgb3JpZ1JlbW92ZVRyYWNrID0gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5yZW1vdmVUcmFjaztcbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnJlbW92ZVRyYWNrID0gZnVuY3Rpb24oc2VuZGVyKSB7XG4gICAgICB2YXIgcGMgPSB0aGlzO1xuICAgICAgdGhpcy5fc2hpbW1lZExvY2FsU3RyZWFtcyA9IHRoaXMuX3NoaW1tZWRMb2NhbFN0cmVhbXMgfHwge307XG4gICAgICBpZiAoc2VuZGVyKSB7XG4gICAgICAgIE9iamVjdC5rZXlzKHRoaXMuX3NoaW1tZWRMb2NhbFN0cmVhbXMpLmZvckVhY2goZnVuY3Rpb24oc3RyZWFtSWQpIHtcbiAgICAgICAgICB2YXIgaWR4ID0gcGMuX3NoaW1tZWRMb2NhbFN0cmVhbXNbc3RyZWFtSWRdLmluZGV4T2Yoc2VuZGVyKTtcbiAgICAgICAgICBpZiAoaWR4ICE9PSAtMSkge1xuICAgICAgICAgICAgcGMuX3NoaW1tZWRMb2NhbFN0cmVhbXNbc3RyZWFtSWRdLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAocGMuX3NoaW1tZWRMb2NhbFN0cmVhbXNbc3RyZWFtSWRdLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgZGVsZXRlIHBjLl9zaGltbWVkTG9jYWxTdHJlYW1zW3N0cmVhbUlkXTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG9yaWdSZW1vdmVUcmFjay5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG4gIH0sXG5cbiAgc2hpbUFkZFRyYWNrUmVtb3ZlVHJhY2s6IGZ1bmN0aW9uKHdpbmRvdykge1xuICAgIHZhciBicm93c2VyRGV0YWlscyA9IHV0aWxzLmRldGVjdEJyb3dzZXIod2luZG93KTtcbiAgICAvLyBzaGltIGFkZFRyYWNrIGFuZCByZW1vdmVUcmFjay5cbiAgICBpZiAod2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5hZGRUcmFjayAmJlxuICAgICAgICBicm93c2VyRGV0YWlscy52ZXJzaW9uID49IDY1KSB7XG4gICAgICByZXR1cm4gdGhpcy5zaGltQWRkVHJhY2tSZW1vdmVUcmFja1dpdGhOYXRpdmUod2luZG93KTtcbiAgICB9XG5cbiAgICAvLyBhbHNvIHNoaW0gcGMuZ2V0TG9jYWxTdHJlYW1zIHdoZW4gYWRkVHJhY2sgaXMgc2hpbW1lZFxuICAgIC8vIHRvIHJldHVybiB0aGUgb3JpZ2luYWwgc3RyZWFtcy5cbiAgICB2YXIgb3JpZ0dldExvY2FsU3RyZWFtcyA9IHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGVcbiAgICAgICAgLmdldExvY2FsU3RyZWFtcztcbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmdldExvY2FsU3RyZWFtcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHBjID0gdGhpcztcbiAgICAgIHZhciBuYXRpdmVTdHJlYW1zID0gb3JpZ0dldExvY2FsU3RyZWFtcy5hcHBseSh0aGlzKTtcbiAgICAgIHBjLl9yZXZlcnNlU3RyZWFtcyA9IHBjLl9yZXZlcnNlU3RyZWFtcyB8fCB7fTtcbiAgICAgIHJldHVybiBuYXRpdmVTdHJlYW1zLm1hcChmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgcmV0dXJuIHBjLl9yZXZlcnNlU3RyZWFtc1tzdHJlYW0uaWRdO1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIHZhciBvcmlnQWRkU3RyZWFtID0gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5hZGRTdHJlYW07XG4gICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5hZGRTdHJlYW0gPSBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgIHZhciBwYyA9IHRoaXM7XG4gICAgICBwYy5fc3RyZWFtcyA9IHBjLl9zdHJlYW1zIHx8IHt9O1xuICAgICAgcGMuX3JldmVyc2VTdHJlYW1zID0gcGMuX3JldmVyc2VTdHJlYW1zIHx8IHt9O1xuXG4gICAgICBzdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaChmdW5jdGlvbih0cmFjaykge1xuICAgICAgICB2YXIgYWxyZWFkeUV4aXN0cyA9IHBjLmdldFNlbmRlcnMoKS5maW5kKGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgICByZXR1cm4gcy50cmFjayA9PT0gdHJhY2s7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoYWxyZWFkeUV4aXN0cykge1xuICAgICAgICAgIHRocm93IG5ldyBET01FeGNlcHRpb24oJ1RyYWNrIGFscmVhZHkgZXhpc3RzLicsXG4gICAgICAgICAgICAgICdJbnZhbGlkQWNjZXNzRXJyb3InKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICAvLyBBZGQgaWRlbnRpdHkgbWFwcGluZyBmb3IgY29uc2lzdGVuY3kgd2l0aCBhZGRUcmFjay5cbiAgICAgIC8vIFVubGVzcyB0aGlzIGlzIGJlaW5nIHVzZWQgd2l0aCBhIHN0cmVhbSBmcm9tIGFkZFRyYWNrLlxuICAgICAgaWYgKCFwYy5fcmV2ZXJzZVN0cmVhbXNbc3RyZWFtLmlkXSkge1xuICAgICAgICB2YXIgbmV3U3RyZWFtID0gbmV3IHdpbmRvdy5NZWRpYVN0cmVhbShzdHJlYW0uZ2V0VHJhY2tzKCkpO1xuICAgICAgICBwYy5fc3RyZWFtc1tzdHJlYW0uaWRdID0gbmV3U3RyZWFtO1xuICAgICAgICBwYy5fcmV2ZXJzZVN0cmVhbXNbbmV3U3RyZWFtLmlkXSA9IHN0cmVhbTtcbiAgICAgICAgc3RyZWFtID0gbmV3U3RyZWFtO1xuICAgICAgfVxuICAgICAgb3JpZ0FkZFN0cmVhbS5hcHBseShwYywgW3N0cmVhbV0pO1xuICAgIH07XG5cbiAgICB2YXIgb3JpZ1JlbW92ZVN0cmVhbSA9IHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUucmVtb3ZlU3RyZWFtO1xuICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUucmVtb3ZlU3RyZWFtID0gZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICB2YXIgcGMgPSB0aGlzO1xuICAgICAgcGMuX3N0cmVhbXMgPSBwYy5fc3RyZWFtcyB8fCB7fTtcbiAgICAgIHBjLl9yZXZlcnNlU3RyZWFtcyA9IHBjLl9yZXZlcnNlU3RyZWFtcyB8fCB7fTtcblxuICAgICAgb3JpZ1JlbW92ZVN0cmVhbS5hcHBseShwYywgWyhwYy5fc3RyZWFtc1tzdHJlYW0uaWRdIHx8IHN0cmVhbSldKTtcbiAgICAgIGRlbGV0ZSBwYy5fcmV2ZXJzZVN0cmVhbXNbKHBjLl9zdHJlYW1zW3N0cmVhbS5pZF0gP1xuICAgICAgICAgIHBjLl9zdHJlYW1zW3N0cmVhbS5pZF0uaWQgOiBzdHJlYW0uaWQpXTtcbiAgICAgIGRlbGV0ZSBwYy5fc3RyZWFtc1tzdHJlYW0uaWRdO1xuICAgIH07XG5cbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmFkZFRyYWNrID0gZnVuY3Rpb24odHJhY2ssIHN0cmVhbSkge1xuICAgICAgdmFyIHBjID0gdGhpcztcbiAgICAgIGlmIChwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgdGhyb3cgbmV3IERPTUV4Y2VwdGlvbihcbiAgICAgICAgICAnVGhlIFJUQ1BlZXJDb25uZWN0aW9uXFwncyBzaWduYWxpbmdTdGF0ZSBpcyBcXCdjbG9zZWRcXCcuJyxcbiAgICAgICAgICAnSW52YWxpZFN0YXRlRXJyb3InKTtcbiAgICAgIH1cbiAgICAgIHZhciBzdHJlYW1zID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgaWYgKHN0cmVhbXMubGVuZ3RoICE9PSAxIHx8XG4gICAgICAgICAgIXN0cmVhbXNbMF0uZ2V0VHJhY2tzKCkuZmluZChmdW5jdGlvbih0KSB7XG4gICAgICAgICAgICByZXR1cm4gdCA9PT0gdHJhY2s7XG4gICAgICAgICAgfSkpIHtcbiAgICAgICAgLy8gdGhpcyBpcyBub3QgZnVsbHkgY29ycmVjdCBidXQgYWxsIHdlIGNhbiBtYW5hZ2Ugd2l0aG91dFxuICAgICAgICAvLyBbW2Fzc29jaWF0ZWQgTWVkaWFTdHJlYW1zXV0gaW50ZXJuYWwgc2xvdC5cbiAgICAgICAgdGhyb3cgbmV3IERPTUV4Y2VwdGlvbihcbiAgICAgICAgICAnVGhlIGFkYXB0ZXIuanMgYWRkVHJhY2sgcG9seWZpbGwgb25seSBzdXBwb3J0cyBhIHNpbmdsZSAnICtcbiAgICAgICAgICAnIHN0cmVhbSB3aGljaCBpcyBhc3NvY2lhdGVkIHdpdGggdGhlIHNwZWNpZmllZCB0cmFjay4nLFxuICAgICAgICAgICdOb3RTdXBwb3J0ZWRFcnJvcicpO1xuICAgICAgfVxuXG4gICAgICB2YXIgYWxyZWFkeUV4aXN0cyA9IHBjLmdldFNlbmRlcnMoKS5maW5kKGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgcmV0dXJuIHMudHJhY2sgPT09IHRyYWNrO1xuICAgICAgfSk7XG4gICAgICBpZiAoYWxyZWFkeUV4aXN0cykge1xuICAgICAgICB0aHJvdyBuZXcgRE9NRXhjZXB0aW9uKCdUcmFjayBhbHJlYWR5IGV4aXN0cy4nLFxuICAgICAgICAgICAgJ0ludmFsaWRBY2Nlc3NFcnJvcicpO1xuICAgICAgfVxuXG4gICAgICBwYy5fc3RyZWFtcyA9IHBjLl9zdHJlYW1zIHx8IHt9O1xuICAgICAgcGMuX3JldmVyc2VTdHJlYW1zID0gcGMuX3JldmVyc2VTdHJlYW1zIHx8IHt9O1xuICAgICAgdmFyIG9sZFN0cmVhbSA9IHBjLl9zdHJlYW1zW3N0cmVhbS5pZF07XG4gICAgICBpZiAob2xkU3RyZWFtKSB7XG4gICAgICAgIC8vIHRoaXMgaXMgdXNpbmcgb2RkIENocm9tZSBiZWhhdmlvdXIsIHVzZSB3aXRoIGNhdXRpb246XG4gICAgICAgIC8vIGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC93ZWJydGMvaXNzdWVzL2RldGFpbD9pZD03ODE1XG4gICAgICAgIC8vIE5vdGU6IHdlIHJlbHkgb24gdGhlIGhpZ2gtbGV2ZWwgYWRkVHJhY2svZHRtZiBzaGltIHRvXG4gICAgICAgIC8vIGNyZWF0ZSB0aGUgc2VuZGVyIHdpdGggYSBkdG1mIHNlbmRlci5cbiAgICAgICAgb2xkU3RyZWFtLmFkZFRyYWNrKHRyYWNrKTtcblxuICAgICAgICAvLyBUcmlnZ2VyIE9OTiBhc3luYy5cbiAgICAgICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbihmdW5jdGlvbigpIHtcbiAgICAgICAgICBwYy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudCgnbmVnb3RpYXRpb25uZWVkZWQnKSk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIG5ld1N0cmVhbSA9IG5ldyB3aW5kb3cuTWVkaWFTdHJlYW0oW3RyYWNrXSk7XG4gICAgICAgIHBjLl9zdHJlYW1zW3N0cmVhbS5pZF0gPSBuZXdTdHJlYW07XG4gICAgICAgIHBjLl9yZXZlcnNlU3RyZWFtc1tuZXdTdHJlYW0uaWRdID0gc3RyZWFtO1xuICAgICAgICBwYy5hZGRTdHJlYW0obmV3U3RyZWFtKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBwYy5nZXRTZW5kZXJzKCkuZmluZChmdW5jdGlvbihzKSB7XG4gICAgICAgIHJldHVybiBzLnRyYWNrID09PSB0cmFjaztcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvLyByZXBsYWNlIHRoZSBpbnRlcm5hbCBzdHJlYW0gaWQgd2l0aCB0aGUgZXh0ZXJuYWwgb25lIGFuZFxuICAgIC8vIHZpY2UgdmVyc2EuXG4gICAgZnVuY3Rpb24gcmVwbGFjZUludGVybmFsU3RyZWFtSWQocGMsIGRlc2NyaXB0aW9uKSB7XG4gICAgICB2YXIgc2RwID0gZGVzY3JpcHRpb24uc2RwO1xuICAgICAgT2JqZWN0LmtleXMocGMuX3JldmVyc2VTdHJlYW1zIHx8IFtdKS5mb3JFYWNoKGZ1bmN0aW9uKGludGVybmFsSWQpIHtcbiAgICAgICAgdmFyIGV4dGVybmFsU3RyZWFtID0gcGMuX3JldmVyc2VTdHJlYW1zW2ludGVybmFsSWRdO1xuICAgICAgICB2YXIgaW50ZXJuYWxTdHJlYW0gPSBwYy5fc3RyZWFtc1tleHRlcm5hbFN0cmVhbS5pZF07XG4gICAgICAgIHNkcCA9IHNkcC5yZXBsYWNlKG5ldyBSZWdFeHAoaW50ZXJuYWxTdHJlYW0uaWQsICdnJyksXG4gICAgICAgICAgICBleHRlcm5hbFN0cmVhbS5pZCk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBuZXcgUlRDU2Vzc2lvbkRlc2NyaXB0aW9uKHtcbiAgICAgICAgdHlwZTogZGVzY3JpcHRpb24udHlwZSxcbiAgICAgICAgc2RwOiBzZHBcbiAgICAgIH0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZXBsYWNlRXh0ZXJuYWxTdHJlYW1JZChwYywgZGVzY3JpcHRpb24pIHtcbiAgICAgIHZhciBzZHAgPSBkZXNjcmlwdGlvbi5zZHA7XG4gICAgICBPYmplY3Qua2V5cyhwYy5fcmV2ZXJzZVN0cmVhbXMgfHwgW10pLmZvckVhY2goZnVuY3Rpb24oaW50ZXJuYWxJZCkge1xuICAgICAgICB2YXIgZXh0ZXJuYWxTdHJlYW0gPSBwYy5fcmV2ZXJzZVN0cmVhbXNbaW50ZXJuYWxJZF07XG4gICAgICAgIHZhciBpbnRlcm5hbFN0cmVhbSA9IHBjLl9zdHJlYW1zW2V4dGVybmFsU3RyZWFtLmlkXTtcbiAgICAgICAgc2RwID0gc2RwLnJlcGxhY2UobmV3IFJlZ0V4cChleHRlcm5hbFN0cmVhbS5pZCwgJ2cnKSxcbiAgICAgICAgICAgIGludGVybmFsU3RyZWFtLmlkKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIG5ldyBSVENTZXNzaW9uRGVzY3JpcHRpb24oe1xuICAgICAgICB0eXBlOiBkZXNjcmlwdGlvbi50eXBlLFxuICAgICAgICBzZHA6IHNkcFxuICAgICAgfSk7XG4gICAgfVxuICAgIFsnY3JlYXRlT2ZmZXInLCAnY3JlYXRlQW5zd2VyJ10uZm9yRWFjaChmdW5jdGlvbihtZXRob2QpIHtcbiAgICAgIHZhciBuYXRpdmVNZXRob2QgPSB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlW21ldGhvZF07XG4gICAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlW21ldGhvZF0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHBjID0gdGhpcztcbiAgICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgIHZhciBpc0xlZ2FjeUNhbGwgPSBhcmd1bWVudHMubGVuZ3RoICYmXG4gICAgICAgICAgICB0eXBlb2YgYXJndW1lbnRzWzBdID09PSAnZnVuY3Rpb24nO1xuICAgICAgICBpZiAoaXNMZWdhY3lDYWxsKSB7XG4gICAgICAgICAgcmV0dXJuIG5hdGl2ZU1ldGhvZC5hcHBseShwYywgW1xuICAgICAgICAgICAgZnVuY3Rpb24oZGVzY3JpcHRpb24pIHtcbiAgICAgICAgICAgICAgdmFyIGRlc2MgPSByZXBsYWNlSW50ZXJuYWxTdHJlYW1JZChwYywgZGVzY3JpcHRpb24pO1xuICAgICAgICAgICAgICBhcmdzWzBdLmFwcGx5KG51bGwsIFtkZXNjXSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZnVuY3Rpb24oZXJyKSB7XG4gICAgICAgICAgICAgIGlmIChhcmdzWzFdKSB7XG4gICAgICAgICAgICAgICAgYXJnc1sxXS5hcHBseShudWxsLCBlcnIpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LCBhcmd1bWVudHNbMl1cbiAgICAgICAgICBdKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmF0aXZlTWV0aG9kLmFwcGx5KHBjLCBhcmd1bWVudHMpXG4gICAgICAgIC50aGVuKGZ1bmN0aW9uKGRlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgcmV0dXJuIHJlcGxhY2VJbnRlcm5hbFN0cmVhbUlkKHBjLCBkZXNjcmlwdGlvbik7XG4gICAgICAgIH0pO1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIHZhciBvcmlnU2V0TG9jYWxEZXNjcmlwdGlvbiA9XG4gICAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuc2V0TG9jYWxEZXNjcmlwdGlvbjtcbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnNldExvY2FsRGVzY3JpcHRpb24gPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBwYyA9IHRoaXM7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGggfHwgIWFyZ3VtZW50c1swXS50eXBlKSB7XG4gICAgICAgIHJldHVybiBvcmlnU2V0TG9jYWxEZXNjcmlwdGlvbi5hcHBseShwYywgYXJndW1lbnRzKTtcbiAgICAgIH1cbiAgICAgIGFyZ3VtZW50c1swXSA9IHJlcGxhY2VFeHRlcm5hbFN0cmVhbUlkKHBjLCBhcmd1bWVudHNbMF0pO1xuICAgICAgcmV0dXJuIG9yaWdTZXRMb2NhbERlc2NyaXB0aW9uLmFwcGx5KHBjLCBhcmd1bWVudHMpO1xuICAgIH07XG5cbiAgICAvLyBUT0RPOiBtYW5nbGUgZ2V0U3RhdHM6IGh0dHBzOi8vdzNjLmdpdGh1Yi5pby93ZWJydGMtc3RhdHMvI2RvbS1ydGNtZWRpYXN0cmVhbXN0YXRzLXN0cmVhbWlkZW50aWZpZXJcblxuICAgIHZhciBvcmlnTG9jYWxEZXNjcmlwdGlvbiA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoXG4gICAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUsICdsb2NhbERlc2NyaXB0aW9uJyk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUsXG4gICAgICAgICdsb2NhbERlc2NyaXB0aW9uJywge1xuICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgcGMgPSB0aGlzO1xuICAgICAgICAgICAgdmFyIGRlc2NyaXB0aW9uID0gb3JpZ0xvY2FsRGVzY3JpcHRpb24uZ2V0LmFwcGx5KHRoaXMpO1xuICAgICAgICAgICAgaWYgKGRlc2NyaXB0aW9uLnR5cGUgPT09ICcnKSB7XG4gICAgICAgICAgICAgIHJldHVybiBkZXNjcmlwdGlvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXBsYWNlSW50ZXJuYWxTdHJlYW1JZChwYywgZGVzY3JpcHRpb24pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnJlbW92ZVRyYWNrID0gZnVuY3Rpb24oc2VuZGVyKSB7XG4gICAgICB2YXIgcGMgPSB0aGlzO1xuICAgICAgaWYgKHBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgICB0aHJvdyBuZXcgRE9NRXhjZXB0aW9uKFxuICAgICAgICAgICdUaGUgUlRDUGVlckNvbm5lY3Rpb25cXCdzIHNpZ25hbGluZ1N0YXRlIGlzIFxcJ2Nsb3NlZFxcJy4nLFxuICAgICAgICAgICdJbnZhbGlkU3RhdGVFcnJvcicpO1xuICAgICAgfVxuICAgICAgLy8gV2UgY2FuIG5vdCB5ZXQgY2hlY2sgZm9yIHNlbmRlciBpbnN0YW5jZW9mIFJUQ1J0cFNlbmRlclxuICAgICAgLy8gc2luY2Ugd2Ugc2hpbSBSVFBTZW5kZXIuIFNvIHdlIGNoZWNrIGlmIHNlbmRlci5fcGMgaXMgc2V0LlxuICAgICAgaWYgKCFzZW5kZXIuX3BjKSB7XG4gICAgICAgIHRocm93IG5ldyBET01FeGNlcHRpb24oJ0FyZ3VtZW50IDEgb2YgUlRDUGVlckNvbm5lY3Rpb24ucmVtb3ZlVHJhY2sgJyArXG4gICAgICAgICAgICAnZG9lcyBub3QgaW1wbGVtZW50IGludGVyZmFjZSBSVENSdHBTZW5kZXIuJywgJ1R5cGVFcnJvcicpO1xuICAgICAgfVxuICAgICAgdmFyIGlzTG9jYWwgPSBzZW5kZXIuX3BjID09PSBwYztcbiAgICAgIGlmICghaXNMb2NhbCkge1xuICAgICAgICB0aHJvdyBuZXcgRE9NRXhjZXB0aW9uKCdTZW5kZXIgd2FzIG5vdCBjcmVhdGVkIGJ5IHRoaXMgY29ubmVjdGlvbi4nLFxuICAgICAgICAgICAgJ0ludmFsaWRBY2Nlc3NFcnJvcicpO1xuICAgICAgfVxuXG4gICAgICAvLyBTZWFyY2ggZm9yIHRoZSBuYXRpdmUgc3RyZWFtIHRoZSBzZW5kZXJzIHRyYWNrIGJlbG9uZ3MgdG8uXG4gICAgICBwYy5fc3RyZWFtcyA9IHBjLl9zdHJlYW1zIHx8IHt9O1xuICAgICAgdmFyIHN0cmVhbTtcbiAgICAgIE9iamVjdC5rZXlzKHBjLl9zdHJlYW1zKS5mb3JFYWNoKGZ1bmN0aW9uKHN0cmVhbWlkKSB7XG4gICAgICAgIHZhciBoYXNUcmFjayA9IHBjLl9zdHJlYW1zW3N0cmVhbWlkXS5nZXRUcmFja3MoKS5maW5kKGZ1bmN0aW9uKHRyYWNrKSB7XG4gICAgICAgICAgcmV0dXJuIHNlbmRlci50cmFjayA9PT0gdHJhY2s7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoaGFzVHJhY2spIHtcbiAgICAgICAgICBzdHJlYW0gPSBwYy5fc3RyZWFtc1tzdHJlYW1pZF07XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBpZiAoc3RyZWFtKSB7XG4gICAgICAgIGlmIChzdHJlYW0uZ2V0VHJhY2tzKCkubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgLy8gaWYgdGhpcyBpcyB0aGUgbGFzdCB0cmFjayBvZiB0aGUgc3RyZWFtLCByZW1vdmUgdGhlIHN0cmVhbS4gVGhpc1xuICAgICAgICAgIC8vIHRha2VzIGNhcmUgb2YgYW55IHNoaW1tZWQgX3NlbmRlcnMuXG4gICAgICAgICAgcGMucmVtb3ZlU3RyZWFtKHBjLl9yZXZlcnNlU3RyZWFtc1tzdHJlYW0uaWRdKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyByZWx5aW5nIG9uIHRoZSBzYW1lIG9kZCBjaHJvbWUgYmVoYXZpb3VyIGFzIGFib3ZlLlxuICAgICAgICAgIHN0cmVhbS5yZW1vdmVUcmFjayhzZW5kZXIudHJhY2spO1xuICAgICAgICB9XG4gICAgICAgIHBjLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KCduZWdvdGlhdGlvbm5lZWRlZCcpKTtcbiAgICAgIH1cbiAgICB9O1xuICB9LFxuXG4gIHNoaW1QZWVyQ29ubmVjdGlvbjogZnVuY3Rpb24od2luZG93KSB7XG4gICAgdmFyIGJyb3dzZXJEZXRhaWxzID0gdXRpbHMuZGV0ZWN0QnJvd3Nlcih3aW5kb3cpO1xuXG4gICAgLy8gVGhlIFJUQ1BlZXJDb25uZWN0aW9uIG9iamVjdC5cbiAgICBpZiAoIXdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiAmJiB3aW5kb3cud2Via2l0UlRDUGVlckNvbm5lY3Rpb24pIHtcbiAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiA9IGZ1bmN0aW9uKHBjQ29uZmlnLCBwY0NvbnN0cmFpbnRzKSB7XG4gICAgICAgIC8vIFRyYW5zbGF0ZSBpY2VUcmFuc3BvcnRQb2xpY3kgdG8gaWNlVHJhbnNwb3J0cyxcbiAgICAgICAgLy8gc2VlIGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3Avd2VicnRjL2lzc3Vlcy9kZXRhaWw/aWQ9NDg2OVxuICAgICAgICAvLyB0aGlzIHdhcyBmaXhlZCBpbiBNNTYgYWxvbmcgd2l0aCB1bnByZWZpeGluZyBSVENQZWVyQ29ubmVjdGlvbi5cbiAgICAgICAgbG9nZ2luZygnUGVlckNvbm5lY3Rpb24nKTtcbiAgICAgICAgaWYgKHBjQ29uZmlnICYmIHBjQ29uZmlnLmljZVRyYW5zcG9ydFBvbGljeSkge1xuICAgICAgICAgIHBjQ29uZmlnLmljZVRyYW5zcG9ydHMgPSBwY0NvbmZpZy5pY2VUcmFuc3BvcnRQb2xpY3k7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbmV3IHdpbmRvdy53ZWJraXRSVENQZWVyQ29ubmVjdGlvbihwY0NvbmZpZywgcGNDb25zdHJhaW50cyk7XG4gICAgICB9O1xuICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSA9XG4gICAgICAgICAgd2luZG93LndlYmtpdFJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZTtcbiAgICAgIC8vIHdyYXAgc3RhdGljIG1ldGhvZHMuIEN1cnJlbnRseSBqdXN0IGdlbmVyYXRlQ2VydGlmaWNhdGUuXG4gICAgICBpZiAod2luZG93LndlYmtpdFJUQ1BlZXJDb25uZWN0aW9uLmdlbmVyYXRlQ2VydGlmaWNhdGUpIHtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiwgJ2dlbmVyYXRlQ2VydGlmaWNhdGUnLCB7XG4gICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiB3aW5kb3cud2Via2l0UlRDUGVlckNvbm5lY3Rpb24uZ2VuZXJhdGVDZXJ0aWZpY2F0ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBtaWdyYXRlIGZyb20gbm9uLXNwZWMgUlRDSWNlU2VydmVyLnVybCB0byBSVENJY2VTZXJ2ZXIudXJsc1xuICAgICAgdmFyIE9yaWdQZWVyQ29ubmVjdGlvbiA9IHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbjtcbiAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiA9IGZ1bmN0aW9uKHBjQ29uZmlnLCBwY0NvbnN0cmFpbnRzKSB7XG4gICAgICAgIGlmIChwY0NvbmZpZyAmJiBwY0NvbmZpZy5pY2VTZXJ2ZXJzKSB7XG4gICAgICAgICAgdmFyIG5ld0ljZVNlcnZlcnMgPSBbXTtcbiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBjQ29uZmlnLmljZVNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBzZXJ2ZXIgPSBwY0NvbmZpZy5pY2VTZXJ2ZXJzW2ldO1xuICAgICAgICAgICAgaWYgKCFzZXJ2ZXIuaGFzT3duUHJvcGVydHkoJ3VybHMnKSAmJlxuICAgICAgICAgICAgICAgIHNlcnZlci5oYXNPd25Qcm9wZXJ0eSgndXJsJykpIHtcbiAgICAgICAgICAgICAgdXRpbHMuZGVwcmVjYXRlZCgnUlRDSWNlU2VydmVyLnVybCcsICdSVENJY2VTZXJ2ZXIudXJscycpO1xuICAgICAgICAgICAgICBzZXJ2ZXIgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KHNlcnZlcikpO1xuICAgICAgICAgICAgICBzZXJ2ZXIudXJscyA9IHNlcnZlci51cmw7XG4gICAgICAgICAgICAgIG5ld0ljZVNlcnZlcnMucHVzaChzZXJ2ZXIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgbmV3SWNlU2VydmVycy5wdXNoKHBjQ29uZmlnLmljZVNlcnZlcnNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBwY0NvbmZpZy5pY2VTZXJ2ZXJzID0gbmV3SWNlU2VydmVycztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IE9yaWdQZWVyQ29ubmVjdGlvbihwY0NvbmZpZywgcGNDb25zdHJhaW50cyk7XG4gICAgICB9O1xuICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSA9IE9yaWdQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGU7XG4gICAgICAvLyB3cmFwIHN0YXRpYyBtZXRob2RzLiBDdXJyZW50bHkganVzdCBnZW5lcmF0ZUNlcnRpZmljYXRlLlxuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiwgJ2dlbmVyYXRlQ2VydGlmaWNhdGUnLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIE9yaWdQZWVyQ29ubmVjdGlvbi5nZW5lcmF0ZUNlcnRpZmljYXRlO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgb3JpZ0dldFN0YXRzID0gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5nZXRTdGF0cztcbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmdldFN0YXRzID0gZnVuY3Rpb24oc2VsZWN0b3IsXG4gICAgICAgIHN1Y2Nlc3NDYWxsYmFjaywgZXJyb3JDYWxsYmFjaykge1xuICAgICAgdmFyIHBjID0gdGhpcztcbiAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzO1xuXG4gICAgICAvLyBJZiBzZWxlY3RvciBpcyBhIGZ1bmN0aW9uIHRoZW4gd2UgYXJlIGluIHRoZSBvbGQgc3R5bGUgc3RhdHMgc28ganVzdFxuICAgICAgLy8gcGFzcyBiYWNrIHRoZSBvcmlnaW5hbCBnZXRTdGF0cyBmb3JtYXQgdG8gYXZvaWQgYnJlYWtpbmcgb2xkIHVzZXJzLlxuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIHR5cGVvZiBzZWxlY3RvciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gb3JpZ0dldFN0YXRzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICB9XG5cbiAgICAgIC8vIFdoZW4gc3BlYy1zdHlsZSBnZXRTdGF0cyBpcyBzdXBwb3J0ZWQsIHJldHVybiB0aG9zZSB3aGVuIGNhbGxlZCB3aXRoXG4gICAgICAvLyBlaXRoZXIgbm8gYXJndW1lbnRzIG9yIHRoZSBzZWxlY3RvciBhcmd1bWVudCBpcyBudWxsLlxuICAgICAgaWYgKG9yaWdHZXRTdGF0cy5sZW5ndGggPT09IDAgJiYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDAgfHxcbiAgICAgICAgICB0eXBlb2YgYXJndW1lbnRzWzBdICE9PSAnZnVuY3Rpb24nKSkge1xuICAgICAgICByZXR1cm4gb3JpZ0dldFN0YXRzLmFwcGx5KHRoaXMsIFtdKTtcbiAgICAgIH1cblxuICAgICAgdmFyIGZpeENocm9tZVN0YXRzXyA9IGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG4gICAgICAgIHZhciBzdGFuZGFyZFJlcG9ydCA9IHt9O1xuICAgICAgICB2YXIgcmVwb3J0cyA9IHJlc3BvbnNlLnJlc3VsdCgpO1xuICAgICAgICByZXBvcnRzLmZvckVhY2goZnVuY3Rpb24ocmVwb3J0KSB7XG4gICAgICAgICAgdmFyIHN0YW5kYXJkU3RhdHMgPSB7XG4gICAgICAgICAgICBpZDogcmVwb3J0LmlkLFxuICAgICAgICAgICAgdGltZXN0YW1wOiByZXBvcnQudGltZXN0YW1wLFxuICAgICAgICAgICAgdHlwZToge1xuICAgICAgICAgICAgICBsb2NhbGNhbmRpZGF0ZTogJ2xvY2FsLWNhbmRpZGF0ZScsXG4gICAgICAgICAgICAgIHJlbW90ZWNhbmRpZGF0ZTogJ3JlbW90ZS1jYW5kaWRhdGUnXG4gICAgICAgICAgICB9W3JlcG9ydC50eXBlXSB8fCByZXBvcnQudHlwZVxuICAgICAgICAgIH07XG4gICAgICAgICAgcmVwb3J0Lm5hbWVzKCkuZm9yRWFjaChmdW5jdGlvbihuYW1lKSB7XG4gICAgICAgICAgICBzdGFuZGFyZFN0YXRzW25hbWVdID0gcmVwb3J0LnN0YXQobmFtZSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgc3RhbmRhcmRSZXBvcnRbc3RhbmRhcmRTdGF0cy5pZF0gPSBzdGFuZGFyZFN0YXRzO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gc3RhbmRhcmRSZXBvcnQ7XG4gICAgICB9O1xuXG4gICAgICAvLyBzaGltIGdldFN0YXRzIHdpdGggbWFwbGlrZSBzdXBwb3J0XG4gICAgICB2YXIgbWFrZU1hcFN0YXRzID0gZnVuY3Rpb24oc3RhdHMpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBNYXAoT2JqZWN0LmtleXMoc3RhdHMpLm1hcChmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgICByZXR1cm4gW2tleSwgc3RhdHNba2V5XV07XG4gICAgICAgIH0pKTtcbiAgICAgIH07XG5cbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID49IDIpIHtcbiAgICAgICAgdmFyIHN1Y2Nlc3NDYWxsYmFja1dyYXBwZXJfID0gZnVuY3Rpb24ocmVzcG9uc2UpIHtcbiAgICAgICAgICBhcmdzWzFdKG1ha2VNYXBTdGF0cyhmaXhDaHJvbWVTdGF0c18ocmVzcG9uc2UpKSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIG9yaWdHZXRTdGF0cy5hcHBseSh0aGlzLCBbc3VjY2Vzc0NhbGxiYWNrV3JhcHBlcl8sXG4gICAgICAgICAgYXJndW1lbnRzWzBdXSk7XG4gICAgICB9XG5cbiAgICAgIC8vIHByb21pc2Utc3VwcG9ydFxuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICBvcmlnR2V0U3RhdHMuYXBwbHkocGMsIFtcbiAgICAgICAgICBmdW5jdGlvbihyZXNwb25zZSkge1xuICAgICAgICAgICAgcmVzb2x2ZShtYWtlTWFwU3RhdHMoZml4Q2hyb21lU3RhdHNfKHJlc3BvbnNlKSkpO1xuICAgICAgICAgIH0sIHJlamVjdF0pO1xuICAgICAgfSkudGhlbihzdWNjZXNzQ2FsbGJhY2ssIGVycm9yQ2FsbGJhY2spO1xuICAgIH07XG5cbiAgICAvLyBhZGQgcHJvbWlzZSBzdXBwb3J0IC0tIG5hdGl2ZWx5IGF2YWlsYWJsZSBpbiBDaHJvbWUgNTFcbiAgICBpZiAoYnJvd3NlckRldGFpbHMudmVyc2lvbiA8IDUxKSB7XG4gICAgICBbJ3NldExvY2FsRGVzY3JpcHRpb24nLCAnc2V0UmVtb3RlRGVzY3JpcHRpb24nLCAnYWRkSWNlQ2FuZGlkYXRlJ11cbiAgICAgICAgICAuZm9yRWFjaChmdW5jdGlvbihtZXRob2QpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVNZXRob2QgPSB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlW21ldGhvZF07XG4gICAgICAgICAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlW21ldGhvZF0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgICAgICAgIHZhciBwYyA9IHRoaXM7XG4gICAgICAgICAgICAgIHZhciBwcm9taXNlID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgICAgICAgICAgbmF0aXZlTWV0aG9kLmFwcGx5KHBjLCBbYXJnc1swXSwgcmVzb2x2ZSwgcmVqZWN0XSk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICBpZiAoYXJncy5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmV0dXJuIHByb21pc2UudGhlbihmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBhcmdzWzFdLmFwcGx5KG51bGwsIFtdKTtcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgZnVuY3Rpb24oZXJyKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFyZ3MubGVuZ3RoID49IDMpIHtcbiAgICAgICAgICAgICAgICAgIGFyZ3NbMl0uYXBwbHkobnVsbCwgW2Vycl0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIHByb21pc2Ugc3VwcG9ydCBmb3IgY3JlYXRlT2ZmZXIgYW5kIGNyZWF0ZUFuc3dlci4gQXZhaWxhYmxlICh3aXRob3V0XG4gICAgLy8gYnVncykgc2luY2UgTTUyOiBjcmJ1Zy82MTkyODlcbiAgICBpZiAoYnJvd3NlckRldGFpbHMudmVyc2lvbiA8IDUyKSB7XG4gICAgICBbJ2NyZWF0ZU9mZmVyJywgJ2NyZWF0ZUFuc3dlciddLmZvckVhY2goZnVuY3Rpb24obWV0aG9kKSB7XG4gICAgICAgIHZhciBuYXRpdmVNZXRob2QgPSB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlW21ldGhvZF07XG4gICAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGVbbWV0aG9kXSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHZhciBwYyA9IHRoaXM7XG4gICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAxIHx8IChhcmd1bWVudHMubGVuZ3RoID09PSAxICYmXG4gICAgICAgICAgICAgIHR5cGVvZiBhcmd1bWVudHNbMF0gPT09ICdvYmplY3QnKSkge1xuICAgICAgICAgICAgdmFyIG9wdHMgPSBhcmd1bWVudHMubGVuZ3RoID09PSAxID8gYXJndW1lbnRzWzBdIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAgICAgICBuYXRpdmVNZXRob2QuYXBwbHkocGMsIFtyZXNvbHZlLCByZWplY3QsIG9wdHNdKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbmF0aXZlTWV0aG9kLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH07XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBzaGltIGltcGxpY2l0IGNyZWF0aW9uIG9mIFJUQ1Nlc3Npb25EZXNjcmlwdGlvbi9SVENJY2VDYW5kaWRhdGVcbiAgICBbJ3NldExvY2FsRGVzY3JpcHRpb24nLCAnc2V0UmVtb3RlRGVzY3JpcHRpb24nLCAnYWRkSWNlQ2FuZGlkYXRlJ11cbiAgICAgICAgLmZvckVhY2goZnVuY3Rpb24obWV0aG9kKSB7XG4gICAgICAgICAgdmFyIG5hdGl2ZU1ldGhvZCA9IHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGVbbWV0aG9kXTtcbiAgICAgICAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlW21ldGhvZF0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGFyZ3VtZW50c1swXSA9IG5ldyAoKG1ldGhvZCA9PT0gJ2FkZEljZUNhbmRpZGF0ZScpID9cbiAgICAgICAgICAgICAgICB3aW5kb3cuUlRDSWNlQ2FuZGlkYXRlIDpcbiAgICAgICAgICAgICAgICB3aW5kb3cuUlRDU2Vzc2lvbkRlc2NyaXB0aW9uKShhcmd1bWVudHNbMF0pO1xuICAgICAgICAgICAgcmV0dXJuIG5hdGl2ZU1ldGhvZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuXG4gICAgLy8gc3VwcG9ydCBmb3IgYWRkSWNlQ2FuZGlkYXRlKG51bGwgb3IgdW5kZWZpbmVkKVxuICAgIHZhciBuYXRpdmVBZGRJY2VDYW5kaWRhdGUgPVxuICAgICAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmFkZEljZUNhbmRpZGF0ZTtcbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmFkZEljZUNhbmRpZGF0ZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKCFhcmd1bWVudHNbMF0pIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50c1sxXSkge1xuICAgICAgICAgIGFyZ3VtZW50c1sxXS5hcHBseShudWxsKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gbmF0aXZlQWRkSWNlQ2FuZGlkYXRlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfTtcbiAgfVxufTtcbiIsIi8qXG4gKiAgQ29weXJpZ2h0IChjKSAyMDE2IFRoZSBXZWJSVEMgcHJvamVjdCBhdXRob3JzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqICBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhIEJTRC1zdHlsZSBsaWNlbnNlXG4gKiAgdGhhdCBjYW4gYmUgZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBvZiB0aGUgc291cmNlXG4gKiAgdHJlZS5cbiAqL1xuIC8qIGVzbGludC1lbnYgbm9kZSAqL1xuJ3VzZSBzdHJpY3QnO1xudmFyIHV0aWxzID0gcmVxdWlyZSgnLi4vdXRpbHMuanMnKTtcbnZhciBsb2dnaW5nID0gdXRpbHMubG9nO1xuXG4vLyBFeHBvc2UgcHVibGljIG1ldGhvZHMuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHdpbmRvdykge1xuICB2YXIgYnJvd3NlckRldGFpbHMgPSB1dGlscy5kZXRlY3RCcm93c2VyKHdpbmRvdyk7XG4gIHZhciBuYXZpZ2F0b3IgPSB3aW5kb3cgJiYgd2luZG93Lm5hdmlnYXRvcjtcblxuICB2YXIgY29uc3RyYWludHNUb0Nocm9tZV8gPSBmdW5jdGlvbihjKSB7XG4gICAgaWYgKHR5cGVvZiBjICE9PSAnb2JqZWN0JyB8fCBjLm1hbmRhdG9yeSB8fCBjLm9wdGlvbmFsKSB7XG4gICAgICByZXR1cm4gYztcbiAgICB9XG4gICAgdmFyIGNjID0ge307XG4gICAgT2JqZWN0LmtleXMoYykuZm9yRWFjaChmdW5jdGlvbihrZXkpIHtcbiAgICAgIGlmIChrZXkgPT09ICdyZXF1aXJlJyB8fCBrZXkgPT09ICdhZHZhbmNlZCcgfHwga2V5ID09PSAnbWVkaWFTb3VyY2UnKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHZhciByID0gKHR5cGVvZiBjW2tleV0gPT09ICdvYmplY3QnKSA/IGNba2V5XSA6IHtpZGVhbDogY1trZXldfTtcbiAgICAgIGlmIChyLmV4YWN0ICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIHIuZXhhY3QgPT09ICdudW1iZXInKSB7XG4gICAgICAgIHIubWluID0gci5tYXggPSByLmV4YWN0O1xuICAgICAgfVxuICAgICAgdmFyIG9sZG5hbWVfID0gZnVuY3Rpb24ocHJlZml4LCBuYW1lKSB7XG4gICAgICAgIGlmIChwcmVmaXgpIHtcbiAgICAgICAgICByZXR1cm4gcHJlZml4ICsgbmFtZS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIG5hbWUuc2xpY2UoMSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIChuYW1lID09PSAnZGV2aWNlSWQnKSA/ICdzb3VyY2VJZCcgOiBuYW1lO1xuICAgICAgfTtcbiAgICAgIGlmIChyLmlkZWFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY2Mub3B0aW9uYWwgPSBjYy5vcHRpb25hbCB8fCBbXTtcbiAgICAgICAgdmFyIG9jID0ge307XG4gICAgICAgIGlmICh0eXBlb2Ygci5pZGVhbCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICBvY1tvbGRuYW1lXygnbWluJywga2V5KV0gPSByLmlkZWFsO1xuICAgICAgICAgIGNjLm9wdGlvbmFsLnB1c2gob2MpO1xuICAgICAgICAgIG9jID0ge307XG4gICAgICAgICAgb2Nbb2xkbmFtZV8oJ21heCcsIGtleSldID0gci5pZGVhbDtcbiAgICAgICAgICBjYy5vcHRpb25hbC5wdXNoKG9jKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvY1tvbGRuYW1lXygnJywga2V5KV0gPSByLmlkZWFsO1xuICAgICAgICAgIGNjLm9wdGlvbmFsLnB1c2gob2MpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoci5leGFjdCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiByLmV4YWN0ICE9PSAnbnVtYmVyJykge1xuICAgICAgICBjYy5tYW5kYXRvcnkgPSBjYy5tYW5kYXRvcnkgfHwge307XG4gICAgICAgIGNjLm1hbmRhdG9yeVtvbGRuYW1lXygnJywga2V5KV0gPSByLmV4YWN0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgWydtaW4nLCAnbWF4J10uZm9yRWFjaChmdW5jdGlvbihtaXgpIHtcbiAgICAgICAgICBpZiAoclttaXhdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNjLm1hbmRhdG9yeSA9IGNjLm1hbmRhdG9yeSB8fCB7fTtcbiAgICAgICAgICAgIGNjLm1hbmRhdG9yeVtvbGRuYW1lXyhtaXgsIGtleSldID0gclttaXhdO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgaWYgKGMuYWR2YW5jZWQpIHtcbiAgICAgIGNjLm9wdGlvbmFsID0gKGNjLm9wdGlvbmFsIHx8IFtdKS5jb25jYXQoYy5hZHZhbmNlZCk7XG4gICAgfVxuICAgIHJldHVybiBjYztcbiAgfTtcblxuICB2YXIgc2hpbUNvbnN0cmFpbnRzXyA9IGZ1bmN0aW9uKGNvbnN0cmFpbnRzLCBmdW5jKSB7XG4gICAgaWYgKGJyb3dzZXJEZXRhaWxzLnZlcnNpb24gPj0gNjEpIHtcbiAgICAgIHJldHVybiBmdW5jKGNvbnN0cmFpbnRzKTtcbiAgICB9XG4gICAgY29uc3RyYWludHMgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGNvbnN0cmFpbnRzKSk7XG4gICAgaWYgKGNvbnN0cmFpbnRzICYmIHR5cGVvZiBjb25zdHJhaW50cy5hdWRpbyA9PT0gJ29iamVjdCcpIHtcbiAgICAgIHZhciByZW1hcCA9IGZ1bmN0aW9uKG9iaiwgYSwgYikge1xuICAgICAgICBpZiAoYSBpbiBvYmogJiYgIShiIGluIG9iaikpIHtcbiAgICAgICAgICBvYmpbYl0gPSBvYmpbYV07XG4gICAgICAgICAgZGVsZXRlIG9ialthXTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIGNvbnN0cmFpbnRzID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShjb25zdHJhaW50cykpO1xuICAgICAgcmVtYXAoY29uc3RyYWludHMuYXVkaW8sICdhdXRvR2FpbkNvbnRyb2wnLCAnZ29vZ0F1dG9HYWluQ29udHJvbCcpO1xuICAgICAgcmVtYXAoY29uc3RyYWludHMuYXVkaW8sICdub2lzZVN1cHByZXNzaW9uJywgJ2dvb2dOb2lzZVN1cHByZXNzaW9uJyk7XG4gICAgICBjb25zdHJhaW50cy5hdWRpbyA9IGNvbnN0cmFpbnRzVG9DaHJvbWVfKGNvbnN0cmFpbnRzLmF1ZGlvKTtcbiAgICB9XG4gICAgaWYgKGNvbnN0cmFpbnRzICYmIHR5cGVvZiBjb25zdHJhaW50cy52aWRlbyA9PT0gJ29iamVjdCcpIHtcbiAgICAgIC8vIFNoaW0gZmFjaW5nTW9kZSBmb3IgbW9iaWxlICYgc3VyZmFjZSBwcm8uXG4gICAgICB2YXIgZmFjZSA9IGNvbnN0cmFpbnRzLnZpZGVvLmZhY2luZ01vZGU7XG4gICAgICBmYWNlID0gZmFjZSAmJiAoKHR5cGVvZiBmYWNlID09PSAnb2JqZWN0JykgPyBmYWNlIDoge2lkZWFsOiBmYWNlfSk7XG4gICAgICB2YXIgZ2V0U3VwcG9ydGVkRmFjaW5nTW9kZUxpZXMgPSBicm93c2VyRGV0YWlscy52ZXJzaW9uIDwgNjY7XG5cbiAgICAgIGlmICgoZmFjZSAmJiAoZmFjZS5leGFjdCA9PT0gJ3VzZXInIHx8IGZhY2UuZXhhY3QgPT09ICdlbnZpcm9ubWVudCcgfHxcbiAgICAgICAgICAgICAgICAgICAgZmFjZS5pZGVhbCA9PT0gJ3VzZXInIHx8IGZhY2UuaWRlYWwgPT09ICdlbnZpcm9ubWVudCcpKSAmJlxuICAgICAgICAgICEobmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRTdXBwb3J0ZWRDb25zdHJhaW50cyAmJlxuICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRTdXBwb3J0ZWRDb25zdHJhaW50cygpLmZhY2luZ01vZGUgJiZcbiAgICAgICAgICAgICFnZXRTdXBwb3J0ZWRGYWNpbmdNb2RlTGllcykpIHtcbiAgICAgICAgZGVsZXRlIGNvbnN0cmFpbnRzLnZpZGVvLmZhY2luZ01vZGU7XG4gICAgICAgIHZhciBtYXRjaGVzO1xuICAgICAgICBpZiAoZmFjZS5leGFjdCA9PT0gJ2Vudmlyb25tZW50JyB8fCBmYWNlLmlkZWFsID09PSAnZW52aXJvbm1lbnQnKSB7XG4gICAgICAgICAgbWF0Y2hlcyA9IFsnYmFjaycsICdyZWFyJ107XG4gICAgICAgIH0gZWxzZSBpZiAoZmFjZS5leGFjdCA9PT0gJ3VzZXInIHx8IGZhY2UuaWRlYWwgPT09ICd1c2VyJykge1xuICAgICAgICAgIG1hdGNoZXMgPSBbJ2Zyb250J107XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1hdGNoZXMpIHtcbiAgICAgICAgICAvLyBMb29rIGZvciBtYXRjaGVzIGluIGxhYmVsLCBvciB1c2UgbGFzdCBjYW0gZm9yIGJhY2sgKHR5cGljYWwpLlxuICAgICAgICAgIHJldHVybiBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmVudW1lcmF0ZURldmljZXMoKVxuICAgICAgICAgIC50aGVuKGZ1bmN0aW9uKGRldmljZXMpIHtcbiAgICAgICAgICAgIGRldmljZXMgPSBkZXZpY2VzLmZpbHRlcihmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgIHJldHVybiBkLmtpbmQgPT09ICd2aWRlb2lucHV0JztcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdmFyIGRldiA9IGRldmljZXMuZmluZChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgIHJldHVybiBtYXRjaGVzLnNvbWUoZnVuY3Rpb24obWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZC5sYWJlbC50b0xvd2VyQ2FzZSgpLmluZGV4T2YobWF0Y2gpICE9PSAtMTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmICghZGV2ICYmIGRldmljZXMubGVuZ3RoICYmIG1hdGNoZXMuaW5kZXhPZignYmFjaycpICE9PSAtMSkge1xuICAgICAgICAgICAgICBkZXYgPSBkZXZpY2VzW2RldmljZXMubGVuZ3RoIC0gMV07IC8vIG1vcmUgbGlrZWx5IHRoZSBiYWNrIGNhbVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGRldikge1xuICAgICAgICAgICAgICBjb25zdHJhaW50cy52aWRlby5kZXZpY2VJZCA9IGZhY2UuZXhhY3QgPyB7ZXhhY3Q6IGRldi5kZXZpY2VJZH0gOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7aWRlYWw6IGRldi5kZXZpY2VJZH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdHJhaW50cy52aWRlbyA9IGNvbnN0cmFpbnRzVG9DaHJvbWVfKGNvbnN0cmFpbnRzLnZpZGVvKTtcbiAgICAgICAgICAgIGxvZ2dpbmcoJ2Nocm9tZTogJyArIEpTT04uc3RyaW5naWZ5KGNvbnN0cmFpbnRzKSk7XG4gICAgICAgICAgICByZXR1cm4gZnVuYyhjb25zdHJhaW50cyk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNvbnN0cmFpbnRzLnZpZGVvID0gY29uc3RyYWludHNUb0Nocm9tZV8oY29uc3RyYWludHMudmlkZW8pO1xuICAgIH1cbiAgICBsb2dnaW5nKCdjaHJvbWU6ICcgKyBKU09OLnN0cmluZ2lmeShjb25zdHJhaW50cykpO1xuICAgIHJldHVybiBmdW5jKGNvbnN0cmFpbnRzKTtcbiAgfTtcblxuICB2YXIgc2hpbUVycm9yXyA9IGZ1bmN0aW9uKGUpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbmFtZToge1xuICAgICAgICBQZXJtaXNzaW9uRGVuaWVkRXJyb3I6ICdOb3RBbGxvd2VkRXJyb3InLFxuICAgICAgICBJbnZhbGlkU3RhdGVFcnJvcjogJ05vdFJlYWRhYmxlRXJyb3InLFxuICAgICAgICBEZXZpY2VzTm90Rm91bmRFcnJvcjogJ05vdEZvdW5kRXJyb3InLFxuICAgICAgICBDb25zdHJhaW50Tm90U2F0aXNmaWVkRXJyb3I6ICdPdmVyY29uc3RyYWluZWRFcnJvcicsXG4gICAgICAgIFRyYWNrU3RhcnRFcnJvcjogJ05vdFJlYWRhYmxlRXJyb3InLFxuICAgICAgICBNZWRpYURldmljZUZhaWxlZER1ZVRvU2h1dGRvd246ICdOb3RSZWFkYWJsZUVycm9yJyxcbiAgICAgICAgTWVkaWFEZXZpY2VLaWxsU3dpdGNoT246ICdOb3RSZWFkYWJsZUVycm9yJ1xuICAgICAgfVtlLm5hbWVdIHx8IGUubmFtZSxcbiAgICAgIG1lc3NhZ2U6IGUubWVzc2FnZSxcbiAgICAgIGNvbnN0cmFpbnQ6IGUuY29uc3RyYWludE5hbWUsXG4gICAgICB0b1N0cmluZzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm5hbWUgKyAodGhpcy5tZXNzYWdlICYmICc6ICcpICsgdGhpcy5tZXNzYWdlO1xuICAgICAgfVxuICAgIH07XG4gIH07XG5cbiAgdmFyIGdldFVzZXJNZWRpYV8gPSBmdW5jdGlvbihjb25zdHJhaW50cywgb25TdWNjZXNzLCBvbkVycm9yKSB7XG4gICAgc2hpbUNvbnN0cmFpbnRzXyhjb25zdHJhaW50cywgZnVuY3Rpb24oYykge1xuICAgICAgbmF2aWdhdG9yLndlYmtpdEdldFVzZXJNZWRpYShjLCBvblN1Y2Nlc3MsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgaWYgKG9uRXJyb3IpIHtcbiAgICAgICAgICBvbkVycm9yKHNoaW1FcnJvcl8oZSkpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfTtcblxuICBuYXZpZ2F0b3IuZ2V0VXNlck1lZGlhID0gZ2V0VXNlck1lZGlhXztcblxuICAvLyBSZXR1cm5zIHRoZSByZXN1bHQgb2YgZ2V0VXNlck1lZGlhIGFzIGEgUHJvbWlzZS5cbiAgdmFyIGdldFVzZXJNZWRpYVByb21pc2VfID0gZnVuY3Rpb24oY29uc3RyYWludHMpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICBuYXZpZ2F0b3IuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzLCByZXNvbHZlLCByZWplY3QpO1xuICAgIH0pO1xuICB9O1xuXG4gIGlmICghbmF2aWdhdG9yLm1lZGlhRGV2aWNlcykge1xuICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMgPSB7XG4gICAgICBnZXRVc2VyTWVkaWE6IGdldFVzZXJNZWRpYVByb21pc2VfLFxuICAgICAgZW51bWVyYXRlRGV2aWNlczogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlKSB7XG4gICAgICAgICAgdmFyIGtpbmRzID0ge2F1ZGlvOiAnYXVkaW9pbnB1dCcsIHZpZGVvOiAndmlkZW9pbnB1dCd9O1xuICAgICAgICAgIHJldHVybiB3aW5kb3cuTWVkaWFTdHJlYW1UcmFjay5nZXRTb3VyY2VzKGZ1bmN0aW9uKGRldmljZXMpIHtcbiAgICAgICAgICAgIHJlc29sdmUoZGV2aWNlcy5tYXAoZnVuY3Rpb24oZGV2aWNlKSB7XG4gICAgICAgICAgICAgIHJldHVybiB7bGFiZWw6IGRldmljZS5sYWJlbCxcbiAgICAgICAgICAgICAgICBraW5kOiBraW5kc1tkZXZpY2Uua2luZF0sXG4gICAgICAgICAgICAgICAgZGV2aWNlSWQ6IGRldmljZS5pZCxcbiAgICAgICAgICAgICAgICBncm91cElkOiAnJ307XG4gICAgICAgICAgICB9KSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICAgIGdldFN1cHBvcnRlZENvbnN0cmFpbnRzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBkZXZpY2VJZDogdHJ1ZSwgZWNob0NhbmNlbGxhdGlvbjogdHJ1ZSwgZmFjaW5nTW9kZTogdHJ1ZSxcbiAgICAgICAgICBmcmFtZVJhdGU6IHRydWUsIGhlaWdodDogdHJ1ZSwgd2lkdGg6IHRydWVcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgLy8gQSBzaGltIGZvciBnZXRVc2VyTWVkaWEgbWV0aG9kIG9uIHRoZSBtZWRpYURldmljZXMgb2JqZWN0LlxuICAvLyBUT0RPKEthcHRlbkphbnNzb24pIHJlbW92ZSBvbmNlIGltcGxlbWVudGVkIGluIENocm9tZSBzdGFibGUuXG4gIGlmICghbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEpIHtcbiAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSA9IGZ1bmN0aW9uKGNvbnN0cmFpbnRzKSB7XG4gICAgICByZXR1cm4gZ2V0VXNlck1lZGlhUHJvbWlzZV8oY29uc3RyYWludHMpO1xuICAgIH07XG4gIH0gZWxzZSB7XG4gICAgLy8gRXZlbiB0aG91Z2ggQ2hyb21lIDQ1IGhhcyBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzIGFuZCBhIGdldFVzZXJNZWRpYVxuICAgIC8vIGZ1bmN0aW9uIHdoaWNoIHJldHVybnMgYSBQcm9taXNlLCBpdCBkb2VzIG5vdCBhY2NlcHQgc3BlYy1zdHlsZVxuICAgIC8vIGNvbnN0cmFpbnRzLlxuICAgIHZhciBvcmlnR2V0VXNlck1lZGlhID0gbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEuXG4gICAgICAgIGJpbmQobmF2aWdhdG9yLm1lZGlhRGV2aWNlcyk7XG4gICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEgPSBmdW5jdGlvbihjcykge1xuICAgICAgcmV0dXJuIHNoaW1Db25zdHJhaW50c18oY3MsIGZ1bmN0aW9uKGMpIHtcbiAgICAgICAgcmV0dXJuIG9yaWdHZXRVc2VyTWVkaWEoYykudGhlbihmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgICBpZiAoYy5hdWRpbyAmJiAhc3RyZWFtLmdldEF1ZGlvVHJhY2tzKCkubGVuZ3RoIHx8XG4gICAgICAgICAgICAgIGMudmlkZW8gJiYgIXN0cmVhbS5nZXRWaWRlb1RyYWNrcygpLmxlbmd0aCkge1xuICAgICAgICAgICAgc3RyZWFtLmdldFRyYWNrcygpLmZvckVhY2goZnVuY3Rpb24odHJhY2spIHtcbiAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRE9NRXhjZXB0aW9uKCcnLCAnTm90Rm91bmRFcnJvcicpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gc3RyZWFtO1xuICAgICAgICB9LCBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHNoaW1FcnJvcl8oZSkpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH07XG4gIH1cblxuICAvLyBEdW1teSBkZXZpY2VjaGFuZ2UgZXZlbnQgbWV0aG9kcy5cbiAgLy8gVE9ETyhLYXB0ZW5KYW5zc29uKSByZW1vdmUgb25jZSBpbXBsZW1lbnRlZCBpbiBDaHJvbWUgc3RhYmxlLlxuICBpZiAodHlwZW9mIG5hdmlnYXRvci5tZWRpYURldmljZXMuYWRkRXZlbnRMaXN0ZW5lciA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgIGxvZ2dpbmcoJ0R1bW15IG1lZGlhRGV2aWNlcy5hZGRFdmVudExpc3RlbmVyIGNhbGxlZC4nKTtcbiAgICB9O1xuICB9XG4gIGlmICh0eXBlb2YgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5yZW1vdmVFdmVudExpc3RlbmVyID09PSAndW5kZWZpbmVkJykge1xuICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMucmVtb3ZlRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uKCkge1xuICAgICAgbG9nZ2luZygnRHVtbXkgbWVkaWFEZXZpY2VzLnJlbW92ZUV2ZW50TGlzdGVuZXIgY2FsbGVkLicpO1xuICAgIH07XG4gIH1cbn07XG4iLCIvKlxuICogIENvcHlyaWdodCAoYykgMjAxNyBUaGUgV2ViUlRDIHByb2plY3QgYXV0aG9ycy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiAgVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYSBCU0Qtc3R5bGUgbGljZW5zZVxuICogIHRoYXQgY2FuIGJlIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3Qgb2YgdGhlIHNvdXJjZVxuICogIHRyZWUuXG4gKi9cbiAvKiBlc2xpbnQtZW52IG5vZGUgKi9cbid1c2Ugc3RyaWN0JztcblxudmFyIFNEUFV0aWxzID0gcmVxdWlyZSgnc2RwJyk7XG52YXIgdXRpbHMgPSByZXF1aXJlKCcuL3V0aWxzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBzaGltUlRDSWNlQ2FuZGlkYXRlOiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICAvLyBmb3VuZGF0aW9uIGlzIGFyYml0cmFyaWx5IGNob3NlbiBhcyBhbiBpbmRpY2F0b3IgZm9yIGZ1bGwgc3VwcG9ydCBmb3JcbiAgICAvLyBodHRwczovL3czYy5naXRodWIuaW8vd2VicnRjLXBjLyNydGNpY2VjYW5kaWRhdGUtaW50ZXJmYWNlXG4gICAgaWYgKHdpbmRvdy5SVENJY2VDYW5kaWRhdGUgJiYgJ2ZvdW5kYXRpb24nIGluXG4gICAgICAgIHdpbmRvdy5SVENJY2VDYW5kaWRhdGUucHJvdG90eXBlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIE5hdGl2ZVJUQ0ljZUNhbmRpZGF0ZSA9IHdpbmRvdy5SVENJY2VDYW5kaWRhdGU7XG4gICAgd2luZG93LlJUQ0ljZUNhbmRpZGF0ZSA9IGZ1bmN0aW9uKGFyZ3MpIHtcbiAgICAgIC8vIFJlbW92ZSB0aGUgYT0gd2hpY2ggc2hvdWxkbid0IGJlIHBhcnQgb2YgdGhlIGNhbmRpZGF0ZSBzdHJpbmcuXG4gICAgICBpZiAodHlwZW9mIGFyZ3MgPT09ICdvYmplY3QnICYmIGFyZ3MuY2FuZGlkYXRlICYmXG4gICAgICAgICAgYXJncy5jYW5kaWRhdGUuaW5kZXhPZignYT0nKSA9PT0gMCkge1xuICAgICAgICBhcmdzID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShhcmdzKSk7XG4gICAgICAgIGFyZ3MuY2FuZGlkYXRlID0gYXJncy5jYW5kaWRhdGUuc3Vic3RyKDIpO1xuICAgICAgfVxuXG4gICAgICAvLyBBdWdtZW50IHRoZSBuYXRpdmUgY2FuZGlkYXRlIHdpdGggdGhlIHBhcnNlZCBmaWVsZHMuXG4gICAgICB2YXIgbmF0aXZlQ2FuZGlkYXRlID0gbmV3IE5hdGl2ZVJUQ0ljZUNhbmRpZGF0ZShhcmdzKTtcbiAgICAgIHZhciBwYXJzZWRDYW5kaWRhdGUgPSBTRFBVdGlscy5wYXJzZUNhbmRpZGF0ZShhcmdzLmNhbmRpZGF0ZSk7XG4gICAgICB2YXIgYXVnbWVudGVkQ2FuZGlkYXRlID0gT2JqZWN0LmFzc2lnbihuYXRpdmVDYW5kaWRhdGUsXG4gICAgICAgICAgcGFyc2VkQ2FuZGlkYXRlKTtcblxuICAgICAgLy8gQWRkIGEgc2VyaWFsaXplciB0aGF0IGRvZXMgbm90IHNlcmlhbGl6ZSB0aGUgZXh0cmEgYXR0cmlidXRlcy5cbiAgICAgIGF1Z21lbnRlZENhbmRpZGF0ZS50b0pTT04gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBjYW5kaWRhdGU6IGF1Z21lbnRlZENhbmRpZGF0ZS5jYW5kaWRhdGUsXG4gICAgICAgICAgc2RwTWlkOiBhdWdtZW50ZWRDYW5kaWRhdGUuc2RwTWlkLFxuICAgICAgICAgIHNkcE1MaW5lSW5kZXg6IGF1Z21lbnRlZENhbmRpZGF0ZS5zZHBNTGluZUluZGV4LFxuICAgICAgICAgIHVzZXJuYW1lRnJhZ21lbnQ6IGF1Z21lbnRlZENhbmRpZGF0ZS51c2VybmFtZUZyYWdtZW50LFxuICAgICAgICB9O1xuICAgICAgfTtcbiAgICAgIHJldHVybiBhdWdtZW50ZWRDYW5kaWRhdGU7XG4gICAgfTtcblxuICAgIC8vIEhvb2sgdXAgdGhlIGF1Z21lbnRlZCBjYW5kaWRhdGUgaW4gb25pY2VjYW5kaWRhdGUgYW5kXG4gICAgLy8gYWRkRXZlbnRMaXN0ZW5lcignaWNlY2FuZGlkYXRlJywgLi4uKVxuICAgIHV0aWxzLndyYXBQZWVyQ29ubmVjdGlvbkV2ZW50KHdpbmRvdywgJ2ljZWNhbmRpZGF0ZScsIGZ1bmN0aW9uKGUpIHtcbiAgICAgIGlmIChlLmNhbmRpZGF0ZSkge1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZSwgJ2NhbmRpZGF0ZScsIHtcbiAgICAgICAgICB2YWx1ZTogbmV3IHdpbmRvdy5SVENJY2VDYW5kaWRhdGUoZS5jYW5kaWRhdGUpLFxuICAgICAgICAgIHdyaXRhYmxlOiAnZmFsc2UnXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGU7XG4gICAgfSk7XG4gIH0sXG5cbiAgLy8gc2hpbUNyZWF0ZU9iamVjdFVSTCBtdXN0IGJlIGNhbGxlZCBiZWZvcmUgc2hpbVNvdXJjZU9iamVjdCB0byBhdm9pZCBsb29wLlxuXG4gIHNoaW1DcmVhdGVPYmplY3RVUkw6IGZ1bmN0aW9uKHdpbmRvdykge1xuICAgIHZhciBVUkwgPSB3aW5kb3cgJiYgd2luZG93LlVSTDtcblxuICAgIGlmICghKHR5cGVvZiB3aW5kb3cgPT09ICdvYmplY3QnICYmIHdpbmRvdy5IVE1MTWVkaWFFbGVtZW50ICYmXG4gICAgICAgICAgJ3NyY09iamVjdCcgaW4gd2luZG93LkhUTUxNZWRpYUVsZW1lbnQucHJvdG90eXBlICYmXG4gICAgICAgIFVSTC5jcmVhdGVPYmplY3RVUkwgJiYgVVJMLnJldm9rZU9iamVjdFVSTCkpIHtcbiAgICAgIC8vIE9ubHkgc2hpbSBDcmVhdGVPYmplY3RVUkwgdXNpbmcgc3JjT2JqZWN0IGlmIHNyY09iamVjdCBleGlzdHMuXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHZhciBuYXRpdmVDcmVhdGVPYmplY3RVUkwgPSBVUkwuY3JlYXRlT2JqZWN0VVJMLmJpbmQoVVJMKTtcbiAgICB2YXIgbmF0aXZlUmV2b2tlT2JqZWN0VVJMID0gVVJMLnJldm9rZU9iamVjdFVSTC5iaW5kKFVSTCk7XG4gICAgdmFyIHN0cmVhbXMgPSBuZXcgTWFwKCksIG5ld0lkID0gMDtcblxuICAgIFVSTC5jcmVhdGVPYmplY3RVUkwgPSBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgIGlmICgnZ2V0VHJhY2tzJyBpbiBzdHJlYW0pIHtcbiAgICAgICAgdmFyIHVybCA9ICdwb2x5YmxvYjonICsgKCsrbmV3SWQpO1xuICAgICAgICBzdHJlYW1zLnNldCh1cmwsIHN0cmVhbSk7XG4gICAgICAgIHV0aWxzLmRlcHJlY2F0ZWQoJ1VSTC5jcmVhdGVPYmplY3RVUkwoc3RyZWFtKScsXG4gICAgICAgICAgICAnZWxlbS5zcmNPYmplY3QgPSBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHVybDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuYXRpdmVDcmVhdGVPYmplY3RVUkwoc3RyZWFtKTtcbiAgICB9O1xuICAgIFVSTC5yZXZva2VPYmplY3RVUkwgPSBmdW5jdGlvbih1cmwpIHtcbiAgICAgIG5hdGl2ZVJldm9rZU9iamVjdFVSTCh1cmwpO1xuICAgICAgc3RyZWFtcy5kZWxldGUodXJsKTtcbiAgICB9O1xuXG4gICAgdmFyIGRzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iod2luZG93LkhUTUxNZWRpYUVsZW1lbnQucHJvdG90eXBlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzcmMnKTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkod2luZG93LkhUTUxNZWRpYUVsZW1lbnQucHJvdG90eXBlLCAnc3JjJywge1xuICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIGRzYy5nZXQuYXBwbHkodGhpcyk7XG4gICAgICB9LFxuICAgICAgc2V0OiBmdW5jdGlvbih1cmwpIHtcbiAgICAgICAgdGhpcy5zcmNPYmplY3QgPSBzdHJlYW1zLmdldCh1cmwpIHx8IG51bGw7XG4gICAgICAgIHJldHVybiBkc2Muc2V0LmFwcGx5KHRoaXMsIFt1cmxdKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHZhciBuYXRpdmVTZXRBdHRyaWJ1dGUgPSB3aW5kb3cuSFRNTE1lZGlhRWxlbWVudC5wcm90b3R5cGUuc2V0QXR0cmlidXRlO1xuICAgIHdpbmRvdy5IVE1MTWVkaWFFbGVtZW50LnByb3RvdHlwZS5zZXRBdHRyaWJ1dGUgPSBmdW5jdGlvbigpIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyICYmXG4gICAgICAgICAgKCcnICsgYXJndW1lbnRzWzBdKS50b0xvd2VyQ2FzZSgpID09PSAnc3JjJykge1xuICAgICAgICB0aGlzLnNyY09iamVjdCA9IHN0cmVhbXMuZ2V0KGFyZ3VtZW50c1sxXSkgfHwgbnVsbDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuYXRpdmVTZXRBdHRyaWJ1dGUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9O1xuICB9LFxuXG4gIHNoaW1NYXhNZXNzYWdlU2l6ZTogZnVuY3Rpb24od2luZG93KSB7XG4gICAgaWYgKHdpbmRvdy5SVENTY3RwVHJhbnNwb3J0IHx8ICF3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIGJyb3dzZXJEZXRhaWxzID0gdXRpbHMuZGV0ZWN0QnJvd3Nlcih3aW5kb3cpO1xuXG4gICAgaWYgKCEoJ3NjdHAnIGluIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUpKSB7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkod2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSwgJ3NjdHAnLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIHR5cGVvZiB0aGlzLl9zY3RwID09PSAndW5kZWZpbmVkJyA/IG51bGwgOiB0aGlzLl9zY3RwO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgc2N0cEluRGVzY3JpcHRpb24gPSBmdW5jdGlvbihkZXNjcmlwdGlvbikge1xuICAgICAgdmFyIHNlY3Rpb25zID0gU0RQVXRpbHMuc3BsaXRTZWN0aW9ucyhkZXNjcmlwdGlvbi5zZHApO1xuICAgICAgc2VjdGlvbnMuc2hpZnQoKTtcbiAgICAgIHJldHVybiBzZWN0aW9ucy5zb21lKGZ1bmN0aW9uKG1lZGlhU2VjdGlvbikge1xuICAgICAgICB2YXIgbUxpbmUgPSBTRFBVdGlscy5wYXJzZU1MaW5lKG1lZGlhU2VjdGlvbik7XG4gICAgICAgIHJldHVybiBtTGluZSAmJiBtTGluZS5raW5kID09PSAnYXBwbGljYXRpb24nXG4gICAgICAgICAgICAmJiBtTGluZS5wcm90b2NvbC5pbmRleE9mKCdTQ1RQJykgIT09IC0xO1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIHZhciBnZXRSZW1vdGVGaXJlZm94VmVyc2lvbiA9IGZ1bmN0aW9uKGRlc2NyaXB0aW9uKSB7XG4gICAgICAvLyBUT0RPOiBJcyB0aGVyZSBhIGJldHRlciBzb2x1dGlvbiBmb3IgZGV0ZWN0aW5nIEZpcmVmb3g/XG4gICAgICB2YXIgbWF0Y2ggPSBkZXNjcmlwdGlvbi5zZHAubWF0Y2goL21vemlsbGEuLi5USElTX0lTX1NEUEFSVEEtKFxcZCspLyk7XG4gICAgICBpZiAobWF0Y2ggPT09IG51bGwgfHwgbWF0Y2gubGVuZ3RoIDwgMikge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG4gICAgICB2YXIgdmVyc2lvbiA9IHBhcnNlSW50KG1hdGNoWzFdLCAxMCk7XG4gICAgICAvLyBUZXN0IGZvciBOYU4gKHllcywgdGhpcyBpcyB1Z2x5KVxuICAgICAgcmV0dXJuIHZlcnNpb24gIT09IHZlcnNpb24gPyAtMSA6IHZlcnNpb247XG4gICAgfTtcblxuICAgIHZhciBnZXRDYW5TZW5kTWF4TWVzc2FnZVNpemUgPSBmdW5jdGlvbihyZW1vdGVJc0ZpcmVmb3gpIHtcbiAgICAgIC8vIEV2ZXJ5IGltcGxlbWVudGF0aW9uIHdlIGtub3cgY2FuIHNlbmQgYXQgbGVhc3QgNjQgS2lCLlxuICAgICAgLy8gTm90ZTogQWx0aG91Z2ggQ2hyb21lIGlzIHRlY2huaWNhbGx5IGFibGUgdG8gc2VuZCB1cCB0byAyNTYgS2lCLCB0aGVcbiAgICAgIC8vICAgICAgIGRhdGEgZG9lcyBub3QgcmVhY2ggdGhlIG90aGVyIHBlZXIgcmVsaWFibHkuXG4gICAgICAvLyAgICAgICBTZWU6IGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC93ZWJydGMvaXNzdWVzL2RldGFpbD9pZD04NDE5XG4gICAgICB2YXIgY2FuU2VuZE1heE1lc3NhZ2VTaXplID0gNjU1MzY7XG4gICAgICBpZiAoYnJvd3NlckRldGFpbHMuYnJvd3NlciA9PT0gJ2ZpcmVmb3gnKSB7XG4gICAgICAgIGlmIChicm93c2VyRGV0YWlscy52ZXJzaW9uIDwgNTcpIHtcbiAgICAgICAgICBpZiAocmVtb3RlSXNGaXJlZm94ID09PSAtMSkge1xuICAgICAgICAgICAgLy8gRkYgPCA1NyB3aWxsIHNlbmQgaW4gMTYgS2lCIGNodW5rcyB1c2luZyB0aGUgZGVwcmVjYXRlZCBQUElEXG4gICAgICAgICAgICAvLyBmcmFnbWVudGF0aW9uLlxuICAgICAgICAgICAgY2FuU2VuZE1heE1lc3NhZ2VTaXplID0gMTYzODQ7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEhvd2V2ZXIsIG90aGVyIEZGIChhbmQgUkFXUlRDKSBjYW4gcmVhc3NlbWJsZSBQUElELWZyYWdtZW50ZWRcbiAgICAgICAgICAgIC8vIG1lc3NhZ2VzLiBUaHVzLCBzdXBwb3J0aW5nIH4yIEdpQiB3aGVuIHNlbmRpbmcuXG4gICAgICAgICAgICBjYW5TZW5kTWF4TWVzc2FnZVNpemUgPSAyMTQ3NDgzNjM3O1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBDdXJyZW50bHksIGFsbCBGRiA+PSA1NyB3aWxsIHJlc2V0IHRoZSByZW1vdGUgbWF4aW11bSBtZXNzYWdlIHNpemVcbiAgICAgICAgICAvLyB0byB0aGUgZGVmYXVsdCB2YWx1ZSB3aGVuIGEgZGF0YSBjaGFubmVsIGlzIGNyZWF0ZWQgYXQgYSBsYXRlclxuICAgICAgICAgIC8vIHN0YWdlLiA6KFxuICAgICAgICAgIC8vIFNlZTogaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTQyNjgzMVxuICAgICAgICAgIGNhblNlbmRNYXhNZXNzYWdlU2l6ZSA9XG4gICAgICAgICAgICBicm93c2VyRGV0YWlscy52ZXJzaW9uID09PSA1NyA/IDY1NTM1IDogNjU1MzY7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBjYW5TZW5kTWF4TWVzc2FnZVNpemU7XG4gICAgfTtcblxuICAgIHZhciBnZXRNYXhNZXNzYWdlU2l6ZSA9IGZ1bmN0aW9uKGRlc2NyaXB0aW9uLCByZW1vdGVJc0ZpcmVmb3gpIHtcbiAgICAgIC8vIE5vdGU6IDY1NTM2IGJ5dGVzIGlzIHRoZSBkZWZhdWx0IHZhbHVlIGZyb20gdGhlIFNEUCBzcGVjLiBBbHNvLFxuICAgICAgLy8gICAgICAgZXZlcnkgaW1wbGVtZW50YXRpb24gd2Uga25vdyBzdXBwb3J0cyByZWNlaXZpbmcgNjU1MzYgYnl0ZXMuXG4gICAgICB2YXIgbWF4TWVzc2FnZVNpemUgPSA2NTUzNjtcblxuICAgICAgLy8gRkYgNTcgaGFzIGEgc2xpZ2h0bHkgaW5jb3JyZWN0IGRlZmF1bHQgcmVtb3RlIG1heCBtZXNzYWdlIHNpemUsIHNvXG4gICAgICAvLyB3ZSBuZWVkIHRvIGFkanVzdCBpdCBoZXJlIHRvIGF2b2lkIGEgZmFpbHVyZSB3aGVuIHNlbmRpbmcuXG4gICAgICAvLyBTZWU6IGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTE0MjU2OTdcbiAgICAgIGlmIChicm93c2VyRGV0YWlscy5icm93c2VyID09PSAnZmlyZWZveCdcbiAgICAgICAgICAgJiYgYnJvd3NlckRldGFpbHMudmVyc2lvbiA9PT0gNTcpIHtcbiAgICAgICAgbWF4TWVzc2FnZVNpemUgPSA2NTUzNTtcbiAgICAgIH1cblxuICAgICAgdmFyIG1hdGNoID0gU0RQVXRpbHMubWF0Y2hQcmVmaXgoZGVzY3JpcHRpb24uc2RwLCAnYT1tYXgtbWVzc2FnZS1zaXplOicpO1xuICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDApIHtcbiAgICAgICAgbWF4TWVzc2FnZVNpemUgPSBwYXJzZUludChtYXRjaFswXS5zdWJzdHIoMTkpLCAxMCk7XG4gICAgICB9IGVsc2UgaWYgKGJyb3dzZXJEZXRhaWxzLmJyb3dzZXIgPT09ICdmaXJlZm94JyAmJlxuICAgICAgICAgICAgICAgICAgcmVtb3RlSXNGaXJlZm94ICE9PSAtMSkge1xuICAgICAgICAvLyBJZiB0aGUgbWF4aW11bSBtZXNzYWdlIHNpemUgaXMgbm90IHByZXNlbnQgaW4gdGhlIHJlbW90ZSBTRFAgYW5kXG4gICAgICAgIC8vIGJvdGggbG9jYWwgYW5kIHJlbW90ZSBhcmUgRmlyZWZveCwgdGhlIHJlbW90ZSBwZWVyIGNhbiByZWNlaXZlXG4gICAgICAgIC8vIH4yIEdpQi5cbiAgICAgICAgbWF4TWVzc2FnZVNpemUgPSAyMTQ3NDgzNjM3O1xuICAgICAgfVxuICAgICAgcmV0dXJuIG1heE1lc3NhZ2VTaXplO1xuICAgIH07XG5cbiAgICB2YXIgb3JpZ1NldFJlbW90ZURlc2NyaXB0aW9uID1cbiAgICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5zZXRSZW1vdGVEZXNjcmlwdGlvbjtcbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnNldFJlbW90ZURlc2NyaXB0aW9uID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgcGMgPSB0aGlzO1xuICAgICAgcGMuX3NjdHAgPSBudWxsO1xuXG4gICAgICBpZiAoc2N0cEluRGVzY3JpcHRpb24oYXJndW1lbnRzWzBdKSkge1xuICAgICAgICAvLyBDaGVjayBpZiB0aGUgcmVtb3RlIGlzIEZGLlxuICAgICAgICB2YXIgaXNGaXJlZm94ID0gZ2V0UmVtb3RlRmlyZWZveFZlcnNpb24oYXJndW1lbnRzWzBdKTtcblxuICAgICAgICAvLyBHZXQgdGhlIG1heGltdW0gbWVzc2FnZSBzaXplIHRoZSBsb2NhbCBwZWVyIGlzIGNhcGFibGUgb2Ygc2VuZGluZ1xuICAgICAgICB2YXIgY2FuU2VuZE1NUyA9IGdldENhblNlbmRNYXhNZXNzYWdlU2l6ZShpc0ZpcmVmb3gpO1xuXG4gICAgICAgIC8vIEdldCB0aGUgbWF4aW11bSBtZXNzYWdlIHNpemUgb2YgdGhlIHJlbW90ZSBwZWVyLlxuICAgICAgICB2YXIgcmVtb3RlTU1TID0gZ2V0TWF4TWVzc2FnZVNpemUoYXJndW1lbnRzWzBdLCBpc0ZpcmVmb3gpO1xuXG4gICAgICAgIC8vIERldGVybWluZSBmaW5hbCBtYXhpbXVtIG1lc3NhZ2Ugc2l6ZVxuICAgICAgICB2YXIgbWF4TWVzc2FnZVNpemU7XG4gICAgICAgIGlmIChjYW5TZW5kTU1TID09PSAwICYmIHJlbW90ZU1NUyA9PT0gMCkge1xuICAgICAgICAgIG1heE1lc3NhZ2VTaXplID0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZO1xuICAgICAgICB9IGVsc2UgaWYgKGNhblNlbmRNTVMgPT09IDAgfHwgcmVtb3RlTU1TID09PSAwKSB7XG4gICAgICAgICAgbWF4TWVzc2FnZVNpemUgPSBNYXRoLm1heChjYW5TZW5kTU1TLCByZW1vdGVNTVMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG1heE1lc3NhZ2VTaXplID0gTWF0aC5taW4oY2FuU2VuZE1NUywgcmVtb3RlTU1TKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENyZWF0ZSBhIGR1bW15IFJUQ1NjdHBUcmFuc3BvcnQgb2JqZWN0IGFuZCB0aGUgJ21heE1lc3NhZ2VTaXplJ1xuICAgICAgICAvLyBhdHRyaWJ1dGUuXG4gICAgICAgIHZhciBzY3RwID0ge307XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShzY3RwLCAnbWF4TWVzc2FnZVNpemUnLCB7XG4gICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiBtYXhNZXNzYWdlU2l6ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBwYy5fc2N0cCA9IHNjdHA7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBvcmlnU2V0UmVtb3RlRGVzY3JpcHRpb24uYXBwbHkocGMsIGFyZ3VtZW50cyk7XG4gICAgfTtcbiAgfSxcblxuICBzaGltU2VuZFRocm93VHlwZUVycm9yOiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICAvLyBOb3RlOiBBbHRob3VnaCBGaXJlZm94ID49IDU3IGhhcyBhIG5hdGl2ZSBpbXBsZW1lbnRhdGlvbiwgdGhlIG1heGltdW1cbiAgICAvLyAgICAgICBtZXNzYWdlIHNpemUgY2FuIGJlIHJlc2V0IGZvciBhbGwgZGF0YSBjaGFubmVscyBhdCBhIGxhdGVyIHN0YWdlLlxuICAgIC8vICAgICAgIFNlZTogaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTQyNjgzMVxuXG4gICAgdmFyIG9yaWdDcmVhdGVEYXRhQ2hhbm5lbCA9XG4gICAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmNyZWF0ZURhdGFDaGFubmVsO1xuICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuY3JlYXRlRGF0YUNoYW5uZWwgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBwYyA9IHRoaXM7XG4gICAgICB2YXIgZGF0YUNoYW5uZWwgPSBvcmlnQ3JlYXRlRGF0YUNoYW5uZWwuYXBwbHkocGMsIGFyZ3VtZW50cyk7XG4gICAgICB2YXIgb3JpZ0RhdGFDaGFubmVsU2VuZCA9IGRhdGFDaGFubmVsLnNlbmQ7XG5cbiAgICAgIC8vIFBhdGNoICdzZW5kJyBtZXRob2RcbiAgICAgIGRhdGFDaGFubmVsLnNlbmQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGRjID0gdGhpcztcbiAgICAgICAgdmFyIGRhdGEgPSBhcmd1bWVudHNbMF07XG4gICAgICAgIHZhciBsZW5ndGggPSBkYXRhLmxlbmd0aCB8fCBkYXRhLnNpemUgfHwgZGF0YS5ieXRlTGVuZ3RoO1xuICAgICAgICBpZiAobGVuZ3RoID4gcGMuc2N0cC5tYXhNZXNzYWdlU2l6ZSkge1xuICAgICAgICAgIHRocm93IG5ldyBET01FeGNlcHRpb24oJ01lc3NhZ2UgdG9vIGxhcmdlIChjYW4gc2VuZCBhIG1heGltdW0gb2YgJyArXG4gICAgICAgICAgICBwYy5zY3RwLm1heE1lc3NhZ2VTaXplICsgJyBieXRlcyknLCAnVHlwZUVycm9yJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9yaWdEYXRhQ2hhbm5lbFNlbmQuYXBwbHkoZGMsIGFyZ3VtZW50cyk7XG4gICAgICB9O1xuXG4gICAgICByZXR1cm4gZGF0YUNoYW5uZWw7XG4gICAgfTtcbiAgfVxufTtcbiIsIi8qXG4gKiAgQ29weXJpZ2h0IChjKSAyMDE2IFRoZSBXZWJSVEMgcHJvamVjdCBhdXRob3JzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqICBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhIEJTRC1zdHlsZSBsaWNlbnNlXG4gKiAgdGhhdCBjYW4gYmUgZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBvZiB0aGUgc291cmNlXG4gKiAgdHJlZS5cbiAqL1xuIC8qIGVzbGludC1lbnYgbm9kZSAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbHMgPSByZXF1aXJlKCcuLi91dGlscycpO1xudmFyIHNoaW1SVENQZWVyQ29ubmVjdGlvbiA9IHJlcXVpcmUoJ3J0Y3BlZXJjb25uZWN0aW9uLXNoaW0nKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHNoaW1HZXRVc2VyTWVkaWE6IHJlcXVpcmUoJy4vZ2V0dXNlcm1lZGlhJyksXG4gIHNoaW1QZWVyQ29ubmVjdGlvbjogZnVuY3Rpb24od2luZG93KSB7XG4gICAgdmFyIGJyb3dzZXJEZXRhaWxzID0gdXRpbHMuZGV0ZWN0QnJvd3Nlcih3aW5kb3cpO1xuXG4gICAgaWYgKHdpbmRvdy5SVENJY2VHYXRoZXJlcikge1xuICAgICAgLy8gT1JUQyBkZWZpbmVzIGFuIFJUQ0ljZUNhbmRpZGF0ZSBvYmplY3QgYnV0IG5vIGNvbnN0cnVjdG9yLlxuICAgICAgLy8gTm90IGltcGxlbWVudGVkIGluIEVkZ2UuXG4gICAgICBpZiAoIXdpbmRvdy5SVENJY2VDYW5kaWRhdGUpIHtcbiAgICAgICAgd2luZG93LlJUQ0ljZUNhbmRpZGF0ZSA9IGZ1bmN0aW9uKGFyZ3MpIHtcbiAgICAgICAgICByZXR1cm4gYXJncztcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIC8vIE9SVEMgZG9lcyBub3QgaGF2ZSBhIHNlc3Npb24gZGVzY3JpcHRpb24gb2JqZWN0IGJ1dFxuICAgICAgLy8gb3RoZXIgYnJvd3NlcnMgKGkuZS4gQ2hyb21lKSB0aGF0IHdpbGwgc3VwcG9ydCBib3RoIFBDIGFuZCBPUlRDXG4gICAgICAvLyBpbiB0aGUgZnV0dXJlIG1pZ2h0IGhhdmUgdGhpcyBkZWZpbmVkIGFscmVhZHkuXG4gICAgICBpZiAoIXdpbmRvdy5SVENTZXNzaW9uRGVzY3JpcHRpb24pIHtcbiAgICAgICAgd2luZG93LlJUQ1Nlc3Npb25EZXNjcmlwdGlvbiA9IGZ1bmN0aW9uKGFyZ3MpIHtcbiAgICAgICAgICByZXR1cm4gYXJncztcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIC8vIHRoaXMgYWRkcyBhbiBhZGRpdGlvbmFsIGV2ZW50IGxpc3RlbmVyIHRvIE1lZGlhU3RyYWNrVHJhY2sgdGhhdCBzaWduYWxzXG4gICAgICAvLyB3aGVuIGEgdHJhY2tzIGVuYWJsZWQgcHJvcGVydHkgd2FzIGNoYW5nZWQuIFdvcmthcm91bmQgZm9yIGEgYnVnIGluXG4gICAgICAvLyBhZGRTdHJlYW0sIHNlZSBiZWxvdy4gTm8gbG9uZ2VyIHJlcXVpcmVkIGluIDE1MDI1K1xuICAgICAgaWYgKGJyb3dzZXJEZXRhaWxzLnZlcnNpb24gPCAxNTAyNSkge1xuICAgICAgICB2YXIgb3JpZ01TVEVuYWJsZWQgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKFxuICAgICAgICAgICAgd2luZG93Lk1lZGlhU3RyZWFtVHJhY2sucHJvdG90eXBlLCAnZW5hYmxlZCcpO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkod2luZG93Lk1lZGlhU3RyZWFtVHJhY2sucHJvdG90eXBlLCAnZW5hYmxlZCcsIHtcbiAgICAgICAgICBzZXQ6IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgICAgICBvcmlnTVNURW5hYmxlZC5zZXQuY2FsbCh0aGlzLCB2YWx1ZSk7XG4gICAgICAgICAgICB2YXIgZXYgPSBuZXcgRXZlbnQoJ2VuYWJsZWQnKTtcbiAgICAgICAgICAgIGV2LmVuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChldik7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBPUlRDIGRlZmluZXMgdGhlIERUTUYgc2VuZGVyIGEgYml0IGRpZmZlcmVudC5cbiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vdzNjL29ydGMvaXNzdWVzLzcxNFxuICAgIGlmICh3aW5kb3cuUlRDUnRwU2VuZGVyICYmICEoJ2R0bWYnIGluIHdpbmRvdy5SVENSdHBTZW5kZXIucHJvdG90eXBlKSkge1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHdpbmRvdy5SVENSdHBTZW5kZXIucHJvdG90eXBlLCAnZHRtZicsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICBpZiAodGhpcy5fZHRtZiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBpZiAodGhpcy50cmFjay5raW5kID09PSAnYXVkaW8nKSB7XG4gICAgICAgICAgICAgIHRoaXMuX2R0bWYgPSBuZXcgd2luZG93LlJUQ0R0bWZTZW5kZXIodGhpcyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMudHJhY2sua2luZCA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICB0aGlzLl9kdG1mID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHRoaXMuX2R0bWY7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiA9XG4gICAgICAgIHNoaW1SVENQZWVyQ29ubmVjdGlvbih3aW5kb3csIGJyb3dzZXJEZXRhaWxzLnZlcnNpb24pO1xuICB9LFxuICBzaGltUmVwbGFjZVRyYWNrOiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICAvLyBPUlRDIGhhcyByZXBsYWNlVHJhY2sgLS0gaHR0cHM6Ly9naXRodWIuY29tL3czYy9vcnRjL2lzc3Vlcy82MTRcbiAgICBpZiAod2luZG93LlJUQ1J0cFNlbmRlciAmJlxuICAgICAgICAhKCdyZXBsYWNlVHJhY2snIGluIHdpbmRvdy5SVENSdHBTZW5kZXIucHJvdG90eXBlKSkge1xuICAgICAgd2luZG93LlJUQ1J0cFNlbmRlci5wcm90b3R5cGUucmVwbGFjZVRyYWNrID1cbiAgICAgICAgICB3aW5kb3cuUlRDUnRwU2VuZGVyLnByb3RvdHlwZS5zZXRUcmFjaztcbiAgICB9XG4gIH1cbn07XG4iLCIvKlxuICogIENvcHlyaWdodCAoYykgMjAxNiBUaGUgV2ViUlRDIHByb2plY3QgYXV0aG9ycy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiAgVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYSBCU0Qtc3R5bGUgbGljZW5zZVxuICogIHRoYXQgY2FuIGJlIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3Qgb2YgdGhlIHNvdXJjZVxuICogIHRyZWUuXG4gKi9cbiAvKiBlc2xpbnQtZW52IG5vZGUgKi9cbid1c2Ugc3RyaWN0JztcblxuLy8gRXhwb3NlIHB1YmxpYyBtZXRob2RzLlxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbih3aW5kb3cpIHtcbiAgdmFyIG5hdmlnYXRvciA9IHdpbmRvdyAmJiB3aW5kb3cubmF2aWdhdG9yO1xuXG4gIHZhciBzaGltRXJyb3JfID0gZnVuY3Rpb24oZSkge1xuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiB7UGVybWlzc2lvbkRlbmllZEVycm9yOiAnTm90QWxsb3dlZEVycm9yJ31bZS5uYW1lXSB8fCBlLm5hbWUsXG4gICAgICBtZXNzYWdlOiBlLm1lc3NhZ2UsXG4gICAgICBjb25zdHJhaW50OiBlLmNvbnN0cmFpbnQsXG4gICAgICB0b1N0cmluZzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm5hbWU7XG4gICAgICB9XG4gICAgfTtcbiAgfTtcblxuICAvLyBnZXRVc2VyTWVkaWEgZXJyb3Igc2hpbS5cbiAgdmFyIG9yaWdHZXRVc2VyTWVkaWEgPSBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYS5cbiAgICAgIGJpbmQobmF2aWdhdG9yLm1lZGlhRGV2aWNlcyk7XG4gIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhID0gZnVuY3Rpb24oYykge1xuICAgIHJldHVybiBvcmlnR2V0VXNlck1lZGlhKGMpLmNhdGNoKGZ1bmN0aW9uKGUpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChzaGltRXJyb3JfKGUpKTtcbiAgICB9KTtcbiAgfTtcbn07XG4iLCIvKlxuICogIENvcHlyaWdodCAoYykgMjAxNiBUaGUgV2ViUlRDIHByb2plY3QgYXV0aG9ycy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiAgVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYSBCU0Qtc3R5bGUgbGljZW5zZVxuICogIHRoYXQgY2FuIGJlIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3Qgb2YgdGhlIHNvdXJjZVxuICogIHRyZWUuXG4gKi9cbiAvKiBlc2xpbnQtZW52IG5vZGUgKi9cbid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWxzID0gcmVxdWlyZSgnLi4vdXRpbHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHNoaW1HZXRVc2VyTWVkaWE6IHJlcXVpcmUoJy4vZ2V0dXNlcm1lZGlhJyksXG4gIHNoaW1PblRyYWNrOiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcgJiYgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uICYmICEoJ29udHJhY2snIGluXG4gICAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUpKSB7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkod2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSwgJ29udHJhY2snLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuX29udHJhY2s7XG4gICAgICAgIH0sXG4gICAgICAgIHNldDogZnVuY3Rpb24oZikge1xuICAgICAgICAgIGlmICh0aGlzLl9vbnRyYWNrKSB7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RyYWNrJywgdGhpcy5fb250cmFjayk7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2FkZHN0cmVhbScsIHRoaXMuX29udHJhY2twb2x5KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCd0cmFjaycsIHRoaXMuX29udHJhY2sgPSBmKTtcbiAgICAgICAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ2FkZHN0cmVhbScsIHRoaXMuX29udHJhY2twb2x5ID0gZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgZS5zdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaChmdW5jdGlvbih0cmFjaykge1xuICAgICAgICAgICAgICB2YXIgZXZlbnQgPSBuZXcgRXZlbnQoJ3RyYWNrJyk7XG4gICAgICAgICAgICAgIGV2ZW50LnRyYWNrID0gdHJhY2s7XG4gICAgICAgICAgICAgIGV2ZW50LnJlY2VpdmVyID0ge3RyYWNrOiB0cmFja307XG4gICAgICAgICAgICAgIGV2ZW50LnRyYW5zY2VpdmVyID0ge3JlY2VpdmVyOiBldmVudC5yZWNlaXZlcn07XG4gICAgICAgICAgICAgIGV2ZW50LnN0cmVhbXMgPSBbZS5zdHJlYW1dO1xuICAgICAgICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgICAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgPT09ICdvYmplY3QnICYmIHdpbmRvdy5SVENUcmFja0V2ZW50ICYmXG4gICAgICAgICgncmVjZWl2ZXInIGluIHdpbmRvdy5SVENUcmFja0V2ZW50LnByb3RvdHlwZSkgJiZcbiAgICAgICAgISgndHJhbnNjZWl2ZXInIGluIHdpbmRvdy5SVENUcmFja0V2ZW50LnByb3RvdHlwZSkpIHtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh3aW5kb3cuUlRDVHJhY2tFdmVudC5wcm90b3R5cGUsICd0cmFuc2NlaXZlcicsIHtcbiAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4ge3JlY2VpdmVyOiB0aGlzLnJlY2VpdmVyfTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9LFxuXG4gIHNoaW1Tb3VyY2VPYmplY3Q6IGZ1bmN0aW9uKHdpbmRvdykge1xuICAgIC8vIEZpcmVmb3ggaGFzIHN1cHBvcnRlZCBtb3pTcmNPYmplY3Qgc2luY2UgRkYyMiwgdW5wcmVmaXhlZCBpbiA0Mi5cbiAgICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGlmICh3aW5kb3cuSFRNTE1lZGlhRWxlbWVudCAmJlxuICAgICAgICAhKCdzcmNPYmplY3QnIGluIHdpbmRvdy5IVE1MTWVkaWFFbGVtZW50LnByb3RvdHlwZSkpIHtcbiAgICAgICAgLy8gU2hpbSB0aGUgc3JjT2JqZWN0IHByb3BlcnR5LCBvbmNlLCB3aGVuIEhUTUxNZWRpYUVsZW1lbnQgaXMgZm91bmQuXG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh3aW5kb3cuSFRNTE1lZGlhRWxlbWVudC5wcm90b3R5cGUsICdzcmNPYmplY3QnLCB7XG4gICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1velNyY09iamVjdDtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHNldDogZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICAgICAgICB0aGlzLm1velNyY09iamVjdCA9IHN0cmVhbTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfSxcblxuICBzaGltUGVlckNvbm5lY3Rpb246IGZ1bmN0aW9uKHdpbmRvdykge1xuICAgIHZhciBicm93c2VyRGV0YWlscyA9IHV0aWxzLmRldGVjdEJyb3dzZXIod2luZG93KTtcblxuICAgIGlmICh0eXBlb2Ygd2luZG93ICE9PSAnb2JqZWN0JyB8fCAhKHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiB8fFxuICAgICAgICB3aW5kb3cubW96UlRDUGVlckNvbm5lY3Rpb24pKSB7XG4gICAgICByZXR1cm47IC8vIHByb2JhYmx5IG1lZGlhLnBlZXJjb25uZWN0aW9uLmVuYWJsZWQ9ZmFsc2UgaW4gYWJvdXQ6Y29uZmlnXG4gICAgfVxuICAgIC8vIFRoZSBSVENQZWVyQ29ubmVjdGlvbiBvYmplY3QuXG4gICAgaWYgKCF3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24pIHtcbiAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiA9IGZ1bmN0aW9uKHBjQ29uZmlnLCBwY0NvbnN0cmFpbnRzKSB7XG4gICAgICAgIGlmIChicm93c2VyRGV0YWlscy52ZXJzaW9uIDwgMzgpIHtcbiAgICAgICAgICAvLyAudXJscyBpcyBub3Qgc3VwcG9ydGVkIGluIEZGIDwgMzguXG4gICAgICAgICAgLy8gY3JlYXRlIFJUQ0ljZVNlcnZlcnMgd2l0aCBhIHNpbmdsZSB1cmwuXG4gICAgICAgICAgaWYgKHBjQ29uZmlnICYmIHBjQ29uZmlnLmljZVNlcnZlcnMpIHtcbiAgICAgICAgICAgIHZhciBuZXdJY2VTZXJ2ZXJzID0gW107XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBjQ29uZmlnLmljZVNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgdmFyIHNlcnZlciA9IHBjQ29uZmlnLmljZVNlcnZlcnNbaV07XG4gICAgICAgICAgICAgIGlmIChzZXJ2ZXIuaGFzT3duUHJvcGVydHkoJ3VybHMnKSkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgc2VydmVyLnVybHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgIHZhciBuZXdTZXJ2ZXIgPSB7XG4gICAgICAgICAgICAgICAgICAgIHVybDogc2VydmVyLnVybHNbal1cbiAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICBpZiAoc2VydmVyLnVybHNbal0uaW5kZXhPZigndHVybicpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld1NlcnZlci51c2VybmFtZSA9IHNlcnZlci51c2VybmFtZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3U2VydmVyLmNyZWRlbnRpYWwgPSBzZXJ2ZXIuY3JlZGVudGlhbDtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIG5ld0ljZVNlcnZlcnMucHVzaChuZXdTZXJ2ZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBuZXdJY2VTZXJ2ZXJzLnB1c2gocGNDb25maWcuaWNlU2VydmVyc1tpXSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBjQ29uZmlnLmljZVNlcnZlcnMgPSBuZXdJY2VTZXJ2ZXJzO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IHdpbmRvdy5tb3pSVENQZWVyQ29ubmVjdGlvbihwY0NvbmZpZywgcGNDb25zdHJhaW50cyk7XG4gICAgICB9O1xuICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSA9XG4gICAgICAgICAgd2luZG93Lm1velJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZTtcblxuICAgICAgLy8gd3JhcCBzdGF0aWMgbWV0aG9kcy4gQ3VycmVudGx5IGp1c3QgZ2VuZXJhdGVDZXJ0aWZpY2F0ZS5cbiAgICAgIGlmICh3aW5kb3cubW96UlRDUGVlckNvbm5lY3Rpb24uZ2VuZXJhdGVDZXJ0aWZpY2F0ZSkge1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkod2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLCAnZ2VuZXJhdGVDZXJ0aWZpY2F0ZScsIHtcbiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIHdpbmRvdy5tb3pSVENQZWVyQ29ubmVjdGlvbi5nZW5lcmF0ZUNlcnRpZmljYXRlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHdpbmRvdy5SVENTZXNzaW9uRGVzY3JpcHRpb24gPSB3aW5kb3cubW96UlRDU2Vzc2lvbkRlc2NyaXB0aW9uO1xuICAgICAgd2luZG93LlJUQ0ljZUNhbmRpZGF0ZSA9IHdpbmRvdy5tb3pSVENJY2VDYW5kaWRhdGU7XG4gICAgfVxuXG4gICAgLy8gc2hpbSBhd2F5IG5lZWQgZm9yIG9ic29sZXRlIFJUQ0ljZUNhbmRpZGF0ZS9SVENTZXNzaW9uRGVzY3JpcHRpb24uXG4gICAgWydzZXRMb2NhbERlc2NyaXB0aW9uJywgJ3NldFJlbW90ZURlc2NyaXB0aW9uJywgJ2FkZEljZUNhbmRpZGF0ZSddXG4gICAgICAgIC5mb3JFYWNoKGZ1bmN0aW9uKG1ldGhvZCkge1xuICAgICAgICAgIHZhciBuYXRpdmVNZXRob2QgPSB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlW21ldGhvZF07XG4gICAgICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZVttZXRob2RdID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBhcmd1bWVudHNbMF0gPSBuZXcgKChtZXRob2QgPT09ICdhZGRJY2VDYW5kaWRhdGUnKSA/XG4gICAgICAgICAgICAgICAgd2luZG93LlJUQ0ljZUNhbmRpZGF0ZSA6XG4gICAgICAgICAgICAgICAgd2luZG93LlJUQ1Nlc3Npb25EZXNjcmlwdGlvbikoYXJndW1lbnRzWzBdKTtcbiAgICAgICAgICAgIHJldHVybiBuYXRpdmVNZXRob2QuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICB9O1xuICAgICAgICB9KTtcblxuICAgIC8vIHN1cHBvcnQgZm9yIGFkZEljZUNhbmRpZGF0ZShudWxsIG9yIHVuZGVmaW5lZClcbiAgICB2YXIgbmF0aXZlQWRkSWNlQ2FuZGlkYXRlID1cbiAgICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5hZGRJY2VDYW5kaWRhdGU7XG4gICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5hZGRJY2VDYW5kaWRhdGUgPSBmdW5jdGlvbigpIHtcbiAgICAgIGlmICghYXJndW1lbnRzWzBdKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHNbMV0pIHtcbiAgICAgICAgICBhcmd1bWVudHNbMV0uYXBwbHkobnVsbCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG5hdGl2ZUFkZEljZUNhbmRpZGF0ZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG5cbiAgICAvLyBzaGltIGdldFN0YXRzIHdpdGggbWFwbGlrZSBzdXBwb3J0XG4gICAgdmFyIG1ha2VNYXBTdGF0cyA9IGZ1bmN0aW9uKHN0YXRzKSB7XG4gICAgICB2YXIgbWFwID0gbmV3IE1hcCgpO1xuICAgICAgT2JqZWN0LmtleXMoc3RhdHMpLmZvckVhY2goZnVuY3Rpb24oa2V5KSB7XG4gICAgICAgIG1hcC5zZXQoa2V5LCBzdGF0c1trZXldKTtcbiAgICAgICAgbWFwW2tleV0gPSBzdGF0c1trZXldO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gbWFwO1xuICAgIH07XG5cbiAgICB2YXIgbW9kZXJuU3RhdHNUeXBlcyA9IHtcbiAgICAgIGluYm91bmRydHA6ICdpbmJvdW5kLXJ0cCcsXG4gICAgICBvdXRib3VuZHJ0cDogJ291dGJvdW5kLXJ0cCcsXG4gICAgICBjYW5kaWRhdGVwYWlyOiAnY2FuZGlkYXRlLXBhaXInLFxuICAgICAgbG9jYWxjYW5kaWRhdGU6ICdsb2NhbC1jYW5kaWRhdGUnLFxuICAgICAgcmVtb3RlY2FuZGlkYXRlOiAncmVtb3RlLWNhbmRpZGF0ZSdcbiAgICB9O1xuXG4gICAgdmFyIG5hdGl2ZUdldFN0YXRzID0gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5nZXRTdGF0cztcbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmdldFN0YXRzID0gZnVuY3Rpb24oXG4gICAgICBzZWxlY3RvcixcbiAgICAgIG9uU3VjYyxcbiAgICAgIG9uRXJyXG4gICAgKSB7XG4gICAgICByZXR1cm4gbmF0aXZlR2V0U3RhdHMuYXBwbHkodGhpcywgW3NlbGVjdG9yIHx8IG51bGxdKVxuICAgICAgICAudGhlbihmdW5jdGlvbihzdGF0cykge1xuICAgICAgICAgIGlmIChicm93c2VyRGV0YWlscy52ZXJzaW9uIDwgNDgpIHtcbiAgICAgICAgICAgIHN0YXRzID0gbWFrZU1hcFN0YXRzKHN0YXRzKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGJyb3dzZXJEZXRhaWxzLnZlcnNpb24gPCA1MyAmJiAhb25TdWNjKSB7XG4gICAgICAgICAgICAvLyBTaGltIG9ubHkgcHJvbWlzZSBnZXRTdGF0cyB3aXRoIHNwZWMtaHlwaGVucyBpbiB0eXBlIG5hbWVzXG4gICAgICAgICAgICAvLyBMZWF2ZSBjYWxsYmFjayB2ZXJzaW9uIGFsb25lOyBtaXNjIG9sZCB1c2VzIG9mIGZvckVhY2ggYmVmb3JlIE1hcFxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgc3RhdHMuZm9yRWFjaChmdW5jdGlvbihzdGF0KSB7XG4gICAgICAgICAgICAgICAgc3RhdC50eXBlID0gbW9kZXJuU3RhdHNUeXBlc1tzdGF0LnR5cGVdIHx8IHN0YXQudHlwZTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgIGlmIChlLm5hbWUgIT09ICdUeXBlRXJyb3InKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAvLyBBdm9pZCBUeXBlRXJyb3I6IFwidHlwZVwiIGlzIHJlYWQtb25seSwgaW4gb2xkIHZlcnNpb25zLiAzNC00M2lzaFxuICAgICAgICAgICAgICBzdGF0cy5mb3JFYWNoKGZ1bmN0aW9uKHN0YXQsIGkpIHtcbiAgICAgICAgICAgICAgICBzdGF0cy5zZXQoaSwgT2JqZWN0LmFzc2lnbih7fSwgc3RhdCwge1xuICAgICAgICAgICAgICAgICAgdHlwZTogbW9kZXJuU3RhdHNUeXBlc1tzdGF0LnR5cGVdIHx8IHN0YXQudHlwZVxuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBzdGF0cztcbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4ob25TdWNjLCBvbkVycik7XG4gICAgfTtcbiAgfSxcblxuICBzaGltUmVtb3ZlU3RyZWFtOiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICBpZiAoIXdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiB8fFxuICAgICAgICAncmVtb3ZlU3RyZWFtJyBpbiB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUucmVtb3ZlU3RyZWFtID0gZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICB2YXIgcGMgPSB0aGlzO1xuICAgICAgdXRpbHMuZGVwcmVjYXRlZCgncmVtb3ZlU3RyZWFtJywgJ3JlbW92ZVRyYWNrJyk7XG4gICAgICB0aGlzLmdldFNlbmRlcnMoKS5mb3JFYWNoKGZ1bmN0aW9uKHNlbmRlcikge1xuICAgICAgICBpZiAoc2VuZGVyLnRyYWNrICYmIHN0cmVhbS5nZXRUcmFja3MoKS5pbmRleE9mKHNlbmRlci50cmFjaykgIT09IC0xKSB7XG4gICAgICAgICAgcGMucmVtb3ZlVHJhY2soc2VuZGVyKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfTtcbiAgfVxufTtcbiIsIi8qXG4gKiAgQ29weXJpZ2h0IChjKSAyMDE2IFRoZSBXZWJSVEMgcHJvamVjdCBhdXRob3JzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqICBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhIEJTRC1zdHlsZSBsaWNlbnNlXG4gKiAgdGhhdCBjYW4gYmUgZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBvZiB0aGUgc291cmNlXG4gKiAgdHJlZS5cbiAqL1xuIC8qIGVzbGludC1lbnYgbm9kZSAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbHMgPSByZXF1aXJlKCcuLi91dGlscycpO1xudmFyIGxvZ2dpbmcgPSB1dGlscy5sb2c7XG5cbi8vIEV4cG9zZSBwdWJsaWMgbWV0aG9kcy5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24od2luZG93KSB7XG4gIHZhciBicm93c2VyRGV0YWlscyA9IHV0aWxzLmRldGVjdEJyb3dzZXIod2luZG93KTtcbiAgdmFyIG5hdmlnYXRvciA9IHdpbmRvdyAmJiB3aW5kb3cubmF2aWdhdG9yO1xuICB2YXIgTWVkaWFTdHJlYW1UcmFjayA9IHdpbmRvdyAmJiB3aW5kb3cuTWVkaWFTdHJlYW1UcmFjaztcblxuICB2YXIgc2hpbUVycm9yXyA9IGZ1bmN0aW9uKGUpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbmFtZToge1xuICAgICAgICBJbnRlcm5hbEVycm9yOiAnTm90UmVhZGFibGVFcnJvcicsXG4gICAgICAgIE5vdFN1cHBvcnRlZEVycm9yOiAnVHlwZUVycm9yJyxcbiAgICAgICAgUGVybWlzc2lvbkRlbmllZEVycm9yOiAnTm90QWxsb3dlZEVycm9yJyxcbiAgICAgICAgU2VjdXJpdHlFcnJvcjogJ05vdEFsbG93ZWRFcnJvcidcbiAgICAgIH1bZS5uYW1lXSB8fCBlLm5hbWUsXG4gICAgICBtZXNzYWdlOiB7XG4gICAgICAgICdUaGUgb3BlcmF0aW9uIGlzIGluc2VjdXJlLic6ICdUaGUgcmVxdWVzdCBpcyBub3QgYWxsb3dlZCBieSB0aGUgJyArXG4gICAgICAgICd1c2VyIGFnZW50IG9yIHRoZSBwbGF0Zm9ybSBpbiB0aGUgY3VycmVudCBjb250ZXh0LidcbiAgICAgIH1bZS5tZXNzYWdlXSB8fCBlLm1lc3NhZ2UsXG4gICAgICBjb25zdHJhaW50OiBlLmNvbnN0cmFpbnQsXG4gICAgICB0b1N0cmluZzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm5hbWUgKyAodGhpcy5tZXNzYWdlICYmICc6ICcpICsgdGhpcy5tZXNzYWdlO1xuICAgICAgfVxuICAgIH07XG4gIH07XG5cbiAgLy8gZ2V0VXNlck1lZGlhIGNvbnN0cmFpbnRzIHNoaW0uXG4gIHZhciBnZXRVc2VyTWVkaWFfID0gZnVuY3Rpb24oY29uc3RyYWludHMsIG9uU3VjY2Vzcywgb25FcnJvcikge1xuICAgIHZhciBjb25zdHJhaW50c1RvRkYzN18gPSBmdW5jdGlvbihjKSB7XG4gICAgICBpZiAodHlwZW9mIGMgIT09ICdvYmplY3QnIHx8IGMucmVxdWlyZSkge1xuICAgICAgICByZXR1cm4gYztcbiAgICAgIH1cbiAgICAgIHZhciByZXF1aXJlID0gW107XG4gICAgICBPYmplY3Qua2V5cyhjKS5mb3JFYWNoKGZ1bmN0aW9uKGtleSkge1xuICAgICAgICBpZiAoa2V5ID09PSAncmVxdWlyZScgfHwga2V5ID09PSAnYWR2YW5jZWQnIHx8IGtleSA9PT0gJ21lZGlhU291cmNlJykge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgciA9IGNba2V5XSA9ICh0eXBlb2YgY1trZXldID09PSAnb2JqZWN0JykgP1xuICAgICAgICAgICAgY1trZXldIDoge2lkZWFsOiBjW2tleV19O1xuICAgICAgICBpZiAoci5taW4gIT09IHVuZGVmaW5lZCB8fFxuICAgICAgICAgICAgci5tYXggIT09IHVuZGVmaW5lZCB8fCByLmV4YWN0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICByZXF1aXJlLnB1c2goa2V5KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoci5leGFjdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiByLmV4YWN0ID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgci4gbWluID0gci5tYXggPSByLmV4YWN0O1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjW2tleV0gPSByLmV4YWN0O1xuICAgICAgICAgIH1cbiAgICAgICAgICBkZWxldGUgci5leGFjdDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoci5pZGVhbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgYy5hZHZhbmNlZCA9IGMuYWR2YW5jZWQgfHwgW107XG4gICAgICAgICAgdmFyIG9jID0ge307XG4gICAgICAgICAgaWYgKHR5cGVvZiByLmlkZWFsID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgb2Nba2V5XSA9IHttaW46IHIuaWRlYWwsIG1heDogci5pZGVhbH07XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG9jW2tleV0gPSByLmlkZWFsO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjLmFkdmFuY2VkLnB1c2gob2MpO1xuICAgICAgICAgIGRlbGV0ZSByLmlkZWFsO1xuICAgICAgICAgIGlmICghT2JqZWN0LmtleXMocikubGVuZ3RoKSB7XG4gICAgICAgICAgICBkZWxldGUgY1trZXldO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBpZiAocmVxdWlyZS5sZW5ndGgpIHtcbiAgICAgICAgYy5yZXF1aXJlID0gcmVxdWlyZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBjO1xuICAgIH07XG4gICAgY29uc3RyYWludHMgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGNvbnN0cmFpbnRzKSk7XG4gICAgaWYgKGJyb3dzZXJEZXRhaWxzLnZlcnNpb24gPCAzOCkge1xuICAgICAgbG9nZ2luZygnc3BlYzogJyArIEpTT04uc3RyaW5naWZ5KGNvbnN0cmFpbnRzKSk7XG4gICAgICBpZiAoY29uc3RyYWludHMuYXVkaW8pIHtcbiAgICAgICAgY29uc3RyYWludHMuYXVkaW8gPSBjb25zdHJhaW50c1RvRkYzN18oY29uc3RyYWludHMuYXVkaW8pO1xuICAgICAgfVxuICAgICAgaWYgKGNvbnN0cmFpbnRzLnZpZGVvKSB7XG4gICAgICAgIGNvbnN0cmFpbnRzLnZpZGVvID0gY29uc3RyYWludHNUb0ZGMzdfKGNvbnN0cmFpbnRzLnZpZGVvKTtcbiAgICAgIH1cbiAgICAgIGxvZ2dpbmcoJ2ZmMzc6ICcgKyBKU09OLnN0cmluZ2lmeShjb25zdHJhaW50cykpO1xuICAgIH1cbiAgICByZXR1cm4gbmF2aWdhdG9yLm1vekdldFVzZXJNZWRpYShjb25zdHJhaW50cywgb25TdWNjZXNzLCBmdW5jdGlvbihlKSB7XG4gICAgICBvbkVycm9yKHNoaW1FcnJvcl8oZSkpO1xuICAgIH0pO1xuICB9O1xuXG4gIC8vIFJldHVybnMgdGhlIHJlc3VsdCBvZiBnZXRVc2VyTWVkaWEgYXMgYSBQcm9taXNlLlxuICB2YXIgZ2V0VXNlck1lZGlhUHJvbWlzZV8gPSBmdW5jdGlvbihjb25zdHJhaW50cykge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIGdldFVzZXJNZWRpYV8oY29uc3RyYWludHMsIHJlc29sdmUsIHJlamVjdCk7XG4gICAgfSk7XG4gIH07XG5cbiAgLy8gU2hpbSBmb3IgbWVkaWFEZXZpY2VzIG9uIG9sZGVyIHZlcnNpb25zLlxuICBpZiAoIW5hdmlnYXRvci5tZWRpYURldmljZXMpIHtcbiAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzID0ge2dldFVzZXJNZWRpYTogZ2V0VXNlck1lZGlhUHJvbWlzZV8sXG4gICAgICBhZGRFdmVudExpc3RlbmVyOiBmdW5jdGlvbigpIHsgfSxcbiAgICAgIHJlbW92ZUV2ZW50TGlzdGVuZXI6IGZ1bmN0aW9uKCkgeyB9XG4gICAgfTtcbiAgfVxuICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmVudW1lcmF0ZURldmljZXMgPVxuICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzIHx8IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSkge1xuICAgICAgICAgIHZhciBpbmZvcyA9IFtcbiAgICAgICAgICAgIHtraW5kOiAnYXVkaW9pbnB1dCcsIGRldmljZUlkOiAnZGVmYXVsdCcsIGxhYmVsOiAnJywgZ3JvdXBJZDogJyd9LFxuICAgICAgICAgICAge2tpbmQ6ICd2aWRlb2lucHV0JywgZGV2aWNlSWQ6ICdkZWZhdWx0JywgbGFiZWw6ICcnLCBncm91cElkOiAnJ31cbiAgICAgICAgICBdO1xuICAgICAgICAgIHJlc29sdmUoaW5mb3MpO1xuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgaWYgKGJyb3dzZXJEZXRhaWxzLnZlcnNpb24gPCA0MSkge1xuICAgIC8vIFdvcmsgYXJvdW5kIGh0dHA6Ly9idWd6aWwubGEvMTE2OTY2NVxuICAgIHZhciBvcmdFbnVtZXJhdGVEZXZpY2VzID1cbiAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzLmJpbmQobmF2aWdhdG9yLm1lZGlhRGV2aWNlcyk7XG4gICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gb3JnRW51bWVyYXRlRGV2aWNlcygpLnRoZW4odW5kZWZpbmVkLCBmdW5jdGlvbihlKSB7XG4gICAgICAgIGlmIChlLm5hbWUgPT09ICdOb3RGb3VuZEVycm9yJykge1xuICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlO1xuICAgICAgfSk7XG4gICAgfTtcbiAgfVxuICBpZiAoYnJvd3NlckRldGFpbHMudmVyc2lvbiA8IDQ5KSB7XG4gICAgdmFyIG9yaWdHZXRVc2VyTWVkaWEgPSBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYS5cbiAgICAgICAgYmluZChuYXZpZ2F0b3IubWVkaWFEZXZpY2VzKTtcbiAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSA9IGZ1bmN0aW9uKGMpIHtcbiAgICAgIHJldHVybiBvcmlnR2V0VXNlck1lZGlhKGMpLnRoZW4oZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICAgIC8vIFdvcmsgYXJvdW5kIGh0dHBzOi8vYnVnemlsLmxhLzgwMjMyNlxuICAgICAgICBpZiAoYy5hdWRpbyAmJiAhc3RyZWFtLmdldEF1ZGlvVHJhY2tzKCkubGVuZ3RoIHx8XG4gICAgICAgICAgICBjLnZpZGVvICYmICFzdHJlYW0uZ2V0VmlkZW9UcmFja3MoKS5sZW5ndGgpIHtcbiAgICAgICAgICBzdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaChmdW5jdGlvbih0cmFjaykge1xuICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIHRocm93IG5ldyBET01FeGNlcHRpb24oJ1RoZSBvYmplY3QgY2FuIG5vdCBiZSBmb3VuZCBoZXJlLicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnTm90Rm91bmRFcnJvcicpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdHJlYW07XG4gICAgICB9LCBmdW5jdGlvbihlKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChzaGltRXJyb3JfKGUpKTtcbiAgICAgIH0pO1xuICAgIH07XG4gIH1cbiAgaWYgKCEoYnJvd3NlckRldGFpbHMudmVyc2lvbiA+IDU1ICYmXG4gICAgICAnYXV0b0dhaW5Db250cm9sJyBpbiBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFN1cHBvcnRlZENvbnN0cmFpbnRzKCkpKSB7XG4gICAgdmFyIHJlbWFwID0gZnVuY3Rpb24ob2JqLCBhLCBiKSB7XG4gICAgICBpZiAoYSBpbiBvYmogJiYgIShiIGluIG9iaikpIHtcbiAgICAgICAgb2JqW2JdID0gb2JqW2FdO1xuICAgICAgICBkZWxldGUgb2JqW2FdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB2YXIgbmF0aXZlR2V0VXNlck1lZGlhID0gbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEuXG4gICAgICAgIGJpbmQobmF2aWdhdG9yLm1lZGlhRGV2aWNlcyk7XG4gICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEgPSBmdW5jdGlvbihjKSB7XG4gICAgICBpZiAodHlwZW9mIGMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBjLmF1ZGlvID09PSAnb2JqZWN0Jykge1xuICAgICAgICBjID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShjKSk7XG4gICAgICAgIHJlbWFwKGMuYXVkaW8sICdhdXRvR2FpbkNvbnRyb2wnLCAnbW96QXV0b0dhaW5Db250cm9sJyk7XG4gICAgICAgIHJlbWFwKGMuYXVkaW8sICdub2lzZVN1cHByZXNzaW9uJywgJ21vek5vaXNlU3VwcHJlc3Npb24nKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuYXRpdmVHZXRVc2VyTWVkaWEoYyk7XG4gICAgfTtcblxuICAgIGlmIChNZWRpYVN0cmVhbVRyYWNrICYmIE1lZGlhU3RyZWFtVHJhY2sucHJvdG90eXBlLmdldFNldHRpbmdzKSB7XG4gICAgICB2YXIgbmF0aXZlR2V0U2V0dGluZ3MgPSBNZWRpYVN0cmVhbVRyYWNrLnByb3RvdHlwZS5nZXRTZXR0aW5ncztcbiAgICAgIE1lZGlhU3RyZWFtVHJhY2sucHJvdG90eXBlLmdldFNldHRpbmdzID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBvYmogPSBuYXRpdmVHZXRTZXR0aW5ncy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICByZW1hcChvYmosICdtb3pBdXRvR2FpbkNvbnRyb2wnLCAnYXV0b0dhaW5Db250cm9sJyk7XG4gICAgICAgIHJlbWFwKG9iaiwgJ21vek5vaXNlU3VwcHJlc3Npb24nLCAnbm9pc2VTdXBwcmVzc2lvbicpO1xuICAgICAgICByZXR1cm4gb2JqO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAoTWVkaWFTdHJlYW1UcmFjayAmJiBNZWRpYVN0cmVhbVRyYWNrLnByb3RvdHlwZS5hcHBseUNvbnN0cmFpbnRzKSB7XG4gICAgICB2YXIgbmF0aXZlQXBwbHlDb25zdHJhaW50cyA9IE1lZGlhU3RyZWFtVHJhY2sucHJvdG90eXBlLmFwcGx5Q29uc3RyYWludHM7XG4gICAgICBNZWRpYVN0cmVhbVRyYWNrLnByb3RvdHlwZS5hcHBseUNvbnN0cmFpbnRzID0gZnVuY3Rpb24oYykge1xuICAgICAgICBpZiAodGhpcy5raW5kID09PSAnYXVkaW8nICYmIHR5cGVvZiBjID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgIGMgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGMpKTtcbiAgICAgICAgICByZW1hcChjLCAnYXV0b0dhaW5Db250cm9sJywgJ21vekF1dG9HYWluQ29udHJvbCcpO1xuICAgICAgICAgIHJlbWFwKGMsICdub2lzZVN1cHByZXNzaW9uJywgJ21vek5vaXNlU3VwcHJlc3Npb24nKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmF0aXZlQXBwbHlDb25zdHJhaW50cy5hcHBseSh0aGlzLCBbY10pO1xuICAgICAgfTtcbiAgICB9XG4gIH1cbiAgbmF2aWdhdG9yLmdldFVzZXJNZWRpYSA9IGZ1bmN0aW9uKGNvbnN0cmFpbnRzLCBvblN1Y2Nlc3MsIG9uRXJyb3IpIHtcbiAgICBpZiAoYnJvd3NlckRldGFpbHMudmVyc2lvbiA8IDQ0KSB7XG4gICAgICByZXR1cm4gZ2V0VXNlck1lZGlhXyhjb25zdHJhaW50cywgb25TdWNjZXNzLCBvbkVycm9yKTtcbiAgICB9XG4gICAgLy8gUmVwbGFjZSBGaXJlZm94IDQ0KydzIGRlcHJlY2F0aW9uIHdhcm5pbmcgd2l0aCB1bnByZWZpeGVkIHZlcnNpb24uXG4gICAgdXRpbHMuZGVwcmVjYXRlZCgnbmF2aWdhdG9yLmdldFVzZXJNZWRpYScsXG4gICAgICAgICduYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYScpO1xuICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzKS50aGVuKG9uU3VjY2Vzcywgb25FcnJvcik7XG4gIH07XG59O1xuIiwiLypcbiAqICBDb3B5cmlnaHQgKGMpIDIwMTYgVGhlIFdlYlJUQyBwcm9qZWN0IGF1dGhvcnMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGEgQlNELXN0eWxlIGxpY2Vuc2VcbiAqICB0aGF0IGNhbiBiZSBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGluIHRoZSByb290IG9mIHRoZSBzb3VyY2VcbiAqICB0cmVlLlxuICovXG4ndXNlIHN0cmljdCc7XG52YXIgdXRpbHMgPSByZXF1aXJlKCcuLi91dGlscycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgc2hpbUxvY2FsU3RyZWFtc0FQSTogZnVuY3Rpb24od2luZG93KSB7XG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICdvYmplY3QnIHx8ICF3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKCEoJ2dldExvY2FsU3RyZWFtcycgaW4gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSkpIHtcbiAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuZ2V0TG9jYWxTdHJlYW1zID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICghdGhpcy5fbG9jYWxTdHJlYW1zKSB7XG4gICAgICAgICAgdGhpcy5fbG9jYWxTdHJlYW1zID0gW107XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX2xvY2FsU3RyZWFtcztcbiAgICAgIH07XG4gICAgfVxuICAgIGlmICghKCdnZXRTdHJlYW1CeUlkJyBpbiB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlKSkge1xuICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5nZXRTdHJlYW1CeUlkID0gZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IG51bGw7XG4gICAgICAgIGlmICh0aGlzLl9sb2NhbFN0cmVhbXMpIHtcbiAgICAgICAgICB0aGlzLl9sb2NhbFN0cmVhbXMuZm9yRWFjaChmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgICAgIGlmIChzdHJlYW0uaWQgPT09IGlkKSB7XG4gICAgICAgICAgICAgIHJlc3VsdCA9IHN0cmVhbTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5fcmVtb3RlU3RyZWFtcykge1xuICAgICAgICAgIHRoaXMuX3JlbW90ZVN0cmVhbXMuZm9yRWFjaChmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgICAgIGlmIChzdHJlYW0uaWQgPT09IGlkKSB7XG4gICAgICAgICAgICAgIHJlc3VsdCA9IHN0cmVhbTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfTtcbiAgICB9XG4gICAgaWYgKCEoJ2FkZFN0cmVhbScgaW4gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSkpIHtcbiAgICAgIHZhciBfYWRkVHJhY2sgPSB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmFkZFRyYWNrO1xuICAgICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5hZGRTdHJlYW0gPSBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgaWYgKCF0aGlzLl9sb2NhbFN0cmVhbXMpIHtcbiAgICAgICAgICB0aGlzLl9sb2NhbFN0cmVhbXMgPSBbXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5fbG9jYWxTdHJlYW1zLmluZGV4T2Yoc3RyZWFtKSA9PT0gLTEpIHtcbiAgICAgICAgICB0aGlzLl9sb2NhbFN0cmVhbXMucHVzaChzdHJlYW0pO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwYyA9IHRoaXM7XG4gICAgICAgIHN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKGZ1bmN0aW9uKHRyYWNrKSB7XG4gICAgICAgICAgX2FkZFRyYWNrLmNhbGwocGMsIHRyYWNrLCBzdHJlYW0pO1xuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuYWRkVHJhY2sgPSBmdW5jdGlvbih0cmFjaywgc3RyZWFtKSB7XG4gICAgICAgIGlmIChzdHJlYW0pIHtcbiAgICAgICAgICBpZiAoIXRoaXMuX2xvY2FsU3RyZWFtcykge1xuICAgICAgICAgICAgdGhpcy5fbG9jYWxTdHJlYW1zID0gW3N0cmVhbV07XG4gICAgICAgICAgfSBlbHNlIGlmICh0aGlzLl9sb2NhbFN0cmVhbXMuaW5kZXhPZihzdHJlYW0pID09PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5fbG9jYWxTdHJlYW1zLnB1c2goc3RyZWFtKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIF9hZGRUcmFjay5jYWxsKHRoaXMsIHRyYWNrLCBzdHJlYW0pO1xuICAgICAgfTtcbiAgICB9XG4gICAgaWYgKCEoJ3JlbW92ZVN0cmVhbScgaW4gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSkpIHtcbiAgICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUucmVtb3ZlU3RyZWFtID0gZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICAgIGlmICghdGhpcy5fbG9jYWxTdHJlYW1zKSB7XG4gICAgICAgICAgdGhpcy5fbG9jYWxTdHJlYW1zID0gW107XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGluZGV4ID0gdGhpcy5fbG9jYWxTdHJlYW1zLmluZGV4T2Yoc3RyZWFtKTtcbiAgICAgICAgaWYgKGluZGV4ID09PSAtMSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9sb2NhbFN0cmVhbXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgdmFyIHBjID0gdGhpcztcbiAgICAgICAgdmFyIHRyYWNrcyA9IHN0cmVhbS5nZXRUcmFja3MoKTtcbiAgICAgICAgdGhpcy5nZXRTZW5kZXJzKCkuZm9yRWFjaChmdW5jdGlvbihzZW5kZXIpIHtcbiAgICAgICAgICBpZiAodHJhY2tzLmluZGV4T2Yoc2VuZGVyLnRyYWNrKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHBjLnJlbW92ZVRyYWNrKHNlbmRlcik7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgfVxuICB9LFxuICBzaGltUmVtb3RlU3RyZWFtc0FQSTogZnVuY3Rpb24od2luZG93KSB7XG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICdvYmplY3QnIHx8ICF3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKCEoJ2dldFJlbW90ZVN0cmVhbXMnIGluIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUpKSB7XG4gICAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmdldFJlbW90ZVN0cmVhbXMgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3JlbW90ZVN0cmVhbXMgPyB0aGlzLl9yZW1vdGVTdHJlYW1zIDogW107XG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAoISgnb25hZGRzdHJlYW0nIGluIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUpKSB7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkod2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSwgJ29uYWRkc3RyZWFtJywge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHJldHVybiB0aGlzLl9vbmFkZHN0cmVhbTtcbiAgICAgICAgfSxcbiAgICAgICAgc2V0OiBmdW5jdGlvbihmKSB7XG4gICAgICAgICAgdmFyIHBjID0gdGhpcztcbiAgICAgICAgICBpZiAodGhpcy5fb25hZGRzdHJlYW0pIHtcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcignYWRkc3RyZWFtJywgdGhpcy5fb25hZGRzdHJlYW0pO1xuICAgICAgICAgICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKCd0cmFjaycsIHRoaXMuX29uYWRkc3RyZWFtcG9seSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcignYWRkc3RyZWFtJywgdGhpcy5fb25hZGRzdHJlYW0gPSBmKTtcbiAgICAgICAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ3RyYWNrJywgdGhpcy5fb25hZGRzdHJlYW1wb2x5ID0gZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgZS5zdHJlYW1zLmZvckVhY2goZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICAgICAgICAgIGlmICghcGMuX3JlbW90ZVN0cmVhbXMpIHtcbiAgICAgICAgICAgICAgICBwYy5fcmVtb3RlU3RyZWFtcyA9IFtdO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChwYy5fcmVtb3RlU3RyZWFtcy5pbmRleE9mKHN0cmVhbSkgPj0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBwYy5fcmVtb3RlU3RyZWFtcy5wdXNoKHN0cmVhbSk7XG4gICAgICAgICAgICAgIHZhciBldmVudCA9IG5ldyBFdmVudCgnYWRkc3RyZWFtJyk7XG4gICAgICAgICAgICAgIGV2ZW50LnN0cmVhbSA9IHN0cmVhbTtcbiAgICAgICAgICAgICAgcGMuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9LFxuICBzaGltQ2FsbGJhY2tzQVBJOiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ29iamVjdCcgfHwgIXdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB2YXIgcHJvdG90eXBlID0gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZTtcbiAgICB2YXIgY3JlYXRlT2ZmZXIgPSBwcm90b3R5cGUuY3JlYXRlT2ZmZXI7XG4gICAgdmFyIGNyZWF0ZUFuc3dlciA9IHByb3RvdHlwZS5jcmVhdGVBbnN3ZXI7XG4gICAgdmFyIHNldExvY2FsRGVzY3JpcHRpb24gPSBwcm90b3R5cGUuc2V0TG9jYWxEZXNjcmlwdGlvbjtcbiAgICB2YXIgc2V0UmVtb3RlRGVzY3JpcHRpb24gPSBwcm90b3R5cGUuc2V0UmVtb3RlRGVzY3JpcHRpb247XG4gICAgdmFyIGFkZEljZUNhbmRpZGF0ZSA9IHByb3RvdHlwZS5hZGRJY2VDYW5kaWRhdGU7XG5cbiAgICBwcm90b3R5cGUuY3JlYXRlT2ZmZXIgPSBmdW5jdGlvbihzdWNjZXNzQ2FsbGJhY2ssIGZhaWx1cmVDYWxsYmFjaykge1xuICAgICAgdmFyIG9wdGlvbnMgPSAoYXJndW1lbnRzLmxlbmd0aCA+PSAyKSA/IGFyZ3VtZW50c1syXSA6IGFyZ3VtZW50c1swXTtcbiAgICAgIHZhciBwcm9taXNlID0gY3JlYXRlT2ZmZXIuYXBwbHkodGhpcywgW29wdGlvbnNdKTtcbiAgICAgIGlmICghZmFpbHVyZUNhbGxiYWNrKSB7XG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgICAgfVxuICAgICAgcHJvbWlzZS50aGVuKHN1Y2Nlc3NDYWxsYmFjaywgZmFpbHVyZUNhbGxiYWNrKTtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9O1xuXG4gICAgcHJvdG90eXBlLmNyZWF0ZUFuc3dlciA9IGZ1bmN0aW9uKHN1Y2Nlc3NDYWxsYmFjaywgZmFpbHVyZUNhbGxiYWNrKSB7XG4gICAgICB2YXIgb3B0aW9ucyA9IChhcmd1bWVudHMubGVuZ3RoID49IDIpID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzBdO1xuICAgICAgdmFyIHByb21pc2UgPSBjcmVhdGVBbnN3ZXIuYXBwbHkodGhpcywgW29wdGlvbnNdKTtcbiAgICAgIGlmICghZmFpbHVyZUNhbGxiYWNrKSB7XG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgICAgfVxuICAgICAgcHJvbWlzZS50aGVuKHN1Y2Nlc3NDYWxsYmFjaywgZmFpbHVyZUNhbGxiYWNrKTtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9O1xuXG4gICAgdmFyIHdpdGhDYWxsYmFjayA9IGZ1bmN0aW9uKGRlc2NyaXB0aW9uLCBzdWNjZXNzQ2FsbGJhY2ssIGZhaWx1cmVDYWxsYmFjaykge1xuICAgICAgdmFyIHByb21pc2UgPSBzZXRMb2NhbERlc2NyaXB0aW9uLmFwcGx5KHRoaXMsIFtkZXNjcmlwdGlvbl0pO1xuICAgICAgaWYgKCFmYWlsdXJlQ2FsbGJhY2spIHtcbiAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgICB9XG4gICAgICBwcm9taXNlLnRoZW4oc3VjY2Vzc0NhbGxiYWNrLCBmYWlsdXJlQ2FsbGJhY2spO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH07XG4gICAgcHJvdG90eXBlLnNldExvY2FsRGVzY3JpcHRpb24gPSB3aXRoQ2FsbGJhY2s7XG5cbiAgICB3aXRoQ2FsbGJhY2sgPSBmdW5jdGlvbihkZXNjcmlwdGlvbiwgc3VjY2Vzc0NhbGxiYWNrLCBmYWlsdXJlQ2FsbGJhY2spIHtcbiAgICAgIHZhciBwcm9taXNlID0gc2V0UmVtb3RlRGVzY3JpcHRpb24uYXBwbHkodGhpcywgW2Rlc2NyaXB0aW9uXSk7XG4gICAgICBpZiAoIWZhaWx1cmVDYWxsYmFjaykge1xuICAgICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICAgIH1cbiAgICAgIHByb21pc2UudGhlbihzdWNjZXNzQ2FsbGJhY2ssIGZhaWx1cmVDYWxsYmFjayk7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfTtcbiAgICBwcm90b3R5cGUuc2V0UmVtb3RlRGVzY3JpcHRpb24gPSB3aXRoQ2FsbGJhY2s7XG5cbiAgICB3aXRoQ2FsbGJhY2sgPSBmdW5jdGlvbihjYW5kaWRhdGUsIHN1Y2Nlc3NDYWxsYmFjaywgZmFpbHVyZUNhbGxiYWNrKSB7XG4gICAgICB2YXIgcHJvbWlzZSA9IGFkZEljZUNhbmRpZGF0ZS5hcHBseSh0aGlzLCBbY2FuZGlkYXRlXSk7XG4gICAgICBpZiAoIWZhaWx1cmVDYWxsYmFjaykge1xuICAgICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICAgIH1cbiAgICAgIHByb21pc2UudGhlbihzdWNjZXNzQ2FsbGJhY2ssIGZhaWx1cmVDYWxsYmFjayk7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfTtcbiAgICBwcm90b3R5cGUuYWRkSWNlQ2FuZGlkYXRlID0gd2l0aENhbGxiYWNrO1xuICB9LFxuICBzaGltR2V0VXNlck1lZGlhOiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICB2YXIgbmF2aWdhdG9yID0gd2luZG93ICYmIHdpbmRvdy5uYXZpZ2F0b3I7XG5cbiAgICBpZiAoIW5hdmlnYXRvci5nZXRVc2VyTWVkaWEpIHtcbiAgICAgIGlmIChuYXZpZ2F0b3Iud2Via2l0R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIG5hdmlnYXRvci5nZXRVc2VyTWVkaWEgPSBuYXZpZ2F0b3Iud2Via2l0R2V0VXNlck1lZGlhLmJpbmQobmF2aWdhdG9yKTtcbiAgICAgIH0gZWxzZSBpZiAobmF2aWdhdG9yLm1lZGlhRGV2aWNlcyAmJlxuICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKSB7XG4gICAgICAgIG5hdmlnYXRvci5nZXRVc2VyTWVkaWEgPSBmdW5jdGlvbihjb25zdHJhaW50cywgY2IsIGVycmNiKSB7XG4gICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoY29uc3RyYWludHMpXG4gICAgICAgICAgLnRoZW4oY2IsIGVycmNiKTtcbiAgICAgICAgfS5iaW5kKG5hdmlnYXRvcik7XG4gICAgICB9XG4gICAgfVxuICB9LFxuICBzaGltUlRDSWNlU2VydmVyVXJsczogZnVuY3Rpb24od2luZG93KSB7XG4gICAgLy8gbWlncmF0ZSBmcm9tIG5vbi1zcGVjIFJUQ0ljZVNlcnZlci51cmwgdG8gUlRDSWNlU2VydmVyLnVybHNcbiAgICB2YXIgT3JpZ1BlZXJDb25uZWN0aW9uID0gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uO1xuICAgIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiA9IGZ1bmN0aW9uKHBjQ29uZmlnLCBwY0NvbnN0cmFpbnRzKSB7XG4gICAgICBpZiAocGNDb25maWcgJiYgcGNDb25maWcuaWNlU2VydmVycykge1xuICAgICAgICB2YXIgbmV3SWNlU2VydmVycyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBjQ29uZmlnLmljZVNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICB2YXIgc2VydmVyID0gcGNDb25maWcuaWNlU2VydmVyc1tpXTtcbiAgICAgICAgICBpZiAoIXNlcnZlci5oYXNPd25Qcm9wZXJ0eSgndXJscycpICYmXG4gICAgICAgICAgICAgIHNlcnZlci5oYXNPd25Qcm9wZXJ0eSgndXJsJykpIHtcbiAgICAgICAgICAgIHV0aWxzLmRlcHJlY2F0ZWQoJ1JUQ0ljZVNlcnZlci51cmwnLCAnUlRDSWNlU2VydmVyLnVybHMnKTtcbiAgICAgICAgICAgIHNlcnZlciA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoc2VydmVyKSk7XG4gICAgICAgICAgICBzZXJ2ZXIudXJscyA9IHNlcnZlci51cmw7XG4gICAgICAgICAgICBkZWxldGUgc2VydmVyLnVybDtcbiAgICAgICAgICAgIG5ld0ljZVNlcnZlcnMucHVzaChzZXJ2ZXIpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBuZXdJY2VTZXJ2ZXJzLnB1c2gocGNDb25maWcuaWNlU2VydmVyc1tpXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHBjQ29uZmlnLmljZVNlcnZlcnMgPSBuZXdJY2VTZXJ2ZXJzO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG5ldyBPcmlnUGVlckNvbm5lY3Rpb24ocGNDb25maWcsIHBjQ29uc3RyYWludHMpO1xuICAgIH07XG4gICAgd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSA9IE9yaWdQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGU7XG4gICAgLy8gd3JhcCBzdGF0aWMgbWV0aG9kcy4gQ3VycmVudGx5IGp1c3QgZ2VuZXJhdGVDZXJ0aWZpY2F0ZS5cbiAgICBpZiAoJ2dlbmVyYXRlQ2VydGlmaWNhdGUnIGluIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbikge1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiwgJ2dlbmVyYXRlQ2VydGlmaWNhdGUnLCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIE9yaWdQZWVyQ29ubmVjdGlvbi5nZW5lcmF0ZUNlcnRpZmljYXRlO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH0sXG4gIHNoaW1UcmFja0V2ZW50VHJhbnNjZWl2ZXI6IGZ1bmN0aW9uKHdpbmRvdykge1xuICAgIC8vIEFkZCBldmVudC50cmFuc2NlaXZlciBtZW1iZXIgb3ZlciBkZXByZWNhdGVkIGV2ZW50LnJlY2VpdmVyXG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgPT09ICdvYmplY3QnICYmIHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiAmJlxuICAgICAgICAoJ3JlY2VpdmVyJyBpbiB3aW5kb3cuUlRDVHJhY2tFdmVudC5wcm90b3R5cGUpICYmXG4gICAgICAgIC8vIGNhbid0IGNoZWNrICd0cmFuc2NlaXZlcicgaW4gd2luZG93LlJUQ1RyYWNrRXZlbnQucHJvdG90eXBlLCBhcyBpdCBpc1xuICAgICAgICAvLyBkZWZpbmVkIGZvciBzb21lIHJlYXNvbiBldmVuIHdoZW4gd2luZG93LlJUQ1RyYW5zY2VpdmVyIGlzIG5vdC5cbiAgICAgICAgIXdpbmRvdy5SVENUcmFuc2NlaXZlcikge1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHdpbmRvdy5SVENUcmFja0V2ZW50LnByb3RvdHlwZSwgJ3RyYW5zY2VpdmVyJywge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHJldHVybiB7cmVjZWl2ZXI6IHRoaXMucmVjZWl2ZXJ9O1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH0sXG5cbiAgc2hpbUNyZWF0ZU9mZmVyTGVnYWN5OiBmdW5jdGlvbih3aW5kb3cpIHtcbiAgICB2YXIgb3JpZ0NyZWF0ZU9mZmVyID0gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5jcmVhdGVPZmZlcjtcbiAgICB3aW5kb3cuUlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmNyZWF0ZU9mZmVyID0gZnVuY3Rpb24ob2ZmZXJPcHRpb25zKSB7XG4gICAgICB2YXIgcGMgPSB0aGlzO1xuICAgICAgaWYgKG9mZmVyT3B0aW9ucykge1xuICAgICAgICB2YXIgYXVkaW9UcmFuc2NlaXZlciA9IHBjLmdldFRyYW5zY2VpdmVycygpLmZpbmQoZnVuY3Rpb24odHJhbnNjZWl2ZXIpIHtcbiAgICAgICAgICByZXR1cm4gdHJhbnNjZWl2ZXIuc2VuZGVyLnRyYWNrICYmXG4gICAgICAgICAgICAgIHRyYW5zY2VpdmVyLnNlbmRlci50cmFjay5raW5kID09PSAnYXVkaW8nO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKG9mZmVyT3B0aW9ucy5vZmZlclRvUmVjZWl2ZUF1ZGlvID09PSBmYWxzZSAmJiBhdWRpb1RyYW5zY2VpdmVyKSB7XG4gICAgICAgICAgaWYgKGF1ZGlvVHJhbnNjZWl2ZXIuZGlyZWN0aW9uID09PSAnc2VuZHJlY3YnKSB7XG4gICAgICAgICAgICBpZiAoYXVkaW9UcmFuc2NlaXZlci5zZXREaXJlY3Rpb24pIHtcbiAgICAgICAgICAgICAgYXVkaW9UcmFuc2NlaXZlci5zZXREaXJlY3Rpb24oJ3NlbmRvbmx5Jyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBhdWRpb1RyYW5zY2VpdmVyLmRpcmVjdGlvbiA9ICdzZW5kb25seSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIGlmIChhdWRpb1RyYW5zY2VpdmVyLmRpcmVjdGlvbiA9PT0gJ3JlY3Zvbmx5Jykge1xuICAgICAgICAgICAgaWYgKGF1ZGlvVHJhbnNjZWl2ZXIuc2V0RGlyZWN0aW9uKSB7XG4gICAgICAgICAgICAgIGF1ZGlvVHJhbnNjZWl2ZXIuc2V0RGlyZWN0aW9uKCdpbmFjdGl2ZScpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgYXVkaW9UcmFuc2NlaXZlci5kaXJlY3Rpb24gPSAnaW5hY3RpdmUnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChvZmZlck9wdGlvbnMub2ZmZXJUb1JlY2VpdmVBdWRpbyA9PT0gdHJ1ZSAmJlxuICAgICAgICAgICAgIWF1ZGlvVHJhbnNjZWl2ZXIpIHtcbiAgICAgICAgICBwYy5hZGRUcmFuc2NlaXZlcignYXVkaW8nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB2aWRlb1RyYW5zY2VpdmVyID0gcGMuZ2V0VHJhbnNjZWl2ZXJzKCkuZmluZChmdW5jdGlvbih0cmFuc2NlaXZlcikge1xuICAgICAgICAgIHJldHVybiB0cmFuc2NlaXZlci5zZW5kZXIudHJhY2sgJiZcbiAgICAgICAgICAgICAgdHJhbnNjZWl2ZXIuc2VuZGVyLnRyYWNrLmtpbmQgPT09ICd2aWRlbyc7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAob2ZmZXJPcHRpb25zLm9mZmVyVG9SZWNlaXZlVmlkZW8gPT09IGZhbHNlICYmIHZpZGVvVHJhbnNjZWl2ZXIpIHtcbiAgICAgICAgICBpZiAodmlkZW9UcmFuc2NlaXZlci5kaXJlY3Rpb24gPT09ICdzZW5kcmVjdicpIHtcbiAgICAgICAgICAgIHZpZGVvVHJhbnNjZWl2ZXIuc2V0RGlyZWN0aW9uKCdzZW5kb25seScpO1xuICAgICAgICAgIH0gZWxzZSBpZiAodmlkZW9UcmFuc2NlaXZlci5kaXJlY3Rpb24gPT09ICdyZWN2b25seScpIHtcbiAgICAgICAgICAgIHZpZGVvVHJhbnNjZWl2ZXIuc2V0RGlyZWN0aW9uKCdpbmFjdGl2ZScpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChvZmZlck9wdGlvbnMub2ZmZXJUb1JlY2VpdmVWaWRlbyA9PT0gdHJ1ZSAmJlxuICAgICAgICAgICAgIXZpZGVvVHJhbnNjZWl2ZXIpIHtcbiAgICAgICAgICBwYy5hZGRUcmFuc2NlaXZlcigndmlkZW8nKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIG9yaWdDcmVhdGVPZmZlci5hcHBseShwYywgYXJndW1lbnRzKTtcbiAgICB9O1xuICB9XG59O1xuIiwiLypcbiAqICBDb3B5cmlnaHQgKGMpIDIwMTYgVGhlIFdlYlJUQyBwcm9qZWN0IGF1dGhvcnMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGEgQlNELXN0eWxlIGxpY2Vuc2VcbiAqICB0aGF0IGNhbiBiZSBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGluIHRoZSByb290IG9mIHRoZSBzb3VyY2VcbiAqICB0cmVlLlxuICovXG4gLyogZXNsaW50LWVudiBub2RlICovXG4ndXNlIHN0cmljdCc7XG5cbnZhciBsb2dEaXNhYmxlZF8gPSB0cnVlO1xudmFyIGRlcHJlY2F0aW9uV2FybmluZ3NfID0gdHJ1ZTtcblxuLyoqXG4gKiBFeHRyYWN0IGJyb3dzZXIgdmVyc2lvbiBvdXQgb2YgdGhlIHByb3ZpZGVkIHVzZXIgYWdlbnQgc3RyaW5nLlxuICpcbiAqIEBwYXJhbSB7IXN0cmluZ30gdWFzdHJpbmcgdXNlckFnZW50IHN0cmluZy5cbiAqIEBwYXJhbSB7IXN0cmluZ30gZXhwciBSZWd1bGFyIGV4cHJlc3Npb24gdXNlZCBhcyBtYXRjaCBjcml0ZXJpYS5cbiAqIEBwYXJhbSB7IW51bWJlcn0gcG9zIHBvc2l0aW9uIGluIHRoZSB2ZXJzaW9uIHN0cmluZyB0byBiZSByZXR1cm5lZC5cbiAqIEByZXR1cm4geyFudW1iZXJ9IGJyb3dzZXIgdmVyc2lvbi5cbiAqL1xuZnVuY3Rpb24gZXh0cmFjdFZlcnNpb24odWFzdHJpbmcsIGV4cHIsIHBvcykge1xuICB2YXIgbWF0Y2ggPSB1YXN0cmluZy5tYXRjaChleHByKTtcbiAgcmV0dXJuIG1hdGNoICYmIG1hdGNoLmxlbmd0aCA+PSBwb3MgJiYgcGFyc2VJbnQobWF0Y2hbcG9zXSwgMTApO1xufVxuXG4vLyBXcmFwcyB0aGUgcGVlcmNvbm5lY3Rpb24gZXZlbnQgZXZlbnROYW1lVG9XcmFwIGluIGEgZnVuY3Rpb25cbi8vIHdoaWNoIHJldHVybnMgdGhlIG1vZGlmaWVkIGV2ZW50IG9iamVjdC5cbmZ1bmN0aW9uIHdyYXBQZWVyQ29ubmVjdGlvbkV2ZW50KHdpbmRvdywgZXZlbnROYW1lVG9XcmFwLCB3cmFwcGVyKSB7XG4gIGlmICghd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHZhciBwcm90byA9IHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGU7XG4gIHZhciBuYXRpdmVBZGRFdmVudExpc3RlbmVyID0gcHJvdG8uYWRkRXZlbnRMaXN0ZW5lcjtcbiAgcHJvdG8uYWRkRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uKG5hdGl2ZUV2ZW50TmFtZSwgY2IpIHtcbiAgICBpZiAobmF0aXZlRXZlbnROYW1lICE9PSBldmVudE5hbWVUb1dyYXApIHtcbiAgICAgIHJldHVybiBuYXRpdmVBZGRFdmVudExpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICAgIHZhciB3cmFwcGVkQ2FsbGJhY2sgPSBmdW5jdGlvbihlKSB7XG4gICAgICBjYih3cmFwcGVyKGUpKTtcbiAgICB9O1xuICAgIHRoaXMuX2V2ZW50TWFwID0gdGhpcy5fZXZlbnRNYXAgfHwge307XG4gICAgdGhpcy5fZXZlbnRNYXBbY2JdID0gd3JhcHBlZENhbGxiYWNrO1xuICAgIHJldHVybiBuYXRpdmVBZGRFdmVudExpc3RlbmVyLmFwcGx5KHRoaXMsIFtuYXRpdmVFdmVudE5hbWUsXG4gICAgICB3cmFwcGVkQ2FsbGJhY2tdKTtcbiAgfTtcblxuICB2YXIgbmF0aXZlUmVtb3ZlRXZlbnRMaXN0ZW5lciA9IHByb3RvLnJlbW92ZUV2ZW50TGlzdGVuZXI7XG4gIHByb3RvLnJlbW92ZUV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbihuYXRpdmVFdmVudE5hbWUsIGNiKSB7XG4gICAgaWYgKG5hdGl2ZUV2ZW50TmFtZSAhPT0gZXZlbnROYW1lVG9XcmFwIHx8ICF0aGlzLl9ldmVudE1hcFxuICAgICAgICB8fCAhdGhpcy5fZXZlbnRNYXBbY2JdKSB7XG4gICAgICByZXR1cm4gbmF0aXZlUmVtb3ZlRXZlbnRMaXN0ZW5lci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgICB2YXIgdW53cmFwcGVkQ2IgPSB0aGlzLl9ldmVudE1hcFtjYl07XG4gICAgZGVsZXRlIHRoaXMuX2V2ZW50TWFwW2NiXTtcbiAgICByZXR1cm4gbmF0aXZlUmVtb3ZlRXZlbnRMaXN0ZW5lci5hcHBseSh0aGlzLCBbbmF0aXZlRXZlbnROYW1lLFxuICAgICAgdW53cmFwcGVkQ2JdKTtcbiAgfTtcblxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkocHJvdG8sICdvbicgKyBldmVudE5hbWVUb1dyYXAsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXNbJ19vbicgKyBldmVudE5hbWVUb1dyYXBdO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbihjYikge1xuICAgICAgaWYgKHRoaXNbJ19vbicgKyBldmVudE5hbWVUb1dyYXBdKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE5hbWVUb1dyYXAsXG4gICAgICAgICAgICB0aGlzWydfb24nICsgZXZlbnROYW1lVG9XcmFwXSk7XG4gICAgICAgIGRlbGV0ZSB0aGlzWydfb24nICsgZXZlbnROYW1lVG9XcmFwXTtcbiAgICAgIH1cbiAgICAgIGlmIChjYikge1xuICAgICAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoZXZlbnROYW1lVG9XcmFwLFxuICAgICAgICAgICAgdGhpc1snX29uJyArIGV2ZW50TmFtZVRvV3JhcF0gPSBjYik7XG4gICAgICB9XG4gICAgfVxuICB9KTtcbn1cblxuLy8gVXRpbGl0eSBtZXRob2RzLlxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGV4dHJhY3RWZXJzaW9uOiBleHRyYWN0VmVyc2lvbixcbiAgd3JhcFBlZXJDb25uZWN0aW9uRXZlbnQ6IHdyYXBQZWVyQ29ubmVjdGlvbkV2ZW50LFxuICBkaXNhYmxlTG9nOiBmdW5jdGlvbihib29sKSB7XG4gICAgaWYgKHR5cGVvZiBib29sICE9PSAnYm9vbGVhbicpIHtcbiAgICAgIHJldHVybiBuZXcgRXJyb3IoJ0FyZ3VtZW50IHR5cGU6ICcgKyB0eXBlb2YgYm9vbCArXG4gICAgICAgICAgJy4gUGxlYXNlIHVzZSBhIGJvb2xlYW4uJyk7XG4gICAgfVxuICAgIGxvZ0Rpc2FibGVkXyA9IGJvb2w7XG4gICAgcmV0dXJuIChib29sKSA/ICdhZGFwdGVyLmpzIGxvZ2dpbmcgZGlzYWJsZWQnIDpcbiAgICAgICAgJ2FkYXB0ZXIuanMgbG9nZ2luZyBlbmFibGVkJztcbiAgfSxcblxuICAvKipcbiAgICogRGlzYWJsZSBvciBlbmFibGUgZGVwcmVjYXRpb24gd2FybmluZ3NcbiAgICogQHBhcmFtIHshYm9vbGVhbn0gYm9vbCBzZXQgdG8gdHJ1ZSB0byBkaXNhYmxlIHdhcm5pbmdzLlxuICAgKi9cbiAgZGlzYWJsZVdhcm5pbmdzOiBmdW5jdGlvbihib29sKSB7XG4gICAgaWYgKHR5cGVvZiBib29sICE9PSAnYm9vbGVhbicpIHtcbiAgICAgIHJldHVybiBuZXcgRXJyb3IoJ0FyZ3VtZW50IHR5cGU6ICcgKyB0eXBlb2YgYm9vbCArXG4gICAgICAgICAgJy4gUGxlYXNlIHVzZSBhIGJvb2xlYW4uJyk7XG4gICAgfVxuICAgIGRlcHJlY2F0aW9uV2FybmluZ3NfID0gIWJvb2w7XG4gICAgcmV0dXJuICdhZGFwdGVyLmpzIGRlcHJlY2F0aW9uIHdhcm5pbmdzICcgKyAoYm9vbCA/ICdkaXNhYmxlZCcgOiAnZW5hYmxlZCcpO1xuICB9LFxuXG4gIGxvZzogZnVuY3Rpb24oKSB7XG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgPT09ICdvYmplY3QnKSB7XG4gICAgICBpZiAobG9nRGlzYWJsZWRfKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgY29uc29sZSAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGNvbnNvbGUubG9nID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGNvbnNvbGUubG9nLmFwcGx5KGNvbnNvbGUsIGFyZ3VtZW50cyk7XG4gICAgICB9XG4gICAgfVxuICB9LFxuXG4gIC8qKlxuICAgKiBTaG93cyBhIGRlcHJlY2F0aW9uIHdhcm5pbmcgc3VnZ2VzdGluZyB0aGUgbW9kZXJuIGFuZCBzcGVjLWNvbXBhdGlibGUgQVBJLlxuICAgKi9cbiAgZGVwcmVjYXRlZDogZnVuY3Rpb24ob2xkTWV0aG9kLCBuZXdNZXRob2QpIHtcbiAgICBpZiAoIWRlcHJlY2F0aW9uV2FybmluZ3NfKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnNvbGUud2FybihvbGRNZXRob2QgKyAnIGlzIGRlcHJlY2F0ZWQsIHBsZWFzZSB1c2UgJyArIG5ld01ldGhvZCArXG4gICAgICAgICcgaW5zdGVhZC4nKTtcbiAgfSxcblxuICAvKipcbiAgICogQnJvd3NlciBkZXRlY3Rvci5cbiAgICpcbiAgICogQHJldHVybiB7b2JqZWN0fSByZXN1bHQgY29udGFpbmluZyBicm93c2VyIGFuZCB2ZXJzaW9uXG4gICAqICAgICBwcm9wZXJ0aWVzLlxuICAgKi9cbiAgZGV0ZWN0QnJvd3NlcjogZnVuY3Rpb24od2luZG93KSB7XG4gICAgdmFyIG5hdmlnYXRvciA9IHdpbmRvdyAmJiB3aW5kb3cubmF2aWdhdG9yO1xuXG4gICAgLy8gUmV0dXJuZWQgcmVzdWx0IG9iamVjdC5cbiAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgcmVzdWx0LmJyb3dzZXIgPSBudWxsO1xuICAgIHJlc3VsdC52ZXJzaW9uID0gbnVsbDtcblxuICAgIC8vIEZhaWwgZWFybHkgaWYgaXQncyBub3QgYSBicm93c2VyXG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnIHx8ICF3aW5kb3cubmF2aWdhdG9yKSB7XG4gICAgICByZXN1bHQuYnJvd3NlciA9ICdOb3QgYSBicm93c2VyLic7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGlmIChuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7IC8vIEZpcmVmb3guXG4gICAgICByZXN1bHQuYnJvd3NlciA9ICdmaXJlZm94JztcbiAgICAgIHJlc3VsdC52ZXJzaW9uID0gZXh0cmFjdFZlcnNpb24obmF2aWdhdG9yLnVzZXJBZ2VudCxcbiAgICAgICAgICAvRmlyZWZveFxcLyhcXGQrKVxcLi8sIDEpO1xuICAgIH0gZWxzZSBpZiAobmF2aWdhdG9yLndlYmtpdEdldFVzZXJNZWRpYSkge1xuICAgICAgLy8gQ2hyb21lLCBDaHJvbWl1bSwgV2VidmlldywgT3BlcmEuXG4gICAgICAvLyBWZXJzaW9uIG1hdGNoZXMgQ2hyb21lL1dlYlJUQyB2ZXJzaW9uLlxuICAgICAgcmVzdWx0LmJyb3dzZXIgPSAnY2hyb21lJztcbiAgICAgIHJlc3VsdC52ZXJzaW9uID0gZXh0cmFjdFZlcnNpb24obmF2aWdhdG9yLnVzZXJBZ2VudCxcbiAgICAgICAgICAvQ2hyb20oZXxpdW0pXFwvKFxcZCspXFwuLywgMik7XG4gICAgfSBlbHNlIGlmIChuYXZpZ2F0b3IubWVkaWFEZXZpY2VzICYmXG4gICAgICAgIG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goL0VkZ2VcXC8oXFxkKykuKFxcZCspJC8pKSB7IC8vIEVkZ2UuXG4gICAgICByZXN1bHQuYnJvd3NlciA9ICdlZGdlJztcbiAgICAgIHJlc3VsdC52ZXJzaW9uID0gZXh0cmFjdFZlcnNpb24obmF2aWdhdG9yLnVzZXJBZ2VudCxcbiAgICAgICAgICAvRWRnZVxcLyhcXGQrKS4oXFxkKykkLywgMik7XG4gICAgfSBlbHNlIGlmIChuYXZpZ2F0b3IubWVkaWFEZXZpY2VzICYmXG4gICAgICAgIG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goL0FwcGxlV2ViS2l0XFwvKFxcZCspXFwuLykpIHsgLy8gU2FmYXJpLlxuICAgICAgcmVzdWx0LmJyb3dzZXIgPSAnc2FmYXJpJztcbiAgICAgIHJlc3VsdC52ZXJzaW9uID0gZXh0cmFjdFZlcnNpb24obmF2aWdhdG9yLnVzZXJBZ2VudCxcbiAgICAgICAgICAvQXBwbGVXZWJLaXRcXC8oXFxkKylcXC4vLCAxKTtcbiAgICB9IGVsc2UgeyAvLyBEZWZhdWx0IGZhbGx0aHJvdWdoOiBub3Qgc3VwcG9ydGVkLlxuICAgICAgcmVzdWx0LmJyb3dzZXIgPSAnTm90IGEgc3VwcG9ydGVkIGJyb3dzZXIuJztcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufTtcbiIsIi8qXHJcbldpbGRFbWl0dGVyLmpzIGlzIGEgc2xpbSBsaXR0bGUgZXZlbnQgZW1pdHRlciBieSBAaGVucmlram9yZXRlZyBsYXJnZWx5IGJhc2VkXHJcbm9uIEB2aXNpb25tZWRpYSdzIEVtaXR0ZXIgZnJvbSBVSSBLaXQuXHJcblxyXG5XaHk/IEkgd2FudGVkIGl0IHN0YW5kYWxvbmUuXHJcblxyXG5JIGFsc28gd2FudGVkIHN1cHBvcnQgZm9yIHdpbGRjYXJkIGVtaXR0ZXJzIGxpa2UgdGhpczpcclxuXHJcbmVtaXR0ZXIub24oJyonLCBmdW5jdGlvbiAoZXZlbnROYW1lLCBvdGhlciwgZXZlbnQsIHBheWxvYWRzKSB7XHJcblxyXG59KTtcclxuXHJcbmVtaXR0ZXIub24oJ3NvbWVuYW1lc3BhY2UqJywgZnVuY3Rpb24gKGV2ZW50TmFtZSwgcGF5bG9hZHMpIHtcclxuXHJcbn0pO1xyXG5cclxuUGxlYXNlIG5vdGUgdGhhdCBjYWxsYmFja3MgdHJpZ2dlcmVkIGJ5IHdpbGRjYXJkIHJlZ2lzdGVyZWQgZXZlbnRzIGFsc28gZ2V0XHJcbnRoZSBldmVudCBuYW1lIGFzIHRoZSBmaXJzdCBhcmd1bWVudC5cclxuKi9cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gV2lsZEVtaXR0ZXI7XHJcblxyXG5mdW5jdGlvbiBXaWxkRW1pdHRlcigpIHsgfVxyXG5cclxuV2lsZEVtaXR0ZXIubWl4aW4gPSBmdW5jdGlvbiAoY29uc3RydWN0b3IpIHtcclxuICAgIHZhciBwcm90b3R5cGUgPSBjb25zdHJ1Y3Rvci5wcm90b3R5cGUgfHwgY29uc3RydWN0b3I7XHJcblxyXG4gICAgcHJvdG90eXBlLmlzV2lsZEVtaXR0ZXI9IHRydWU7XHJcblxyXG4gICAgLy8gTGlzdGVuIG9uIHRoZSBnaXZlbiBgZXZlbnRgIHdpdGggYGZuYC4gU3RvcmUgYSBncm91cCBuYW1lIGlmIHByZXNlbnQuXHJcbiAgICBwcm90b3R5cGUub24gPSBmdW5jdGlvbiAoZXZlbnQsIGdyb3VwTmFtZSwgZm4pIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcclxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xyXG4gICAgICAgIGZ1bmMuX2dyb3VwTmFtZSA9IGdyb3VwO1xyXG4gICAgICAgICh0aGlzLmNhbGxiYWNrc1tldmVudF0gPSB0aGlzLmNhbGxiYWNrc1tldmVudF0gfHwgW10pLnB1c2goZnVuYyk7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIEFkZHMgYW4gYGV2ZW50YCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBhIHNpbmdsZVxyXG4gICAgLy8gdGltZSB0aGVuIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZC5cclxuICAgIHByb3RvdHlwZS5vbmNlID0gZnVuY3Rpb24gKGV2ZW50LCBncm91cE5hbWUsIGZuKSB7XHJcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzLFxyXG4gICAgICAgICAgICBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcclxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xyXG4gICAgICAgIGZ1bmN0aW9uIG9uKCkge1xyXG4gICAgICAgICAgICBzZWxmLm9mZihldmVudCwgb24pO1xyXG4gICAgICAgICAgICBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMub24oZXZlbnQsIGdyb3VwLCBvbik7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFVuYmluZHMgYW4gZW50aXJlIGdyb3VwXHJcbiAgICBwcm90b3R5cGUucmVsZWFzZUdyb3VwID0gZnVuY3Rpb24gKGdyb3VwTmFtZSkge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGl0ZW0sIGksIGxlbiwgaGFuZGxlcnM7XHJcbiAgICAgICAgZm9yIChpdGVtIGluIHRoaXMuY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGhhbmRsZXJzID0gdGhpcy5jYWxsYmFja3NbaXRlbV07XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGhhbmRsZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoaGFuZGxlcnNbaV0uX2dyb3VwTmFtZSA9PT0gZ3JvdXBOYW1lKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmxvZygncmVtb3ZpbmcnKTtcclxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXQgYW5kIHNob3J0ZW4gdGhlIGFycmF5IHdlJ3JlIGxvb3BpbmcgdGhyb3VnaFxyXG4gICAgICAgICAgICAgICAgICAgIGhhbmRsZXJzLnNwbGljZShpLCAxKTtcclxuICAgICAgICAgICAgICAgICAgICBpLS07XHJcbiAgICAgICAgICAgICAgICAgICAgbGVuLS07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFJlbW92ZSB0aGUgZ2l2ZW4gY2FsbGJhY2sgZm9yIGBldmVudGAgb3IgYWxsXHJcbiAgICAvLyByZWdpc3RlcmVkIGNhbGxiYWNrcy5cclxuICAgIHByb3RvdHlwZS5vZmYgPSBmdW5jdGlvbiAoZXZlbnQsIGZuKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxyXG4gICAgICAgICAgICBpO1xyXG5cclxuICAgICAgICBpZiAoIWNhbGxiYWNrcykgcmV0dXJuIHRoaXM7XHJcblxyXG4gICAgICAgIC8vIHJlbW92ZSBhbGwgaGFuZGxlcnNcclxuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xyXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5jYWxsYmFja3NbZXZlbnRdO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIHJlbW92ZSBzcGVjaWZpYyBoYW5kbGVyXHJcbiAgICAgICAgaSA9IGNhbGxiYWNrcy5pbmRleE9mKGZuKTtcclxuICAgICAgICBjYWxsYmFja3Muc3BsaWNlKGksIDEpO1xyXG4gICAgICAgIGlmIChjYWxsYmFja3MubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tldmVudF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLy8gRW1pdCBgZXZlbnRgIHdpdGggdGhlIGdpdmVuIGFyZ3MuXHJcbiAgICAvLyBhbHNvIGNhbGxzIGFueSBgKmAgaGFuZGxlcnNcclxuICAgIHByb3RvdHlwZS5lbWl0ID0gZnVuY3Rpb24gKGV2ZW50KSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSxcclxuICAgICAgICAgICAgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxyXG4gICAgICAgICAgICBzcGVjaWFsQ2FsbGJhY2tzID0gdGhpcy5nZXRXaWxkY2FyZENhbGxiYWNrcyhldmVudCksXHJcbiAgICAgICAgICAgIGksXHJcbiAgICAgICAgICAgIGxlbixcclxuICAgICAgICAgICAgaXRlbSxcclxuICAgICAgICAgICAgbGlzdGVuZXJzO1xyXG5cclxuICAgICAgICBpZiAoY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IGNhbGxiYWNrcy5zbGljZSgpO1xyXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcclxuICAgICAgICAgICAgICAgIGlmICghbGlzdGVuZXJzW2ldKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkodGhpcywgYXJncyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChzcGVjaWFsQ2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGxlbiA9IHNwZWNpYWxDYWxsYmFja3MubGVuZ3RoO1xyXG4gICAgICAgICAgICBsaXN0ZW5lcnMgPSBzcGVjaWFsQ2FsbGJhY2tzLnNsaWNlKCk7XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFsaXN0ZW5lcnNbaV0pIHtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBbZXZlbnRdLmNvbmNhdChhcmdzKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBIZWxwZXIgZm9yIGZvciBmaW5kaW5nIHNwZWNpYWwgd2lsZGNhcmQgZXZlbnQgaGFuZGxlcnMgdGhhdCBtYXRjaCB0aGUgZXZlbnRcclxuICAgIHByb3RvdHlwZS5nZXRXaWxkY2FyZENhbGxiYWNrcyA9IGZ1bmN0aW9uIChldmVudE5hbWUpIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBpdGVtLFxyXG4gICAgICAgICAgICBzcGxpdCxcclxuICAgICAgICAgICAgcmVzdWx0ID0gW107XHJcblxyXG4gICAgICAgIGZvciAoaXRlbSBpbiB0aGlzLmNhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBzcGxpdCA9IGl0ZW0uc3BsaXQoJyonKTtcclxuICAgICAgICAgICAgaWYgKGl0ZW0gPT09ICcqJyB8fCAoc3BsaXQubGVuZ3RoID09PSAyICYmIGV2ZW50TmFtZS5zbGljZSgwLCBzcGxpdFswXS5sZW5ndGgpID09PSBzcGxpdFswXSkpIHtcclxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5jb25jYXQodGhpcy5jYWxsYmFja3NbaXRlbV0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICB9O1xyXG5cclxufTtcclxuXHJcbldpbGRFbWl0dGVyLm1peGluKFdpbGRFbWl0dGVyKTtcclxuIiwiLyohXG4gKiBFdmVudEVtaXR0ZXIgdjUuMi40IC0gZ2l0LmlvL2VlXG4gKiBVbmxpY2Vuc2UgLSBodHRwOi8vdW5saWNlbnNlLm9yZy9cbiAqIE9saXZlciBDYWxkd2VsbCAtIGh0dHA6Ly9vbGkubWUudWsvXG4gKiBAcHJlc2VydmVcbiAqL1xuXG47KGZ1bmN0aW9uIChleHBvcnRzKSB7XG4gICAgJ3VzZSBzdHJpY3QnO1xuXG4gICAgLyoqXG4gICAgICogQ2xhc3MgZm9yIG1hbmFnaW5nIGV2ZW50cy5cbiAgICAgKiBDYW4gYmUgZXh0ZW5kZWQgdG8gcHJvdmlkZSBldmVudCBmdW5jdGlvbmFsaXR5IGluIG90aGVyIGNsYXNzZXMuXG4gICAgICpcbiAgICAgKiBAY2xhc3MgRXZlbnRFbWl0dGVyIE1hbmFnZXMgZXZlbnQgcmVnaXN0ZXJpbmcgYW5kIGVtaXR0aW5nLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHt9XG5cbiAgICAvLyBTaG9ydGN1dHMgdG8gaW1wcm92ZSBzcGVlZCBhbmQgc2l6ZVxuICAgIHZhciBwcm90byA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGU7XG4gICAgdmFyIG9yaWdpbmFsR2xvYmFsVmFsdWUgPSBleHBvcnRzLkV2ZW50RW1pdHRlcjtcblxuICAgIC8qKlxuICAgICAqIEZpbmRzIHRoZSBpbmRleCBvZiB0aGUgbGlzdGVuZXIgZm9yIHRoZSBldmVudCBpbiBpdHMgc3RvcmFnZSBhcnJheS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gbGlzdGVuZXJzIEFycmF5IG9mIGxpc3RlbmVycyB0byBzZWFyY2ggdGhyb3VnaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gbG9vayBmb3IuXG4gICAgICogQHJldHVybiB7TnVtYmVyfSBJbmRleCBvZiB0aGUgc3BlY2lmaWVkIGxpc3RlbmVyLCAtMSBpZiBub3QgZm91bmRcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzLCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNbaV0ubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWxpYXMgYSBtZXRob2Qgd2hpbGUga2VlcGluZyB0aGUgY29udGV4dCBjb3JyZWN0LCB0byBhbGxvdyBmb3Igb3ZlcndyaXRpbmcgb2YgdGFyZ2V0IG1ldGhvZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSB0YXJnZXQgbWV0aG9kLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBUaGUgYWxpYXNlZCBtZXRob2RcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhbGlhcyhuYW1lKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBhbGlhc0Nsb3N1cmUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpc1tuYW1lXS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGxpc3RlbmVyIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdpbGwgaW5pdGlhbGlzZSB0aGUgZXZlbnQgb2JqZWN0IGFuZCBsaXN0ZW5lciBhcnJheXMgaWYgcmVxdWlyZWQuXG4gICAgICogV2lsbCByZXR1cm4gYW4gb2JqZWN0IGlmIHlvdSB1c2UgYSByZWdleCBzZWFyY2guIFRoZSBvYmplY3QgY29udGFpbnMga2V5cyBmb3IgZWFjaCBtYXRjaGVkIGV2ZW50LiBTbyAvYmFbcnpdLyBtaWdodCByZXR1cm4gYW4gb2JqZWN0IGNvbnRhaW5pbmcgYmFyIGFuZCBiYXouIEJ1dCBvbmx5IGlmIHlvdSBoYXZlIGVpdGhlciBkZWZpbmVkIHRoZW0gd2l0aCBkZWZpbmVFdmVudCBvciBhZGRlZCBzb21lIGxpc3RlbmVycyB0byB0aGVtLlxuICAgICAqIEVhY2ggcHJvcGVydHkgaW4gdGhlIG9iamVjdCByZXNwb25zZSBpcyBhbiBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZXR1cm4gdGhlIGxpc3RlbmVycyBmcm9tLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9uW118T2JqZWN0fSBBbGwgbGlzdGVuZXIgZnVuY3Rpb25zIGZvciB0aGUgZXZlbnQuXG4gICAgICovXG4gICAgcHJvdG8uZ2V0TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TGlzdGVuZXJzKGV2dCkge1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciByZXNwb25zZTtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICAvLyBSZXR1cm4gYSBjb25jYXRlbmF0ZWQgYXJyYXkgb2YgYWxsIG1hdGNoaW5nIGV2ZW50cyBpZlxuICAgICAgICAvLyB0aGUgc2VsZWN0b3IgaXMgYSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAgICAgIGlmIChldnQgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICAgICAgICBmb3IgKGtleSBpbiBldmVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnRzLmhhc093blByb3BlcnR5KGtleSkgJiYgZXZ0LnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICByZXNwb25zZVtrZXldID0gZXZlbnRzW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSBldmVudHNbZXZ0XSB8fCAoZXZlbnRzW2V2dF0gPSBbXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFRha2VzIGEgbGlzdCBvZiBsaXN0ZW5lciBvYmplY3RzIGFuZCBmbGF0dGVucyBpdCBpbnRvIGEgbGlzdCBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdFtdfSBsaXN0ZW5lcnMgUmF3IGxpc3RlbmVyIG9iamVjdHMuXG4gICAgICogQHJldHVybiB7RnVuY3Rpb25bXX0gSnVzdCB0aGUgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqL1xuICAgIHByb3RvLmZsYXR0ZW5MaXN0ZW5lcnMgPSBmdW5jdGlvbiBmbGF0dGVuTGlzdGVuZXJzKGxpc3RlbmVycykge1xuICAgICAgICB2YXIgZmxhdExpc3RlbmVycyA9IFtdO1xuICAgICAgICB2YXIgaTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBmbGF0TGlzdGVuZXJzLnB1c2gobGlzdGVuZXJzW2ldLmxpc3RlbmVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmbGF0TGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSByZXF1ZXN0ZWQgbGlzdGVuZXJzIHZpYSBnZXRMaXN0ZW5lcnMgYnV0IHdpbGwgYWx3YXlzIHJldHVybiB0aGUgcmVzdWx0cyBpbnNpZGUgYW4gb2JqZWN0LiBUaGlzIGlzIG1haW5seSBmb3IgaW50ZXJuYWwgdXNlIGJ1dCBvdGhlcnMgbWF5IGZpbmQgaXQgdXNlZnVsLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmV0dXJuIHRoZSBsaXN0ZW5lcnMgZnJvbS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEFsbCBsaXN0ZW5lciBmdW5jdGlvbnMgZm9yIGFuIGV2ZW50IGluIGFuIG9iamVjdC5cbiAgICAgKi9cbiAgICBwcm90by5nZXRMaXN0ZW5lcnNBc09iamVjdCA9IGZ1bmN0aW9uIGdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCkge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnMoZXZ0KTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuXG4gICAgICAgIGlmIChsaXN0ZW5lcnMgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSB7fTtcbiAgICAgICAgICAgIHJlc3BvbnNlW2V2dF0gPSBsaXN0ZW5lcnM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2UgfHwgbGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBpc1ZhbGlkTGlzdGVuZXIgKGxpc3RlbmVyKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXIgPT09ICdmdW5jdGlvbicgfHwgbGlzdGVuZXIgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgIH0gZWxzZSBpZiAobGlzdGVuZXIgJiYgdHlwZW9mIGxpc3RlbmVyID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmV0dXJuIGlzVmFsaWRMaXN0ZW5lcihsaXN0ZW5lci5saXN0ZW5lcilcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIHRvIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogVGhlIGxpc3RlbmVyIHdpbGwgbm90IGJlIGFkZGVkIGlmIGl0IGlzIGEgZHVwbGljYXRlLlxuICAgICAqIElmIHRoZSBsaXN0ZW5lciByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgaXQgaXMgY2FsbGVkLlxuICAgICAqIElmIHlvdSBwYXNzIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lIHRoZW4gdGhlIGxpc3RlbmVyIHdpbGwgYmUgYWRkZWQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gYXR0YWNoIHRoZSBsaXN0ZW5lciB0by5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWQuIElmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgY2FsbGluZy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKCFpc1ZhbGlkTGlzdGVuZXIobGlzdGVuZXIpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcklzV3JhcHBlZCA9IHR5cGVvZiBsaXN0ZW5lciA9PT0gJ29iamVjdCc7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmhhc093blByb3BlcnR5KGtleSkgJiYgaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVyc1trZXldLCBsaXN0ZW5lcikgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0ucHVzaChsaXN0ZW5lcklzV3JhcHBlZCA/IGxpc3RlbmVyIDoge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICAgICAgICAgIG9uY2U6IGZhbHNlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgYWRkTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vbiA9IGFsaWFzKCdhZGRMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogU2VtaS1hbGlhcyBvZiBhZGRMaXN0ZW5lci4gSXQgd2lsbCBhZGQgYSBsaXN0ZW5lciB0aGF0IHdpbGwgYmVcbiAgICAgKiBhdXRvbWF0aWNhbGx5IHJlbW92ZWQgYWZ0ZXIgaXRzIGZpcnN0IGV4ZWN1dGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGF0dGFjaCB0aGUgbGlzdGVuZXIgdG8uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyBlbWl0dGVkLiBJZiB0aGUgZnVuY3Rpb24gcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGNhbGxpbmcuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkT25jZUxpc3RlbmVyID0gZnVuY3Rpb24gYWRkT25jZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWRkTGlzdGVuZXIoZXZ0LCB7XG4gICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICBvbmNlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBhZGRPbmNlTGlzdGVuZXIuXG4gICAgICovXG4gICAgcHJvdG8ub25jZSA9IGFsaWFzKCdhZGRPbmNlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIERlZmluZXMgYW4gZXZlbnQgbmFtZS4gVGhpcyBpcyByZXF1aXJlZCBpZiB5b3Ugd2FudCB0byB1c2UgYSByZWdleCB0byBhZGQgYSBsaXN0ZW5lciB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gSWYgeW91IGRvbid0IGRvIHRoaXMgdGhlbiBob3cgZG8geW91IGV4cGVjdCBpdCB0byBrbm93IHdoYXQgZXZlbnQgdG8gYWRkIHRvPyBTaG91bGQgaXQganVzdCBhZGQgdG8gZXZlcnkgcG9zc2libGUgbWF0Y2ggZm9yIGEgcmVnZXg/IE5vLiBUaGF0IGlzIHNjYXJ5IGFuZCBiYWQuXG4gICAgICogWW91IG5lZWQgdG8gdGVsbCBpdCB3aGF0IGV2ZW50IG5hbWVzIHNob3VsZCBiZSBtYXRjaGVkIGJ5IGEgcmVnZXguXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGNyZWF0ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5kZWZpbmVFdmVudCA9IGZ1bmN0aW9uIGRlZmluZUV2ZW50KGV2dCkge1xuICAgICAgICB0aGlzLmdldExpc3RlbmVycyhldnQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVXNlcyBkZWZpbmVFdmVudCB0byBkZWZpbmUgbXVsdGlwbGUgZXZlbnRzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmdbXX0gZXZ0cyBBbiBhcnJheSBvZiBldmVudCBuYW1lcyB0byBkZWZpbmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZGVmaW5lRXZlbnRzID0gZnVuY3Rpb24gZGVmaW5lRXZlbnRzKGV2dHMpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBldnRzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICB0aGlzLmRlZmluZUV2ZW50KGV2dHNbaV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGEgbGlzdGVuZXIgZnVuY3Rpb24gZnJvbSB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdoZW4gcGFzc2VkIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lLCBpdCB3aWxsIHJlbW92ZSB0aGUgbGlzdGVuZXIgZnJvbSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZW1vdmUgdGhlIGxpc3RlbmVyIGZyb20uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIHJlbW92ZSBmcm9tIHRoZSBldmVudC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lciA9IGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGluZGV4O1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVycykge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgaW5kZXggPSBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzW2tleV0sIGxpc3RlbmVyKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0uc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vZmYgPSBhbGlhcygncmVtb3ZlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy4gWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIGFkZGVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIGFkZCB0aGUgYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKiBZZWFoLCB0aGlzIGZ1bmN0aW9uIGRvZXMgcXVpdGUgYSBiaXQuIFRoYXQncyBwcm9iYWJseSBhIGJhZCB0aGluZy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gYWRkLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZExpc3RlbmVycyA9IGZ1bmN0aW9uIGFkZExpc3RlbmVycyhldnQsIGxpc3RlbmVycykge1xuICAgICAgICAvLyBQYXNzIHRocm91Z2ggdG8gbWFuaXB1bGF0ZUxpc3RlbmVyc1xuICAgICAgICByZXR1cm4gdGhpcy5tYW5pcHVsYXRlTGlzdGVuZXJzKGZhbHNlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiByZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSByZW1vdmVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXJzIGZyb20gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIHJlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lcnMgPSBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcnMoZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gUGFzcyB0aHJvdWdoIHRvIG1hbmlwdWxhdGVMaXN0ZW5lcnNcbiAgICAgICAgcmV0dXJuIHRoaXMubWFuaXB1bGF0ZUxpc3RlbmVycyh0cnVlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEVkaXRzIGxpc3RlbmVycyBpbiBidWxrLiBUaGUgYWRkTGlzdGVuZXJzIGFuZCByZW1vdmVMaXN0ZW5lcnMgbWV0aG9kcyBib3RoIHVzZSB0aGlzIHRvIGRvIHRoZWlyIGpvYi4gWW91IHNob3VsZCByZWFsbHkgdXNlIHRob3NlIGluc3RlYWQsIHRoaXMgaXMgYSBsaXR0bGUgbG93ZXIgbGV2ZWwuXG4gICAgICogVGhlIGZpcnN0IGFyZ3VtZW50IHdpbGwgZGV0ZXJtaW5lIGlmIHRoZSBsaXN0ZW5lcnMgYXJlIHJlbW92ZWQgKHRydWUpIG9yIGFkZGVkIChmYWxzZSkuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBzZWNvbmQgYXJndW1lbnQgeW91IGNhbiBhZGQvcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgYWRkZWQvcmVtb3ZlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBtYW5pcHVsYXRlIHRoZSBsaXN0ZW5lcnMgb2YgYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtCb29sZWFufSByZW1vdmUgVHJ1ZSBpZiB5b3Ugd2FudCB0byByZW1vdmUgbGlzdGVuZXJzLCBmYWxzZSBpZiB5b3Ugd2FudCB0byBhZGQuXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIGFkZC9yZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byBhZGQvcmVtb3ZlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLm1hbmlwdWxhdGVMaXN0ZW5lcnMgPSBmdW5jdGlvbiBtYW5pcHVsYXRlTGlzdGVuZXJzKHJlbW92ZSwgZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciB2YWx1ZTtcbiAgICAgICAgdmFyIHNpbmdsZSA9IHJlbW92ZSA/IHRoaXMucmVtb3ZlTGlzdGVuZXIgOiB0aGlzLmFkZExpc3RlbmVyO1xuICAgICAgICB2YXIgbXVsdGlwbGUgPSByZW1vdmUgPyB0aGlzLnJlbW92ZUxpc3RlbmVycyA6IHRoaXMuYWRkTGlzdGVuZXJzO1xuXG4gICAgICAgIC8vIElmIGV2dCBpcyBhbiBvYmplY3QgdGhlbiBwYXNzIGVhY2ggb2YgaXRzIHByb3BlcnRpZXMgdG8gdGhpcyBtZXRob2RcbiAgICAgICAgaWYgKHR5cGVvZiBldnQgPT09ICdvYmplY3QnICYmICEoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSkge1xuICAgICAgICAgICAgZm9yIChpIGluIGV2dCkge1xuICAgICAgICAgICAgICAgIGlmIChldnQuaGFzT3duUHJvcGVydHkoaSkgJiYgKHZhbHVlID0gZXZ0W2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBQYXNzIHRoZSBzaW5nbGUgbGlzdGVuZXIgc3RyYWlnaHQgdGhyb3VnaCB0byB0aGUgc2luZ3VsYXIgbWV0aG9kXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbmdsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBwYXNzIGJhY2sgdG8gdGhlIG11bHRpcGxlIGZ1bmN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXBsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFNvIGV2dCBtdXN0IGJlIGEgc3RyaW5nXG4gICAgICAgICAgICAvLyBBbmQgbGlzdGVuZXJzIG11c3QgYmUgYW4gYXJyYXkgb2YgbGlzdGVuZXJzXG4gICAgICAgICAgICAvLyBMb29wIG92ZXIgaXQgYW5kIHBhc3MgZWFjaCBvbmUgdG8gdGhlIG11bHRpcGxlIG1ldGhvZFxuICAgICAgICAgICAgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgc2luZ2xlLmNhbGwodGhpcywgZXZ0LCBsaXN0ZW5lcnNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGxpc3RlbmVycyBmcm9tIGEgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIElmIHlvdSBkbyBub3Qgc3BlY2lmeSBhbiBldmVudCB0aGVuIGFsbCBsaXN0ZW5lcnMgd2lsbCBiZSByZW1vdmVkLlxuICAgICAqIFRoYXQgbWVhbnMgZXZlcnkgZXZlbnQgd2lsbCBiZSBlbXB0aWVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGEgcmVnZXggdG8gcmVtb3ZlIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gW2V2dF0gT3B0aW9uYWwgbmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIGFsbCBsaXN0ZW5lcnMgZm9yLiBXaWxsIHJlbW92ZSBmcm9tIGV2ZXJ5IGV2ZW50IGlmIG5vdCBwYXNzZWQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlRXZlbnQgPSBmdW5jdGlvbiByZW1vdmVFdmVudChldnQpIHtcbiAgICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgZXZ0O1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgLy8gUmVtb3ZlIGRpZmZlcmVudCB0aGluZ3MgZGVwZW5kaW5nIG9uIHRoZSBzdGF0ZSBvZiBldnRcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGxpc3RlbmVycyBmb3IgdGhlIHNwZWNpZmllZCBldmVudFxuICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1tldnRdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBldmVudHMgbWF0Y2hpbmcgdGhlIHJlZ2V4LlxuICAgICAgICAgICAgZm9yIChrZXkgaW4gZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGV2dC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgbGlzdGVuZXJzIGluIGFsbCBldmVudHNcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlRXZlbnQuXG4gICAgICpcbiAgICAgKiBBZGRlZCB0byBtaXJyb3IgdGhlIG5vZGUgQVBJLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUFsbExpc3RlbmVycyA9IGFsaWFzKCdyZW1vdmVFdmVudCcpO1xuXG4gICAgLyoqXG4gICAgICogRW1pdHMgYW4gZXZlbnQgb2YgeW91ciBjaG9pY2UuXG4gICAgICogV2hlbiBlbWl0dGVkLCBldmVyeSBsaXN0ZW5lciBhdHRhY2hlZCB0byB0aGF0IGV2ZW50IHdpbGwgYmUgZXhlY3V0ZWQuXG4gICAgICogSWYgeW91IHBhc3MgdGhlIG9wdGlvbmFsIGFyZ3VtZW50IGFycmF5IHRoZW4gdGhvc2UgYXJndW1lbnRzIHdpbGwgYmUgcGFzc2VkIHRvIGV2ZXJ5IGxpc3RlbmVyIHVwb24gZXhlY3V0aW9uLlxuICAgICAqIEJlY2F1c2UgaXQgdXNlcyBgYXBwbHlgLCB5b3VyIGFycmF5IG9mIGFyZ3VtZW50cyB3aWxsIGJlIHBhc3NlZCBhcyBpZiB5b3Ugd3JvdGUgdGhlbSBvdXQgc2VwYXJhdGVseS5cbiAgICAgKiBTbyB0aGV5IHdpbGwgbm90IGFycml2ZSB3aXRoaW4gdGhlIGFycmF5IG9uIHRoZSBvdGhlciBzaWRlLCB0aGV5IHdpbGwgYmUgc2VwYXJhdGUuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2FyZ3NdIE9wdGlvbmFsIGFycmF5IG9mIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0RXZlbnQgPSBmdW5jdGlvbiBlbWl0RXZlbnQoZXZ0LCBhcmdzKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnNNYXAgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcnM7XG4gICAgICAgIHZhciBsaXN0ZW5lcjtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIHZhciByZXNwb25zZTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnNNYXApIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNNYXAuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVycyA9IGxpc3RlbmVyc01hcFtrZXldLnNsaWNlKDApO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgbGlzdGVuZXIgcmV0dXJucyB0cnVlIHRoZW4gaXQgc2hhbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBldmVudFxuICAgICAgICAgICAgICAgICAgICAvLyBUaGUgZnVuY3Rpb24gaXMgZXhlY3V0ZWQgZWl0aGVyIHdpdGggYSBiYXNpYyBjYWxsIG9yIGFuIGFwcGx5IGlmIHRoZXJlIGlzIGFuIGFyZ3MgYXJyYXlcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxpc3RlbmVyLm9uY2UgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9IGxpc3RlbmVyLmxpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3MgfHwgW10pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZSA9PT0gdGhpcy5fZ2V0T25jZVJldHVyblZhbHVlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgZW1pdEV2ZW50XG4gICAgICovXG4gICAgcHJvdG8udHJpZ2dlciA9IGFsaWFzKCdlbWl0RXZlbnQnKTtcblxuICAgIC8qKlxuICAgICAqIFN1YnRseSBkaWZmZXJlbnQgZnJvbSBlbWl0RXZlbnQgaW4gdGhhdCBpdCB3aWxsIHBhc3MgaXRzIGFyZ3VtZW50cyBvbiB0byB0aGUgbGlzdGVuZXJzLCBhcyBvcHBvc2VkIHRvIHRha2luZyBhIHNpbmdsZSBhcnJheSBvZiBhcmd1bWVudHMgdG8gcGFzcyBvbi5cbiAgICAgKiBBcyB3aXRoIGVtaXRFdmVudCwgeW91IGNhbiBwYXNzIGEgcmVnZXggaW4gcGxhY2Ugb2YgdGhlIGV2ZW50IG5hbWUgdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHsuLi4qfSBPcHRpb25hbCBhZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0ID0gZnVuY3Rpb24gZW1pdChldnQpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICByZXR1cm4gdGhpcy5lbWl0RXZlbnQoZXZ0LCBhcmdzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBhZ2FpbnN0IHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy4gSWYgYVxuICAgICAqIGxpc3RlbmVycyByZXR1cm4gdmFsdWUgbWF0Y2hlcyB0aGUgb25lIHNldCBoZXJlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkXG4gICAgICogYWZ0ZXIgZXhlY3V0aW9uLiBUaGlzIHZhbHVlIGRlZmF1bHRzIHRvIHRydWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUgdG8gY2hlY2sgZm9yIHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5zZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBzZXRPbmNlUmV0dXJuVmFsdWUodmFsdWUpIHtcbiAgICAgICAgdGhpcy5fb25jZVJldHVyblZhbHVlID0gdmFsdWU7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGFnYWluc3Qgd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLiBJZlxuICAgICAqIHRoZSBsaXN0ZW5lcnMgcmV0dXJuIHZhbHVlIG1hdGNoZXMgdGhpcyBvbmUgdGhlbiBpdCBzaG91bGQgYmUgcmVtb3ZlZFxuICAgICAqIGF1dG9tYXRpY2FsbHkuIEl0IHdpbGwgcmV0dXJuIHRydWUgYnkgZGVmYXVsdC5cbiAgICAgKlxuICAgICAqIEByZXR1cm4geyp8Qm9vbGVhbn0gVGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgZm9yIG9yIHRoZSBkZWZhdWx0LCB0cnVlLlxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIHByb3RvLl9nZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBfZ2V0T25jZVJldHVyblZhbHVlKCkge1xuICAgICAgICBpZiAodGhpcy5oYXNPd25Qcm9wZXJ0eSgnX29uY2VSZXR1cm5WYWx1ZScpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb25jZVJldHVyblZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgZXZlbnRzIG9iamVjdCBhbmQgY3JlYXRlcyBvbmUgaWYgcmVxdWlyZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IFRoZSBldmVudHMgc3RvcmFnZSBvYmplY3QuXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgcHJvdG8uX2dldEV2ZW50cyA9IGZ1bmN0aW9uIF9nZXRFdmVudHMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9ldmVudHMgfHwgKHRoaXMuX2V2ZW50cyA9IHt9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmV2ZXJ0cyB0aGUgZ2xvYmFsIHtAbGluayBFdmVudEVtaXR0ZXJ9IHRvIGl0cyBwcmV2aW91cyB2YWx1ZSBhbmQgcmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGlzIHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gTm9uIGNvbmZsaWN0aW5nIEV2ZW50RW1pdHRlciBjbGFzcy5cbiAgICAgKi9cbiAgICBFdmVudEVtaXR0ZXIubm9Db25mbGljdCA9IGZ1bmN0aW9uIG5vQ29uZmxpY3QoKSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gb3JpZ2luYWxHbG9iYWxWYWx1ZTtcbiAgICAgICAgcmV0dXJuIEV2ZW50RW1pdHRlcjtcbiAgICB9O1xuXG4gICAgLy8gRXhwb3NlIHRoZSBjbGFzcyBlaXRoZXIgdmlhIEFNRCwgQ29tbW9uSlMgb3IgdGhlIGdsb2JhbCBvYmplY3RcbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gRXZlbnRFbWl0dGVyO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMpe1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuICAgIH1cbn0odGhpcyB8fCB7fSkpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vLyBMYXN0IFVwZGF0ZWQgT246IDIwMTctMTItMDkgMjoyOToyMiBQTSBVVENcblxuLy8gX19fX19fX19fX19fX19fX1xuLy8gRGV0ZWN0UlRDIHYxLjMuNlxuXG4vLyBPcGVuLVNvdXJjZWQ6IGh0dHBzOi8vZ2l0aHViLmNvbS9tdWF6LWtoYW4vRGV0ZWN0UlRDXG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBNdWF6IEtoYW4gICAgIC0gd3d3Lk11YXpLaGFuLmNvbVxuLy8gTUlUIExpY2Vuc2UgICAtIHd3dy5XZWJSVEMtRXhwZXJpbWVudC5jb20vbGljZW5jZVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuKGZ1bmN0aW9uKCkge1xuXG4gICAgdmFyIGJyb3dzZXJGYWtlVXNlckFnZW50ID0gJ0Zha2UvNS4wIChGYWtlT1MpIEFwcGxlV2ViS2l0LzEyMyAoS0hUTUwsIGxpa2UgR2Vja28pIEZha2UvMTIuMy40NTY3Ljg5IEZha2UvMTIzLjQ1JztcblxuICAgIHZhciBpc05vZGVqcyA9IHR5cGVvZiBwcm9jZXNzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgcHJvY2Vzcy52ZXJzaW9ucyA9PT0gJ29iamVjdCcgJiYgcHJvY2Vzcy52ZXJzaW9ucy5ub2RlICYmIC8qbm9kZS1wcm9jZXNzKi8gIXByb2Nlc3MuYnJvd3NlcjtcbiAgICBpZiAoaXNOb2RlanMpIHtcbiAgICAgICAgdmFyIHZlcnNpb24gPSBwcm9jZXNzLnZlcnNpb25zLm5vZGUudG9TdHJpbmcoKS5yZXBsYWNlKCd2JywgJycpO1xuICAgICAgICBicm93c2VyRmFrZVVzZXJBZ2VudCA9ICdOb2RlanMvJyArIHZlcnNpb24gKyAnIChOb2RlT1MpIEFwcGxlV2ViS2l0LycgKyB2ZXJzaW9uICsgJyAoS0hUTUwsIGxpa2UgR2Vja28pIE5vZGVqcy8nICsgdmVyc2lvbiArICcgTm9kZWpzLycgKyB2ZXJzaW9uXG4gICAgfVxuXG4gICAgKGZ1bmN0aW9uKHRoYXQpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIGdsb2JhbC5uYXZpZ2F0b3IgPSB7XG4gICAgICAgICAgICAgICAgdXNlckFnZW50OiBicm93c2VyRmFrZVVzZXJBZ2VudCxcbiAgICAgICAgICAgICAgICBnZXRVc2VyTWVkaWE6IGZ1bmN0aW9uKCkge31cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8qZ2xvYmFsIHdpbmRvdzp0cnVlICovXG4gICAgICAgICAgICB0aGF0LndpbmRvdyA9IGdsb2JhbDtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgLy8gd2luZG93ID0gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgbG9jYXRpb24gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAvKmdsb2JhbCBsb2NhdGlvbjp0cnVlICovXG4gICAgICAgICAgICB0aGF0LmxvY2F0aW9uID0ge1xuICAgICAgICAgICAgICAgIHByb3RvY29sOiAnZmlsZTonLFxuICAgICAgICAgICAgICAgIGhyZWY6ICcnLFxuICAgICAgICAgICAgICAgIGhhc2g6ICcnXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBzY3JlZW4gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAvKmdsb2JhbCBzY3JlZW46dHJ1ZSAqL1xuICAgICAgICAgICAgdGhhdC5zY3JlZW4gPSB7XG4gICAgICAgICAgICAgICAgd2lkdGg6IDAsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiAwXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfSkodHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcgPyBnbG9iYWwgOiB3aW5kb3cpO1xuXG4gICAgLypnbG9iYWwgbmF2aWdhdG9yOnRydWUgKi9cbiAgICB2YXIgbmF2aWdhdG9yID0gd2luZG93Lm5hdmlnYXRvcjtcblxuICAgIGlmICh0eXBlb2YgbmF2aWdhdG9yICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBpZiAodHlwZW9mIG5hdmlnYXRvci53ZWJraXRHZXRVc2VyTWVkaWEgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBuYXZpZ2F0b3IuZ2V0VXNlck1lZGlhID0gbmF2aWdhdG9yLndlYmtpdEdldFVzZXJNZWRpYTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgbmF2aWdhdG9yLm1vekdldFVzZXJNZWRpYSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIG5hdmlnYXRvci5nZXRVc2VyTWVkaWEgPSBuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbmF2aWdhdG9yID0ge1xuICAgICAgICAgICAgZ2V0VXNlck1lZGlhOiBmdW5jdGlvbigpIHt9LFxuICAgICAgICAgICAgdXNlckFnZW50OiBicm93c2VyRmFrZVVzZXJBZ2VudFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHZhciBpc01vYmlsZURldmljZSA9ICEhKC9BbmRyb2lkfHdlYk9TfGlQaG9uZXxpUGFkfGlQb2R8QkIxMHxCbGFja0JlcnJ5fElFTW9iaWxlfE9wZXJhIE1pbml8TW9iaWxlfG1vYmlsZS9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCB8fCAnJykpO1xuXG4gICAgdmFyIGlzRWRnZSA9IG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignRWRnZScpICE9PSAtMSAmJiAoISFuYXZpZ2F0b3IubXNTYXZlT3JPcGVuQmxvYiB8fCAhIW5hdmlnYXRvci5tc1NhdmVCbG9iKTtcblxuICAgIHZhciBpc09wZXJhID0gISF3aW5kb3cub3BlcmEgfHwgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCcgT1BSLycpID49IDA7XG4gICAgdmFyIGlzRmlyZWZveCA9IHR5cGVvZiB3aW5kb3cuSW5zdGFsbFRyaWdnZXIgIT09ICd1bmRlZmluZWQnO1xuICAgIHZhciBpc1NhZmFyaSA9IC9eKCg/IWNocm9tZXxhbmRyb2lkKS4pKnNhZmFyaS9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gICAgdmFyIGlzQ2hyb21lID0gISF3aW5kb3cuY2hyb21lICYmICFpc09wZXJhO1xuICAgIHZhciBpc0lFID0gdHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJyAmJiAhIWRvY3VtZW50LmRvY3VtZW50TW9kZSAmJiAhaXNFZGdlO1xuXG4gICAgLy8gdGhpcyBvbmUgY2FuIGFsc28gYmUgdXNlZDpcbiAgICAvLyBodHRwczovL3d3dy53ZWJzb2NrZXQub3JnL2pzL3N0dWZmLmpzIChEZXRlY3RCcm93c2VyLmpzKVxuXG4gICAgZnVuY3Rpb24gZ2V0QnJvd3NlckluZm8oKSB7XG4gICAgICAgIHZhciBuVmVyID0gbmF2aWdhdG9yLmFwcFZlcnNpb247XG4gICAgICAgIHZhciBuQWd0ID0gbmF2aWdhdG9yLnVzZXJBZ2VudDtcbiAgICAgICAgdmFyIGJyb3dzZXJOYW1lID0gbmF2aWdhdG9yLmFwcE5hbWU7XG4gICAgICAgIHZhciBmdWxsVmVyc2lvbiA9ICcnICsgcGFyc2VGbG9hdChuYXZpZ2F0b3IuYXBwVmVyc2lvbik7XG4gICAgICAgIHZhciBtYWpvclZlcnNpb24gPSBwYXJzZUludChuYXZpZ2F0b3IuYXBwVmVyc2lvbiwgMTApO1xuICAgICAgICB2YXIgbmFtZU9mZnNldCwgdmVyT2Zmc2V0LCBpeDtcblxuICAgICAgICAvLyBJbiBPcGVyYSwgdGhlIHRydWUgdmVyc2lvbiBpcyBhZnRlciAnT3BlcmEnIG9yIGFmdGVyICdWZXJzaW9uJ1xuICAgICAgICBpZiAoaXNPcGVyYSkge1xuICAgICAgICAgICAgYnJvd3Nlck5hbWUgPSAnT3BlcmEnO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBmdWxsVmVyc2lvbiA9IG5hdmlnYXRvci51c2VyQWdlbnQuc3BsaXQoJ09QUi8nKVsxXS5zcGxpdCgnICcpWzBdO1xuICAgICAgICAgICAgICAgIG1ham9yVmVyc2lvbiA9IGZ1bGxWZXJzaW9uLnNwbGl0KCcuJylbMF07XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgZnVsbFZlcnNpb24gPSAnMC4wLjAuMCc7XG4gICAgICAgICAgICAgICAgbWFqb3JWZXJzaW9uID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBJbiBNU0lFIHZlcnNpb24gPD0xMCwgdGhlIHRydWUgdmVyc2lvbiBpcyBhZnRlciAnTVNJRScgaW4gdXNlckFnZW50XG4gICAgICAgIC8vIEluIElFIDExLCBsb29rIGZvciB0aGUgc3RyaW5nIGFmdGVyICdydjonXG4gICAgICAgIGVsc2UgaWYgKGlzSUUpIHtcbiAgICAgICAgICAgIHZlck9mZnNldCA9IG5BZ3QuaW5kZXhPZigncnY6Jyk7XG4gICAgICAgICAgICBpZiAodmVyT2Zmc2V0ID4gMCkgeyAvL0lFIDExXG4gICAgICAgICAgICAgICAgZnVsbFZlcnNpb24gPSBuQWd0LnN1YnN0cmluZyh2ZXJPZmZzZXQgKyAzKTtcbiAgICAgICAgICAgIH0gZWxzZSB7IC8vSUUgMTAgb3IgZWFybGllclxuICAgICAgICAgICAgICAgIHZlck9mZnNldCA9IG5BZ3QuaW5kZXhPZignTVNJRScpO1xuICAgICAgICAgICAgICAgIGZ1bGxWZXJzaW9uID0gbkFndC5zdWJzdHJpbmcodmVyT2Zmc2V0ICsgNSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicm93c2VyTmFtZSA9ICdJRSc7XG4gICAgICAgIH1cbiAgICAgICAgLy8gSW4gQ2hyb21lLCB0aGUgdHJ1ZSB2ZXJzaW9uIGlzIGFmdGVyICdDaHJvbWUnIFxuICAgICAgICBlbHNlIGlmIChpc0Nocm9tZSkge1xuICAgICAgICAgICAgdmVyT2Zmc2V0ID0gbkFndC5pbmRleE9mKCdDaHJvbWUnKTtcbiAgICAgICAgICAgIGJyb3dzZXJOYW1lID0gJ0Nocm9tZSc7XG4gICAgICAgICAgICBmdWxsVmVyc2lvbiA9IG5BZ3Quc3Vic3RyaW5nKHZlck9mZnNldCArIDcpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEluIFNhZmFyaSwgdGhlIHRydWUgdmVyc2lvbiBpcyBhZnRlciAnU2FmYXJpJyBvciBhZnRlciAnVmVyc2lvbicgXG4gICAgICAgIGVsc2UgaWYgKGlzU2FmYXJpKSB7XG4gICAgICAgICAgICB2ZXJPZmZzZXQgPSBuQWd0LmluZGV4T2YoJ1NhZmFyaScpO1xuXG4gICAgICAgICAgICBicm93c2VyTmFtZSA9ICdTYWZhcmknO1xuICAgICAgICAgICAgZnVsbFZlcnNpb24gPSBuQWd0LnN1YnN0cmluZyh2ZXJPZmZzZXQgKyA3KTtcblxuICAgICAgICAgICAgaWYgKCh2ZXJPZmZzZXQgPSBuQWd0LmluZGV4T2YoJ1ZlcnNpb24nKSkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgZnVsbFZlcnNpb24gPSBuQWd0LnN1YnN0cmluZyh2ZXJPZmZzZXQgKyA4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignVmVyc2lvbi8nKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBmdWxsVmVyc2lvbiA9IG5hdmlnYXRvci51c2VyQWdlbnQuc3BsaXQoJ1ZlcnNpb24vJylbMV0uc3BsaXQoJyAnKVswXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBJbiBGaXJlZm94LCB0aGUgdHJ1ZSB2ZXJzaW9uIGlzIGFmdGVyICdGaXJlZm94JyBcbiAgICAgICAgZWxzZSBpZiAoaXNGaXJlZm94KSB7XG4gICAgICAgICAgICB2ZXJPZmZzZXQgPSBuQWd0LmluZGV4T2YoJ0ZpcmVmb3gnKTtcbiAgICAgICAgICAgIGJyb3dzZXJOYW1lID0gJ0ZpcmVmb3gnO1xuICAgICAgICAgICAgZnVsbFZlcnNpb24gPSBuQWd0LnN1YnN0cmluZyh2ZXJPZmZzZXQgKyA4KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEluIG1vc3Qgb3RoZXIgYnJvd3NlcnMsICduYW1lL3ZlcnNpb24nIGlzIGF0IHRoZSBlbmQgb2YgdXNlckFnZW50IFxuICAgICAgICBlbHNlIGlmICgobmFtZU9mZnNldCA9IG5BZ3QubGFzdEluZGV4T2YoJyAnKSArIDEpIDwgKHZlck9mZnNldCA9IG5BZ3QubGFzdEluZGV4T2YoJy8nKSkpIHtcbiAgICAgICAgICAgIGJyb3dzZXJOYW1lID0gbkFndC5zdWJzdHJpbmcobmFtZU9mZnNldCwgdmVyT2Zmc2V0KTtcbiAgICAgICAgICAgIGZ1bGxWZXJzaW9uID0gbkFndC5zdWJzdHJpbmcodmVyT2Zmc2V0ICsgMSk7XG5cbiAgICAgICAgICAgIGlmIChicm93c2VyTmFtZS50b0xvd2VyQ2FzZSgpID09PSBicm93c2VyTmFtZS50b1VwcGVyQ2FzZSgpKSB7XG4gICAgICAgICAgICAgICAgYnJvd3Nlck5hbWUgPSBuYXZpZ2F0b3IuYXBwTmFtZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc0VkZ2UpIHtcbiAgICAgICAgICAgIGJyb3dzZXJOYW1lID0gJ0VkZ2UnO1xuICAgICAgICAgICAgZnVsbFZlcnNpb24gPSBuYXZpZ2F0b3IudXNlckFnZW50LnNwbGl0KCdFZGdlLycpWzFdO1xuICAgICAgICAgICAgLy8gZnVsbFZlcnNpb24gPSBwYXJzZUludChuYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKC9FZGdlXFwvKFxcZCspLihcXGQrKSQvKVsyXSwgMTApLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0cmltIHRoZSBmdWxsVmVyc2lvbiBzdHJpbmcgYXQgc2VtaWNvbG9uL3NwYWNlL2JyYWNrZXQgaWYgcHJlc2VudFxuICAgICAgICBpZiAoKGl4ID0gZnVsbFZlcnNpb24uc2VhcmNoKC9bOyBcXCldLykpICE9PSAtMSkge1xuICAgICAgICAgICAgZnVsbFZlcnNpb24gPSBmdWxsVmVyc2lvbi5zdWJzdHJpbmcoMCwgaXgpO1xuICAgICAgICB9XG5cbiAgICAgICAgbWFqb3JWZXJzaW9uID0gcGFyc2VJbnQoJycgKyBmdWxsVmVyc2lvbiwgMTApO1xuXG4gICAgICAgIGlmIChpc05hTihtYWpvclZlcnNpb24pKSB7XG4gICAgICAgICAgICBmdWxsVmVyc2lvbiA9ICcnICsgcGFyc2VGbG9hdChuYXZpZ2F0b3IuYXBwVmVyc2lvbik7XG4gICAgICAgICAgICBtYWpvclZlcnNpb24gPSBwYXJzZUludChuYXZpZ2F0b3IuYXBwVmVyc2lvbiwgMTApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGZ1bGxWZXJzaW9uOiBmdWxsVmVyc2lvbixcbiAgICAgICAgICAgIHZlcnNpb246IG1ham9yVmVyc2lvbixcbiAgICAgICAgICAgIG5hbWU6IGJyb3dzZXJOYW1lLFxuICAgICAgICAgICAgaXNQcml2YXRlQnJvd3Npbmc6IGZhbHNlXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gdmlhOiBodHRwczovL2dpc3QuZ2l0aHViLmNvbS9jb3U5MjkvNzk3Mzk1NlxuXG4gICAgZnVuY3Rpb24gcmV0cnkoaXNEb25lLCBuZXh0KSB7XG4gICAgICAgIHZhciBjdXJyZW50VHJpYWwgPSAwLFxuICAgICAgICAgICAgbWF4UmV0cnkgPSA1MCxcbiAgICAgICAgICAgIGludGVydmFsID0gMTAsXG4gICAgICAgICAgICBpc1RpbWVvdXQgPSBmYWxzZTtcbiAgICAgICAgdmFyIGlkID0gd2luZG93LnNldEludGVydmFsKFxuICAgICAgICAgICAgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzRG9uZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5jbGVhckludGVydmFsKGlkKTtcbiAgICAgICAgICAgICAgICAgICAgbmV4dChpc1RpbWVvdXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudFRyaWFsKysgPiBtYXhSZXRyeSkge1xuICAgICAgICAgICAgICAgICAgICB3aW5kb3cuY2xlYXJJbnRlcnZhbChpZCk7XG4gICAgICAgICAgICAgICAgICAgIGlzVGltZW91dCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIG5leHQoaXNUaW1lb3V0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgMTBcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc0lFMTBPckxhdGVyKHVzZXJBZ2VudCkge1xuICAgICAgICB2YXIgdWEgPSB1c2VyQWdlbnQudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgaWYgKHVhLmluZGV4T2YoJ21zaWUnKSA9PT0gMCAmJiB1YS5pbmRleE9mKCd0cmlkZW50JykgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbWF0Y2ggPSAvKD86bXNpZXxydjopXFxzPyhbXFxkXFwuXSspLy5leGVjKHVhKTtcbiAgICAgICAgaWYgKG1hdGNoICYmIHBhcnNlSW50KG1hdGNoWzFdLCAxMCkgPj0gMTApIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkZXRlY3RQcml2YXRlTW9kZShjYWxsYmFjaykge1xuICAgICAgICB2YXIgaXNQcml2YXRlO1xuXG4gICAgICAgIHRyeSB7XG5cbiAgICAgICAgICAgIGlmICh3aW5kb3cud2Via2l0UmVxdWVzdEZpbGVTeXN0ZW0pIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cud2Via2l0UmVxdWVzdEZpbGVTeXN0ZW0oXG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5URU1QT1JBUlksIDEsXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaXNQcml2YXRlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzUHJpdmF0ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh3aW5kb3cuaW5kZXhlZERCICYmIC9GaXJlZm94Ly50ZXN0KHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50KSkge1xuICAgICAgICAgICAgICAgIHZhciBkYjtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBkYiA9IHdpbmRvdy5pbmRleGVkREIub3BlbigndGVzdCcpO1xuICAgICAgICAgICAgICAgICAgICBkYi5vbmVycm9yID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlzUHJpdmF0ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBpc1ByaXZhdGUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHJ5KFxuICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gaXNEb25lKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkYi5yZWFkeVN0YXRlID09PSAnZG9uZScgPyB0cnVlIDogZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gbmV4dChpc1RpbWVvdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVGltZW91dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1ByaXZhdGUgPSBkYi5yZXN1bHQgPyBmYWxzZSA6IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNJRTEwT3JMYXRlcih3aW5kb3cubmF2aWdhdG9yLnVzZXJBZ2VudCkpIHtcbiAgICAgICAgICAgICAgICBpc1ByaXZhdGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXdpbmRvdy5pbmRleGVkREIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzUHJpdmF0ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlzUHJpdmF0ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmICh3aW5kb3cubG9jYWxTdG9yYWdlICYmIC9TYWZhcmkvLnRlc3Qod2luZG93Lm5hdmlnYXRvci51c2VyQWdlbnQpKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgd2luZG93LmxvY2FsU3RvcmFnZS5zZXRJdGVtKCd0ZXN0JywgMSk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICBpc1ByaXZhdGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaXNQcml2YXRlID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBpc1ByaXZhdGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgd2luZG93LmxvY2FsU3RvcmFnZS5yZW1vdmVJdGVtKCd0ZXN0Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGlzUHJpdmF0ZSA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0cnkoXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0RvbmUoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBpc1ByaXZhdGUgIT09ICd1bmRlZmluZWQnID8gdHJ1ZSA6IGZhbHNlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZ1bmN0aW9uIG5leHQoaXNUaW1lb3V0KSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soaXNQcml2YXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICB2YXIgaXNNb2JpbGUgPSB7XG4gICAgICAgIEFuZHJvaWQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goL0FuZHJvaWQvaSk7XG4gICAgICAgIH0sXG4gICAgICAgIEJsYWNrQmVycnk6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goL0JsYWNrQmVycnl8QkIxMC9pKTtcbiAgICAgICAgfSxcbiAgICAgICAgaU9TOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiBuYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKC9pUGhvbmV8aVBhZHxpUG9kL2kpO1xuICAgICAgICB9LFxuICAgICAgICBPcGVyYTogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gbmF2aWdhdG9yLnVzZXJBZ2VudC5tYXRjaCgvT3BlcmEgTWluaS9pKTtcbiAgICAgICAgfSxcbiAgICAgICAgV2luZG93czogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gbmF2aWdhdG9yLnVzZXJBZ2VudC5tYXRjaCgvSUVNb2JpbGUvaSk7XG4gICAgICAgIH0sXG4gICAgICAgIGFueTogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gKGlzTW9iaWxlLkFuZHJvaWQoKSB8fCBpc01vYmlsZS5CbGFja0JlcnJ5KCkgfHwgaXNNb2JpbGUuaU9TKCkgfHwgaXNNb2JpbGUuT3BlcmEoKSB8fCBpc01vYmlsZS5XaW5kb3dzKCkpO1xuICAgICAgICB9LFxuICAgICAgICBnZXRPc05hbWU6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIG9zTmFtZSA9ICdVbmtub3duIE9TJztcbiAgICAgICAgICAgIGlmIChpc01vYmlsZS5BbmRyb2lkKCkpIHtcbiAgICAgICAgICAgICAgICBvc05hbWUgPSAnQW5kcm9pZCc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChpc01vYmlsZS5CbGFja0JlcnJ5KCkpIHtcbiAgICAgICAgICAgICAgICBvc05hbWUgPSAnQmxhY2tCZXJyeSc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChpc01vYmlsZS5pT1MoKSkge1xuICAgICAgICAgICAgICAgIG9zTmFtZSA9ICdpT1MnO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoaXNNb2JpbGUuT3BlcmEoKSkge1xuICAgICAgICAgICAgICAgIG9zTmFtZSA9ICdPcGVyYSBNaW5pJztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGlzTW9iaWxlLldpbmRvd3MoKSkge1xuICAgICAgICAgICAgICAgIG9zTmFtZSA9ICdXaW5kb3dzJztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIG9zTmFtZTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvLyB2aWE6IGh0dHA6Ly9qc2ZpZGRsZS5uZXQvQ2hyaXN0aWFuTC9BVnlORC9cbiAgICBmdW5jdGlvbiBkZXRlY3REZXNrdG9wT1MoKSB7XG4gICAgICAgIHZhciB1bmtub3duID0gJy0nO1xuXG4gICAgICAgIHZhciBuVmVyID0gbmF2aWdhdG9yLmFwcFZlcnNpb247XG4gICAgICAgIHZhciBuQWd0ID0gbmF2aWdhdG9yLnVzZXJBZ2VudDtcblxuICAgICAgICB2YXIgb3MgPSB1bmtub3duO1xuICAgICAgICB2YXIgY2xpZW50U3RyaW5ncyA9IFt7XG4gICAgICAgICAgICBzOiAnV2luZG93cyAxMCcsXG4gICAgICAgICAgICByOiAvKFdpbmRvd3MgMTAuMHxXaW5kb3dzIE5UIDEwLjApL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnV2luZG93cyA4LjEnLFxuICAgICAgICAgICAgcjogLyhXaW5kb3dzIDguMXxXaW5kb3dzIE5UIDYuMykvXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHM6ICdXaW5kb3dzIDgnLFxuICAgICAgICAgICAgcjogLyhXaW5kb3dzIDh8V2luZG93cyBOVCA2LjIpL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnV2luZG93cyA3JyxcbiAgICAgICAgICAgIHI6IC8oV2luZG93cyA3fFdpbmRvd3MgTlQgNi4xKS9cbiAgICAgICAgfSwge1xuICAgICAgICAgICAgczogJ1dpbmRvd3MgVmlzdGEnLFxuICAgICAgICAgICAgcjogL1dpbmRvd3MgTlQgNi4wL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnV2luZG93cyBTZXJ2ZXIgMjAwMycsXG4gICAgICAgICAgICByOiAvV2luZG93cyBOVCA1LjIvXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHM6ICdXaW5kb3dzIFhQJyxcbiAgICAgICAgICAgIHI6IC8oV2luZG93cyBOVCA1LjF8V2luZG93cyBYUCkvXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHM6ICdXaW5kb3dzIDIwMDAnLFxuICAgICAgICAgICAgcjogLyhXaW5kb3dzIE5UIDUuMHxXaW5kb3dzIDIwMDApL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnV2luZG93cyBNRScsXG4gICAgICAgICAgICByOiAvKFdpbiA5eCA0LjkwfFdpbmRvd3MgTUUpL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnV2luZG93cyA5OCcsXG4gICAgICAgICAgICByOiAvKFdpbmRvd3MgOTh8V2luOTgpL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnV2luZG93cyA5NScsXG4gICAgICAgICAgICByOiAvKFdpbmRvd3MgOTV8V2luOTV8V2luZG93c185NSkvXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHM6ICdXaW5kb3dzIE5UIDQuMCcsXG4gICAgICAgICAgICByOiAvKFdpbmRvd3MgTlQgNC4wfFdpbk5UNC4wfFdpbk5UfFdpbmRvd3MgTlQpL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnV2luZG93cyBDRScsXG4gICAgICAgICAgICByOiAvV2luZG93cyBDRS9cbiAgICAgICAgfSwge1xuICAgICAgICAgICAgczogJ1dpbmRvd3MgMy4xMScsXG4gICAgICAgICAgICByOiAvV2luMTYvXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHM6ICdBbmRyb2lkJyxcbiAgICAgICAgICAgIHI6IC9BbmRyb2lkL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnT3BlbiBCU0QnLFxuICAgICAgICAgICAgcjogL09wZW5CU0QvXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHM6ICdTdW4gT1MnLFxuICAgICAgICAgICAgcjogL1N1bk9TL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnTGludXgnLFxuICAgICAgICAgICAgcjogLyhMaW51eHxYMTEpL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnaU9TJyxcbiAgICAgICAgICAgIHI6IC8oaVBob25lfGlQYWR8aVBvZCkvXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHM6ICdNYWMgT1MgWCcsXG4gICAgICAgICAgICByOiAvTWFjIE9TIFgvXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHM6ICdNYWMgT1MnLFxuICAgICAgICAgICAgcjogLyhNYWNQUEN8TWFjSW50ZWx8TWFjX1Bvd2VyUEN8TWFjaW50b3NoKS9cbiAgICAgICAgfSwge1xuICAgICAgICAgICAgczogJ1FOWCcsXG4gICAgICAgICAgICByOiAvUU5YL1xuICAgICAgICB9LCB7XG4gICAgICAgICAgICBzOiAnVU5JWCcsXG4gICAgICAgICAgICByOiAvVU5JWC9cbiAgICAgICAgfSwge1xuICAgICAgICAgICAgczogJ0JlT1MnLFxuICAgICAgICAgICAgcjogL0JlT1MvXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHM6ICdPUy8yJyxcbiAgICAgICAgICAgIHI6IC9PU1xcLzIvXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHM6ICdTZWFyY2ggQm90JyxcbiAgICAgICAgICAgIHI6IC8obnVoa3xHb29nbGVib3R8WWFtbXlib3R8T3BlbmJvdHxTbHVycHxNU05Cb3R8QXNrIEplZXZlc1xcL1Rlb21hfGlhX2FyY2hpdmVyKS9cbiAgICAgICAgfV07XG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBjczsgY3MgPSBjbGllbnRTdHJpbmdzW2ldOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChjcy5yLnRlc3QobkFndCkpIHtcbiAgICAgICAgICAgICAgICBvcyA9IGNzLnM7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgb3NWZXJzaW9uID0gdW5rbm93bjtcblxuICAgICAgICBpZiAoL1dpbmRvd3MvLnRlc3Qob3MpKSB7XG4gICAgICAgICAgICBpZiAoL1dpbmRvd3MgKC4qKS8udGVzdChvcykpIHtcbiAgICAgICAgICAgICAgICBvc1ZlcnNpb24gPSAvV2luZG93cyAoLiopLy5leGVjKG9zKVsxXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG9zID0gJ1dpbmRvd3MnO1xuICAgICAgICB9XG5cbiAgICAgICAgc3dpdGNoIChvcykge1xuICAgICAgICAgICAgY2FzZSAnTWFjIE9TIFgnOlxuICAgICAgICAgICAgICAgIGlmICgvTWFjIE9TIFggKDEwW1xcLlxcX1xcZF0rKS8udGVzdChuQWd0KSkge1xuICAgICAgICAgICAgICAgICAgICBvc1ZlcnNpb24gPSAvTWFjIE9TIFggKDEwW1xcLlxcX1xcZF0rKS8uZXhlYyhuQWd0KVsxXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdBbmRyb2lkJzpcbiAgICAgICAgICAgICAgICBpZiAoL0FuZHJvaWQgKFtcXC5cXF9cXGRdKykvLnRlc3QobkFndCkpIHtcbiAgICAgICAgICAgICAgICAgICAgb3NWZXJzaW9uID0gL0FuZHJvaWQgKFtcXC5cXF9cXGRdKykvLmV4ZWMobkFndClbMV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnaU9TJzpcbiAgICAgICAgICAgICAgICBpZiAoL09TIChcXGQrKV8oXFxkKylfPyhcXGQrKT8vLnRlc3QobkFndCkpIHtcbiAgICAgICAgICAgICAgICAgICAgb3NWZXJzaW9uID0gL09TIChcXGQrKV8oXFxkKylfPyhcXGQrKT8vLmV4ZWMoblZlcik7XG4gICAgICAgICAgICAgICAgICAgIG9zVmVyc2lvbiA9IG9zVmVyc2lvblsxXSArICcuJyArIG9zVmVyc2lvblsyXSArICcuJyArIChvc1ZlcnNpb25bM10gfCAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgb3NOYW1lOiBvcyxcbiAgICAgICAgICAgIG9zVmVyc2lvbjogb3NWZXJzaW9uXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIG9zTmFtZSA9ICdVbmtub3duIE9TJztcbiAgICB2YXIgb3NWZXJzaW9uID0gJ1Vua25vd24gT1MgVmVyc2lvbic7XG5cbiAgICBmdW5jdGlvbiBnZXRBbmRyb2lkVmVyc2lvbih1YSkge1xuICAgICAgICB1YSA9ICh1YSB8fCBuYXZpZ2F0b3IudXNlckFnZW50KS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICB2YXIgbWF0Y2ggPSB1YS5tYXRjaCgvYW5kcm9pZFxccyhbMC05XFwuXSopLyk7XG4gICAgICAgIHJldHVybiBtYXRjaCA/IG1hdGNoWzFdIDogZmFsc2U7XG4gICAgfVxuXG4gICAgdmFyIG9zSW5mbyA9IGRldGVjdERlc2t0b3BPUygpO1xuXG4gICAgaWYgKG9zSW5mbyAmJiBvc0luZm8ub3NOYW1lICYmIG9zSW5mby5vc05hbWUgIT0gJy0nKSB7XG4gICAgICAgIG9zTmFtZSA9IG9zSW5mby5vc05hbWU7XG4gICAgICAgIG9zVmVyc2lvbiA9IG9zSW5mby5vc1ZlcnNpb247XG4gICAgfSBlbHNlIGlmIChpc01vYmlsZS5hbnkoKSkge1xuICAgICAgICBvc05hbWUgPSBpc01vYmlsZS5nZXRPc05hbWUoKTtcblxuICAgICAgICBpZiAob3NOYW1lID09ICdBbmRyb2lkJykge1xuICAgICAgICAgICAgb3NWZXJzaW9uID0gZ2V0QW5kcm9pZFZlcnNpb24oKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBpc05vZGVqcyA9IHR5cGVvZiBwcm9jZXNzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgcHJvY2Vzcy52ZXJzaW9ucyA9PT0gJ29iamVjdCcgJiYgcHJvY2Vzcy52ZXJzaW9ucy5ub2RlO1xuXG4gICAgaWYgKG9zTmFtZSA9PT0gJ1Vua25vd24gT1MnICYmIGlzTm9kZWpzKSB7XG4gICAgICAgIG9zTmFtZSA9ICdOb2RlanMnO1xuICAgICAgICBvc1ZlcnNpb24gPSBwcm9jZXNzLnZlcnNpb25zLm5vZGUudG9TdHJpbmcoKS5yZXBsYWNlKCd2JywgJycpO1xuICAgIH1cblxuICAgIHZhciBpc0NhbnZhc1N1cHBvcnRzU3RyZWFtQ2FwdHVyaW5nID0gZmFsc2U7XG4gICAgdmFyIGlzVmlkZW9TdXBwb3J0c1N0cmVhbUNhcHR1cmluZyA9IGZhbHNlO1xuICAgIFsnY2FwdHVyZVN0cmVhbScsICdtb3pDYXB0dXJlU3RyZWFtJywgJ3dlYmtpdENhcHR1cmVTdHJlYW0nXS5mb3JFYWNoKGZ1bmN0aW9uKGl0ZW0pIHtcbiAgICAgICAgaWYgKHR5cGVvZiBkb2N1bWVudCA9PT0gJ3VuZGVmaW5lZCcgfHwgdHlwZW9mIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghaXNDYW52YXNTdXBwb3J0c1N0cmVhbUNhcHR1cmluZyAmJiBpdGVtIGluIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpKSB7XG4gICAgICAgICAgICBpc0NhbnZhc1N1cHBvcnRzU3RyZWFtQ2FwdHVyaW5nID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghaXNWaWRlb1N1cHBvcnRzU3RyZWFtQ2FwdHVyaW5nICYmIGl0ZW0gaW4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKSkge1xuICAgICAgICAgICAgaXNWaWRlb1N1cHBvcnRzU3RyZWFtQ2FwdHVyaW5nID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gdmlhOiBodHRwczovL2dpdGh1Yi5jb20vZGlhZnlnaS93ZWJydGMtaXBzXG4gICAgZnVuY3Rpb24gRGV0ZWN0TG9jYWxJUEFkZHJlc3MoY2FsbGJhY2ssIHN0cmVhbSkge1xuICAgICAgICBpZiAoIURldGVjdFJUQy5pc1dlYlJUQ1N1cHBvcnRlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2V0SVBzKGZ1bmN0aW9uKGlwKSB7XG4gICAgICAgICAgICBpZiAoaXAubWF0Y2goL14oMTkyXFwuMTY4XFwufDE2OVxcLjI1NFxcLnwxMFxcLnwxNzJcXC4oMVs2LTldfDJcXGR8M1swMV0pKS8pKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soJ0xvY2FsOiAnICsgaXApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygnUHVibGljOiAnICsgaXApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCBzdHJlYW0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldElQcyhjYWxsYmFjaywgc3RyZWFtKSB7XG4gICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgPT09ICd1bmRlZmluZWQnIHx8IHR5cGVvZiBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGlwRHVwbGljYXRlcyA9IHt9O1xuXG4gICAgICAgIHZhciBSVENQZWVyQ29ubmVjdGlvbiA9IHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiB8fCB3aW5kb3cubW96UlRDUGVlckNvbm5lY3Rpb24gfHwgd2luZG93LndlYmtpdFJUQ1BlZXJDb25uZWN0aW9uO1xuXG4gICAgICAgIGlmICghUlRDUGVlckNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIHZhciBpZnJhbWUgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnaWZyYW1lJyk7XG4gICAgICAgICAgICBpZiAoIWlmcmFtZSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciB3aW4gPSBpZnJhbWUuY29udGVudFdpbmRvdztcbiAgICAgICAgICAgIFJUQ1BlZXJDb25uZWN0aW9uID0gd2luLlJUQ1BlZXJDb25uZWN0aW9uIHx8IHdpbi5tb3pSVENQZWVyQ29ubmVjdGlvbiB8fCB3aW4ud2Via2l0UlRDUGVlckNvbm5lY3Rpb247XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIVJUQ1BlZXJDb25uZWN0aW9uKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcGVlckNvbmZpZyA9IG51bGw7XG5cbiAgICAgICAgaWYgKERldGVjdFJUQy5icm93c2VyID09PSAnQ2hyb21lJyAmJiBEZXRlY3RSVEMuYnJvd3Nlci52ZXJzaW9uIDwgNTgpIHtcbiAgICAgICAgICAgIC8vIHRvZG86IGFkZCBzdXBwb3J0IGZvciBvbGRlciBPcGVyYVxuICAgICAgICAgICAgcGVlckNvbmZpZyA9IHtcbiAgICAgICAgICAgICAgICBvcHRpb25hbDogW3tcbiAgICAgICAgICAgICAgICAgICAgUnRwRGF0YUNoYW5uZWxzOiB0cnVlXG4gICAgICAgICAgICAgICAgfV1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc2VydmVycyA9IHtcbiAgICAgICAgICAgIGljZVNlcnZlcnM6IFt7XG4gICAgICAgICAgICAgICAgdXJsczogJ3N0dW46c3R1bi5sLmdvb2dsZS5jb206MTkzMDInXG4gICAgICAgICAgICB9XVxuICAgICAgICB9O1xuXG4gICAgICAgIHZhciBwYyA9IG5ldyBSVENQZWVyQ29ubmVjdGlvbihzZXJ2ZXJzLCBwZWVyQ29uZmlnKTtcblxuICAgICAgICBpZiAoc3RyZWFtKSB7XG4gICAgICAgICAgICBpZiAocGMuYWRkU3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgcGMuYWRkU3RyZWFtKHN0cmVhbSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHBjLmFkZFRyYWNrICYmIHN0cmVhbS5nZXRUcmFja3MoKVswXSkge1xuICAgICAgICAgICAgICAgIHBjLmFkZFRyYWNrKHN0cmVhbS5nZXRUcmFja3MoKVswXSwgc3RyZWFtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGhhbmRsZUNhbmRpZGF0ZShjYW5kaWRhdGUpIHtcbiAgICAgICAgICAgIHZhciBpcFJlZ2V4ID0gLyhbMC05XXsxLDN9KFxcLlswLTldezEsM30pezN9KS87XG4gICAgICAgICAgICB2YXIgbWF0Y2ggPSBpcFJlZ2V4LmV4ZWMoY2FuZGlkYXRlKTtcbiAgICAgICAgICAgIGlmICghbWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgaXBBZGRyZXNzID0gbWF0Y2hbMV07XG5cbiAgICAgICAgICAgIGlmIChpcER1cGxpY2F0ZXNbaXBBZGRyZXNzXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soaXBBZGRyZXNzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaXBEdXBsaWNhdGVzW2lwQWRkcmVzc10gPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gbGlzdGVuIGZvciBjYW5kaWRhdGUgZXZlbnRzXG4gICAgICAgIHBjLm9uaWNlY2FuZGlkYXRlID0gZnVuY3Rpb24oaWNlKSB7XG4gICAgICAgICAgICBpZiAoaWNlLmNhbmRpZGF0ZSkge1xuICAgICAgICAgICAgICAgIGhhbmRsZUNhbmRpZGF0ZShpY2UuY2FuZGlkYXRlLmNhbmRpZGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gY3JlYXRlIGRhdGEgY2hhbm5lbFxuICAgICAgICBpZiAoIXN0cmVhbSkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBwYy5jcmVhdGVEYXRhQ2hhbm5lbCgnc2N0cCcsIHt9KTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjcmVhdGUgYW4gb2ZmZXIgc2RwXG4gICAgICAgIGlmIChEZXRlY3RSVEMuaXNQcm9taXNlc1N1cHBvcnRlZCkge1xuICAgICAgICAgICAgcGMuY3JlYXRlT2ZmZXIoKS50aGVuKGZ1bmN0aW9uKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgIHBjLnNldExvY2FsRGVzY3JpcHRpb24ocmVzdWx0KS50aGVuKGFmdGVyQ3JlYXRlT2ZmZXIpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwYy5jcmVhdGVPZmZlcihmdW5jdGlvbihyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICBwYy5zZXRMb2NhbERlc2NyaXB0aW9uKHJlc3VsdCwgYWZ0ZXJDcmVhdGVPZmZlciwgZnVuY3Rpb24oKSB7fSk7XG4gICAgICAgICAgICB9LCBmdW5jdGlvbigpIHt9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGFmdGVyQ3JlYXRlT2ZmZXIoKSB7XG4gICAgICAgICAgICB2YXIgbGluZXMgPSBwYy5sb2NhbERlc2NyaXB0aW9uLnNkcC5zcGxpdCgnXFxuJyk7XG5cbiAgICAgICAgICAgIGxpbmVzLmZvckVhY2goZnVuY3Rpb24obGluZSkge1xuICAgICAgICAgICAgICAgIGlmIChsaW5lLmluZGV4T2YoJ2E9Y2FuZGlkYXRlOicpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhbmRsZUNhbmRpZGF0ZShsaW5lKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBNZWRpYURldmljZXMgPSBbXTtcblxuICAgIHZhciBhdWRpb0lucHV0RGV2aWNlcyA9IFtdO1xuICAgIHZhciBhdWRpb091dHB1dERldmljZXMgPSBbXTtcbiAgICB2YXIgdmlkZW9JbnB1dERldmljZXMgPSBbXTtcblxuICAgIGlmIChuYXZpZ2F0b3IubWVkaWFEZXZpY2VzICYmIG5hdmlnYXRvci5tZWRpYURldmljZXMuZW51bWVyYXRlRGV2aWNlcykge1xuICAgICAgICAvLyBGaXJlZm94IDM4KyBzZWVtcyBoYXZpbmcgc3VwcG9ydCBvZiBlbnVtZXJhdGVEZXZpY2VzXG4gICAgICAgIC8vIFRoYW5rcyBAeGR1bWFpbmUvZW51bWVyYXRlRGV2aWNlc1xuICAgICAgICBuYXZpZ2F0b3IuZW51bWVyYXRlRGV2aWNlcyA9IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICB2YXIgZW51bWVyYXRlRGV2aWNlcyA9IG5hdmlnYXRvci5tZWRpYURldmljZXMuZW51bWVyYXRlRGV2aWNlcygpO1xuICAgICAgICAgICAgaWYgKGVudW1lcmF0ZURldmljZXMgJiYgZW51bWVyYXRlRGV2aWNlcy50aGVuKSB7XG4gICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKCkudGhlbihjYWxsYmFjaykuY2F0Y2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKFtdKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIE1lZGlhIERldmljZXMgZGV0ZWN0aW9uXG4gICAgdmFyIGNhbkVudW1lcmF0ZSA9IGZhbHNlO1xuXG4gICAgLypnbG9iYWwgTWVkaWFTdHJlYW1UcmFjazp0cnVlICovXG4gICAgaWYgKHR5cGVvZiBNZWRpYVN0cmVhbVRyYWNrICE9PSAndW5kZWZpbmVkJyAmJiAnZ2V0U291cmNlcycgaW4gTWVkaWFTdHJlYW1UcmFjaykge1xuICAgICAgICBjYW5FbnVtZXJhdGUgPSB0cnVlO1xuICAgIH0gZWxzZSBpZiAobmF2aWdhdG9yLm1lZGlhRGV2aWNlcyAmJiAhIW5hdmlnYXRvci5tZWRpYURldmljZXMuZW51bWVyYXRlRGV2aWNlcykge1xuICAgICAgICBjYW5FbnVtZXJhdGUgPSB0cnVlO1xuICAgIH1cblxuICAgIHZhciBoYXNNaWNyb3Bob25lID0gZmFsc2U7XG4gICAgdmFyIGhhc1NwZWFrZXJzID0gZmFsc2U7XG4gICAgdmFyIGhhc1dlYmNhbSA9IGZhbHNlO1xuXG4gICAgdmFyIGlzV2Vic2l0ZUhhc01pY3JvcGhvbmVQZXJtaXNzaW9ucyA9IGZhbHNlO1xuICAgIHZhciBpc1dlYnNpdGVIYXNXZWJjYW1QZXJtaXNzaW9ucyA9IGZhbHNlO1xuXG4gICAgLy8gaHR0cDovL2Rldi53My5vcmcvMjAxMS93ZWJydGMvZWRpdG9yL2dldHVzZXJtZWRpYS5odG1sI21lZGlhZGV2aWNlc1xuICAgIGZ1bmN0aW9uIGNoZWNrRGV2aWNlU3VwcG9ydChjYWxsYmFjaykge1xuICAgICAgICBpZiAoIWNhbkVudW1lcmF0ZSkge1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghbmF2aWdhdG9yLmVudW1lcmF0ZURldmljZXMgJiYgd2luZG93Lk1lZGlhU3RyZWFtVHJhY2sgJiYgd2luZG93Lk1lZGlhU3RyZWFtVHJhY2suZ2V0U291cmNlcykge1xuICAgICAgICAgICAgbmF2aWdhdG9yLmVudW1lcmF0ZURldmljZXMgPSB3aW5kb3cuTWVkaWFTdHJlYW1UcmFjay5nZXRTb3VyY2VzLmJpbmQod2luZG93Lk1lZGlhU3RyZWFtVHJhY2spO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFuYXZpZ2F0b3IuZW51bWVyYXRlRGV2aWNlcyAmJiBuYXZpZ2F0b3IuZW51bWVyYXRlRGV2aWNlcykge1xuICAgICAgICAgICAgbmF2aWdhdG9yLmVudW1lcmF0ZURldmljZXMgPSBuYXZpZ2F0b3IuZW51bWVyYXRlRGV2aWNlcy5iaW5kKG5hdmlnYXRvcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIW5hdmlnYXRvci5lbnVtZXJhdGVEZXZpY2VzKSB7XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgTWVkaWFEZXZpY2VzID0gW107XG5cbiAgICAgICAgYXVkaW9JbnB1dERldmljZXMgPSBbXTtcbiAgICAgICAgYXVkaW9PdXRwdXREZXZpY2VzID0gW107XG4gICAgICAgIHZpZGVvSW5wdXREZXZpY2VzID0gW107XG5cbiAgICAgICAgaGFzTWljcm9waG9uZSA9IGZhbHNlO1xuICAgICAgICBoYXNTcGVha2VycyA9IGZhbHNlO1xuICAgICAgICBoYXNXZWJjYW0gPSBmYWxzZTtcblxuICAgICAgICBpc1dlYnNpdGVIYXNNaWNyb3Bob25lUGVybWlzc2lvbnMgPSBmYWxzZTtcbiAgICAgICAgaXNXZWJzaXRlSGFzV2ViY2FtUGVybWlzc2lvbnMgPSBmYWxzZTtcblxuICAgICAgICAvLyB0byBwcmV2ZW50IGR1cGxpY2F0aW9uXG4gICAgICAgIHZhciBhbHJlYWR5VXNlZERldmljZXMgPSB7fTtcblxuICAgICAgICBuYXZpZ2F0b3IuZW51bWVyYXRlRGV2aWNlcyhmdW5jdGlvbihkZXZpY2VzKSB7XG4gICAgICAgICAgICBkZXZpY2VzLmZvckVhY2goZnVuY3Rpb24oX2RldmljZSkge1xuICAgICAgICAgICAgICAgIHZhciBkZXZpY2UgPSB7fTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBkIGluIF9kZXZpY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgX2RldmljZVtkXSAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRldmljZVtkXSA9IF9kZXZpY2VbZF07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFscmVhZHlVc2VkRGV2aWNlc1tkZXZpY2UuZGV2aWNlSWQgKyBkZXZpY2UubGFiZWwgKyBkZXZpY2Uua2luZF0pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGlmIGl0IGlzIE1lZGlhU3RyZWFtVHJhY2suZ2V0U291cmNlc1xuICAgICAgICAgICAgICAgIGlmIChkZXZpY2Uua2luZCA9PT0gJ2F1ZGlvJykge1xuICAgICAgICAgICAgICAgICAgICBkZXZpY2Uua2luZCA9ICdhdWRpb2lucHV0JztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoZGV2aWNlLmtpbmQgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgZGV2aWNlLmtpbmQgPSAndmlkZW9pbnB1dCc7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFkZXZpY2UuZGV2aWNlSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgZGV2aWNlLmRldmljZUlkID0gZGV2aWNlLmlkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghZGV2aWNlLmlkKSB7XG4gICAgICAgICAgICAgICAgICAgIGRldmljZS5pZCA9IGRldmljZS5kZXZpY2VJZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIWRldmljZS5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICBkZXZpY2UuaXNDdXN0b21MYWJlbCA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGRldmljZS5raW5kID09PSAndmlkZW9pbnB1dCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRldmljZS5sYWJlbCA9ICdDYW1lcmEgJyArICh2aWRlb0lucHV0RGV2aWNlcy5sZW5ndGggKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkZXZpY2Uua2luZCA9PT0gJ2F1ZGlvaW5wdXQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXZpY2UubGFiZWwgPSAnTWljcm9waG9uZSAnICsgKGF1ZGlvSW5wdXREZXZpY2VzLmxlbmd0aCArIDEpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRldmljZS5raW5kID09PSAnYXVkaW9vdXRwdXQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXZpY2UubGFiZWwgPSAnU3BlYWtlciAnICsgKGF1ZGlvT3V0cHV0RGV2aWNlcy5sZW5ndGggKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRldmljZS5sYWJlbCA9ICdQbGVhc2UgaW52b2tlIGdldFVzZXJNZWRpYSBvbmNlLic7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIERldGVjdFJUQyAhPT0gJ3VuZGVmaW5lZCcgJiYgRGV0ZWN0UlRDLmJyb3dzZXIuaXNDaHJvbWUgJiYgRGV0ZWN0UlRDLmJyb3dzZXIudmVyc2lvbiA+PSA0NiAmJiAhL14oaHR0cHM6fGNocm9tZS1leHRlbnNpb246KSQvZy50ZXN0KGxvY2F0aW9uLnByb3RvY29sIHx8ICcnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGRvY3VtZW50LmRvbWFpbiA9PT0gJ3N0cmluZycgJiYgZG9jdW1lbnQuZG9tYWluLnNlYXJjaCAmJiBkb2N1bWVudC5kb21haW4uc2VhcmNoKC9sb2NhbGhvc3R8MTI3LjAuL2cpID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRldmljZS5sYWJlbCA9ICdIVFRQcyBpcyByZXF1aXJlZCB0byBnZXQgbGFiZWwgb2YgdGhpcyAnICsgZGV2aWNlLmtpbmQgKyAnIGRldmljZS4nO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCBvbiBBbmRyb2lkIHN0aWxsIHJldHVybnMgZW1wdHkgbGFiZWxcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRldmljZS5raW5kID09PSAndmlkZW9pbnB1dCcgJiYgIWlzV2Vic2l0ZUhhc1dlYmNhbVBlcm1pc3Npb25zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc1dlYnNpdGVIYXNXZWJjYW1QZXJtaXNzaW9ucyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoZGV2aWNlLmtpbmQgPT09ICdhdWRpb2lucHV0JyAmJiAhaXNXZWJzaXRlSGFzTWljcm9waG9uZVBlcm1pc3Npb25zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc1dlYnNpdGVIYXNNaWNyb3Bob25lUGVybWlzc2lvbnMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGRldmljZS5raW5kID09PSAnYXVkaW9pbnB1dCcpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzTWljcm9waG9uZSA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGF1ZGlvSW5wdXREZXZpY2VzLmluZGV4T2YoZGV2aWNlKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvSW5wdXREZXZpY2VzLnB1c2goZGV2aWNlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChkZXZpY2Uua2luZCA9PT0gJ2F1ZGlvb3V0cHV0Jykge1xuICAgICAgICAgICAgICAgICAgICBoYXNTcGVha2VycyA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGF1ZGlvT3V0cHV0RGV2aWNlcy5pbmRleE9mKGRldmljZSkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhdWRpb091dHB1dERldmljZXMucHVzaChkZXZpY2UpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGRldmljZS5raW5kID09PSAndmlkZW9pbnB1dCcpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzV2ViY2FtID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodmlkZW9JbnB1dERldmljZXMuaW5kZXhPZihkZXZpY2UpID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmlkZW9JbnB1dERldmljZXMucHVzaChkZXZpY2UpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gdGhlcmUgaXMgbm8gJ3ZpZGVvb3VwdXQnIGluIHRoZSBzcGVjLlxuICAgICAgICAgICAgICAgIE1lZGlhRGV2aWNlcy5wdXNoKGRldmljZSk7XG5cbiAgICAgICAgICAgICAgICBhbHJlYWR5VXNlZERldmljZXNbZGV2aWNlLmRldmljZUlkICsgZGV2aWNlLmxhYmVsICsgZGV2aWNlLmtpbmRdID0gZGV2aWNlO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgRGV0ZWN0UlRDICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIC8vIHRvIHN5bmMgbGF0ZXN0IG91dHB1dHNcbiAgICAgICAgICAgICAgICBEZXRlY3RSVEMuTWVkaWFEZXZpY2VzID0gTWVkaWFEZXZpY2VzO1xuICAgICAgICAgICAgICAgIERldGVjdFJUQy5oYXNNaWNyb3Bob25lID0gaGFzTWljcm9waG9uZTtcbiAgICAgICAgICAgICAgICBEZXRlY3RSVEMuaGFzU3BlYWtlcnMgPSBoYXNTcGVha2VycztcbiAgICAgICAgICAgICAgICBEZXRlY3RSVEMuaGFzV2ViY2FtID0gaGFzV2ViY2FtO1xuXG4gICAgICAgICAgICAgICAgRGV0ZWN0UlRDLmlzV2Vic2l0ZUhhc1dlYmNhbVBlcm1pc3Npb25zID0gaXNXZWJzaXRlSGFzV2ViY2FtUGVybWlzc2lvbnM7XG4gICAgICAgICAgICAgICAgRGV0ZWN0UlRDLmlzV2Vic2l0ZUhhc01pY3JvcGhvbmVQZXJtaXNzaW9ucyA9IGlzV2Vic2l0ZUhhc01pY3JvcGhvbmVQZXJtaXNzaW9ucztcblxuICAgICAgICAgICAgICAgIERldGVjdFJUQy5hdWRpb0lucHV0RGV2aWNlcyA9IGF1ZGlvSW5wdXREZXZpY2VzO1xuICAgICAgICAgICAgICAgIERldGVjdFJUQy5hdWRpb091dHB1dERldmljZXMgPSBhdWRpb091dHB1dERldmljZXM7XG4gICAgICAgICAgICAgICAgRGV0ZWN0UlRDLnZpZGVvSW5wdXREZXZpY2VzID0gdmlkZW9JbnB1dERldmljZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHZhciBEZXRlY3RSVEMgPSB3aW5kb3cuRGV0ZWN0UlRDIHx8IHt9O1xuXG4gICAgLy8gLS0tLS0tLS0tLVxuICAgIC8vIERldGVjdFJUQy5icm93c2VyLm5hbWUgfHwgRGV0ZWN0UlRDLmJyb3dzZXIudmVyc2lvbiB8fCBEZXRlY3RSVEMuYnJvd3Nlci5mdWxsVmVyc2lvblxuICAgIERldGVjdFJUQy5icm93c2VyID0gZ2V0QnJvd3NlckluZm8oKTtcblxuICAgIGRldGVjdFByaXZhdGVNb2RlKGZ1bmN0aW9uKGlzUHJpdmF0ZUJyb3dzaW5nKSB7XG4gICAgICAgIERldGVjdFJUQy5icm93c2VyLmlzUHJpdmF0ZUJyb3dzaW5nID0gISFpc1ByaXZhdGVCcm93c2luZztcbiAgICB9KTtcblxuICAgIC8vIERldGVjdFJUQy5pc0Nocm9tZSB8fCBEZXRlY3RSVEMuaXNGaXJlZm94IHx8IERldGVjdFJUQy5pc0VkZ2VcbiAgICBEZXRlY3RSVEMuYnJvd3NlclsnaXMnICsgRGV0ZWN0UlRDLmJyb3dzZXIubmFtZV0gPSB0cnVlO1xuXG4gICAgLy8gLS0tLS0tLS0tLS1cbiAgICBEZXRlY3RSVEMub3NOYW1lID0gb3NOYW1lO1xuICAgIERldGVjdFJUQy5vc1ZlcnNpb24gPSBvc1ZlcnNpb247XG5cbiAgICB2YXIgaXNOb2RlV2Via2l0ID0gdHlwZW9mIHByb2Nlc3MgPT09ICdvYmplY3QnICYmIHR5cGVvZiBwcm9jZXNzLnZlcnNpb25zID09PSAnb2JqZWN0JyAmJiBwcm9jZXNzLnZlcnNpb25zWydub2RlLXdlYmtpdCddO1xuXG4gICAgLy8gLS0tLS0tLS0tIERldGVjdCBpZiBzeXN0ZW0gc3VwcG9ydHMgV2ViUlRDIDEuMCBvciBXZWJSVEMgMS4xLlxuICAgIHZhciBpc1dlYlJUQ1N1cHBvcnRlZCA9IGZhbHNlO1xuICAgIFsnUlRDUGVlckNvbm5lY3Rpb24nLCAnd2Via2l0UlRDUGVlckNvbm5lY3Rpb24nLCAnbW96UlRDUGVlckNvbm5lY3Rpb24nLCAnUlRDSWNlR2F0aGVyZXInXS5mb3JFYWNoKGZ1bmN0aW9uKGl0ZW0pIHtcbiAgICAgICAgaWYgKGlzV2ViUlRDU3VwcG9ydGVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaXRlbSBpbiB3aW5kb3cpIHtcbiAgICAgICAgICAgIGlzV2ViUlRDU3VwcG9ydGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIERldGVjdFJUQy5pc1dlYlJUQ1N1cHBvcnRlZCA9IGlzV2ViUlRDU3VwcG9ydGVkO1xuXG4gICAgLy8tLS0tLS0tXG4gICAgRGV0ZWN0UlRDLmlzT1JUQ1N1cHBvcnRlZCA9IHR5cGVvZiBSVENJY2VHYXRoZXJlciAhPT0gJ3VuZGVmaW5lZCc7XG5cbiAgICAvLyAtLS0tLS0tLS0gRGV0ZWN0IGlmIFdlYkF1ZGlvIEFQSSBhcmUgc3VwcG9ydGVkXG4gICAgdmFyIHdlYkF1ZGlvID0ge1xuICAgICAgICBpc1N1cHBvcnRlZDogZmFsc2UsXG4gICAgICAgIGlzQ3JlYXRlTWVkaWFTdHJlYW1Tb3VyY2VTdXBwb3J0ZWQ6IGZhbHNlXG4gICAgfTtcblxuICAgIFsnQXVkaW9Db250ZXh0JywgJ3dlYmtpdEF1ZGlvQ29udGV4dCcsICdtb3pBdWRpb0NvbnRleHQnLCAnbXNBdWRpb0NvbnRleHQnXS5mb3JFYWNoKGZ1bmN0aW9uKGl0ZW0pIHtcbiAgICAgICAgaWYgKHdlYkF1ZGlvLmlzU3VwcG9ydGVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaXRlbSBpbiB3aW5kb3cpIHtcbiAgICAgICAgICAgIHdlYkF1ZGlvLmlzU3VwcG9ydGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgaWYgKHdpbmRvd1tpdGVtXSAmJiAnY3JlYXRlTWVkaWFTdHJlYW1Tb3VyY2UnIGluIHdpbmRvd1tpdGVtXS5wcm90b3R5cGUpIHtcbiAgICAgICAgICAgICAgICB3ZWJBdWRpby5pc0NyZWF0ZU1lZGlhU3RyZWFtU291cmNlU3VwcG9ydGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xuICAgIERldGVjdFJUQy5pc0F1ZGlvQ29udGV4dFN1cHBvcnRlZCA9IHdlYkF1ZGlvLmlzU3VwcG9ydGVkO1xuICAgIERldGVjdFJUQy5pc0NyZWF0ZU1lZGlhU3RyZWFtU291cmNlU3VwcG9ydGVkID0gd2ViQXVkaW8uaXNDcmVhdGVNZWRpYVN0cmVhbVNvdXJjZVN1cHBvcnRlZDtcblxuICAgIC8vIC0tLS0tLS0tLS0gRGV0ZWN0IGlmIFNDVFAvUlRQIGNoYW5uZWxzIGFyZSBzdXBwb3J0ZWQuXG5cbiAgICB2YXIgaXNSdHBEYXRhQ2hhbm5lbHNTdXBwb3J0ZWQgPSBmYWxzZTtcbiAgICBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIuaXNDaHJvbWUgJiYgRGV0ZWN0UlRDLmJyb3dzZXIudmVyc2lvbiA+IDMxKSB7XG4gICAgICAgIGlzUnRwRGF0YUNoYW5uZWxzU3VwcG9ydGVkID0gdHJ1ZTtcbiAgICB9XG4gICAgRGV0ZWN0UlRDLmlzUnRwRGF0YUNoYW5uZWxzU3VwcG9ydGVkID0gaXNSdHBEYXRhQ2hhbm5lbHNTdXBwb3J0ZWQ7XG5cbiAgICB2YXIgaXNTQ1RQU3VwcG9ydGQgPSBmYWxzZTtcbiAgICBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIuaXNGaXJlZm94ICYmIERldGVjdFJUQy5icm93c2VyLnZlcnNpb24gPiAyOCkge1xuICAgICAgICBpc1NDVFBTdXBwb3J0ZCA9IHRydWU7XG4gICAgfSBlbHNlIGlmIChEZXRlY3RSVEMuYnJvd3Nlci5pc0Nocm9tZSAmJiBEZXRlY3RSVEMuYnJvd3Nlci52ZXJzaW9uID4gMjUpIHtcbiAgICAgICAgaXNTQ1RQU3VwcG9ydGQgPSB0cnVlO1xuICAgIH0gZWxzZSBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIuaXNPcGVyYSAmJiBEZXRlY3RSVEMuYnJvd3Nlci52ZXJzaW9uID49IDExKSB7XG4gICAgICAgIGlzU0NUUFN1cHBvcnRkID0gdHJ1ZTtcbiAgICB9XG4gICAgRGV0ZWN0UlRDLmlzU2N0cERhdGFDaGFubmVsc1N1cHBvcnRlZCA9IGlzU0NUUFN1cHBvcnRkO1xuXG4gICAgLy8gLS0tLS0tLS0tXG5cbiAgICBEZXRlY3RSVEMuaXNNb2JpbGVEZXZpY2UgPSBpc01vYmlsZURldmljZTsgLy8gXCJpc01vYmlsZURldmljZVwiIGJvb2xlYW4gaXMgZGVmaW5lZCBpbiBcImdldEJyb3dzZXJJbmZvLmpzXCJcblxuICAgIC8vIC0tLS0tLVxuICAgIHZhciBpc0dldFVzZXJNZWRpYVN1cHBvcnRlZCA9IGZhbHNlO1xuICAgIGlmIChuYXZpZ2F0b3IuZ2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGlzR2V0VXNlck1lZGlhU3VwcG9ydGVkID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKG5hdmlnYXRvci5tZWRpYURldmljZXMgJiYgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEpIHtcbiAgICAgICAgaXNHZXRVc2VyTWVkaWFTdXBwb3J0ZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIGlmIChEZXRlY3RSVEMuYnJvd3Nlci5pc0Nocm9tZSAmJiBEZXRlY3RSVEMuYnJvd3Nlci52ZXJzaW9uID49IDQ2ICYmICEvXihodHRwczp8Y2hyb21lLWV4dGVuc2lvbjopJC9nLnRlc3QobG9jYXRpb24ucHJvdG9jb2wgfHwgJycpKSB7XG4gICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBkb2N1bWVudC5kb21haW4gPT09ICdzdHJpbmcnICYmIGRvY3VtZW50LmRvbWFpbi5zZWFyY2ggJiYgZG9jdW1lbnQuZG9tYWluLnNlYXJjaCgvbG9jYWxob3N0fDEyNy4wLi9nKSA9PT0gLTEpIHtcbiAgICAgICAgICAgIGlzR2V0VXNlck1lZGlhU3VwcG9ydGVkID0gJ1JlcXVpcmVzIEhUVFBzJztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmIChEZXRlY3RSVEMub3NOYW1lID09PSAnTm9kZWpzJykge1xuICAgICAgICBpc0dldFVzZXJNZWRpYVN1cHBvcnRlZCA9IGZhbHNlO1xuICAgIH1cbiAgICBEZXRlY3RSVEMuaXNHZXRVc2VyTWVkaWFTdXBwb3J0ZWQgPSBpc0dldFVzZXJNZWRpYVN1cHBvcnRlZDtcblxuICAgIHZhciBkaXNwbGF5UmVzb2x1dGlvbiA9ICcnO1xuICAgIGlmIChzY3JlZW4ud2lkdGgpIHtcbiAgICAgICAgdmFyIHdpZHRoID0gKHNjcmVlbi53aWR0aCkgPyBzY3JlZW4ud2lkdGggOiAnJztcbiAgICAgICAgdmFyIGhlaWdodCA9IChzY3JlZW4uaGVpZ2h0KSA/IHNjcmVlbi5oZWlnaHQgOiAnJztcbiAgICAgICAgZGlzcGxheVJlc29sdXRpb24gKz0gJycgKyB3aWR0aCArICcgeCAnICsgaGVpZ2h0O1xuICAgIH1cbiAgICBEZXRlY3RSVEMuZGlzcGxheVJlc29sdXRpb24gPSBkaXNwbGF5UmVzb2x1dGlvbjtcblxuICAgIGZ1bmN0aW9uIGdldEFzcGVjdFJhdGlvKHcsIGgpIHtcbiAgICAgICAgZnVuY3Rpb24gZ2NkKGEsIGIpIHtcbiAgICAgICAgICAgIHJldHVybiAoYiA9PSAwKSA/IGEgOiBnY2QoYiwgYSAlIGIpO1xuICAgICAgICB9XG4gICAgICAgIHZhciByID0gZ2NkKHcsIGgpO1xuICAgICAgICByZXR1cm4gKHcgLyByKSAvIChoIC8gcik7XG4gICAgfVxuXG4gICAgRGV0ZWN0UlRDLmRpc3BsYXlBc3BlY3RSYXRpbyA9IGdldEFzcGVjdFJhdGlvKHNjcmVlbi53aWR0aCwgc2NyZWVuLmhlaWdodCkudG9GaXhlZCgyKTtcblxuICAgIC8vIC0tLS0tLS0tLS1cbiAgICBEZXRlY3RSVEMuaXNDYW52YXNTdXBwb3J0c1N0cmVhbUNhcHR1cmluZyA9IGlzQ2FudmFzU3VwcG9ydHNTdHJlYW1DYXB0dXJpbmc7XG4gICAgRGV0ZWN0UlRDLmlzVmlkZW9TdXBwb3J0c1N0cmVhbUNhcHR1cmluZyA9IGlzVmlkZW9TdXBwb3J0c1N0cmVhbUNhcHR1cmluZztcblxuICAgIGlmIChEZXRlY3RSVEMuYnJvd3Nlci5uYW1lID09ICdDaHJvbWUnICYmIERldGVjdFJUQy5icm93c2VyLnZlcnNpb24gPj0gNTMpIHtcbiAgICAgICAgaWYgKCFEZXRlY3RSVEMuaXNDYW52YXNTdXBwb3J0c1N0cmVhbUNhcHR1cmluZykge1xuICAgICAgICAgICAgRGV0ZWN0UlRDLmlzQ2FudmFzU3VwcG9ydHNTdHJlYW1DYXB0dXJpbmcgPSAnUmVxdWlyZXMgY2hyb21lIGZsYWc6IGVuYWJsZS1leHBlcmltZW50YWwtd2ViLXBsYXRmb3JtLWZlYXR1cmVzJztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghRGV0ZWN0UlRDLmlzVmlkZW9TdXBwb3J0c1N0cmVhbUNhcHR1cmluZykge1xuICAgICAgICAgICAgRGV0ZWN0UlRDLmlzVmlkZW9TdXBwb3J0c1N0cmVhbUNhcHR1cmluZyA9ICdSZXF1aXJlcyBjaHJvbWUgZmxhZzogZW5hYmxlLWV4cGVyaW1lbnRhbC13ZWItcGxhdGZvcm0tZmVhdHVyZXMnO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gLS0tLS0tXG4gICAgRGV0ZWN0UlRDLkRldGVjdExvY2FsSVBBZGRyZXNzID0gRGV0ZWN0TG9jYWxJUEFkZHJlc3M7XG5cbiAgICBEZXRlY3RSVEMuaXNXZWJTb2NrZXRzU3VwcG9ydGVkID0gJ1dlYlNvY2tldCcgaW4gd2luZG93ICYmIDIgPT09IHdpbmRvdy5XZWJTb2NrZXQuQ0xPU0lORztcbiAgICBEZXRlY3RSVEMuaXNXZWJTb2NrZXRzQmxvY2tlZCA9ICFEZXRlY3RSVEMuaXNXZWJTb2NrZXRzU3VwcG9ydGVkO1xuXG4gICAgaWYgKERldGVjdFJUQy5vc05hbWUgPT09ICdOb2RlanMnKSB7XG4gICAgICAgIERldGVjdFJUQy5pc1dlYlNvY2tldHNTdXBwb3J0ZWQgPSB0cnVlO1xuICAgICAgICBEZXRlY3RSVEMuaXNXZWJTb2NrZXRzQmxvY2tlZCA9IGZhbHNlO1xuICAgIH1cblxuICAgIERldGVjdFJUQy5jaGVja1dlYlNvY2tldHNTdXBwb3J0ID0gZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICAgICAgY2FsbGJhY2sgPSBjYWxsYmFjayB8fCBmdW5jdGlvbigpIHt9O1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgdmFyIHN0YXJ0dGltZTtcbiAgICAgICAgICAgIHZhciB3ZWJzb2NrZXQgPSBuZXcgV2ViU29ja2V0KCd3c3M6Ly9lY2hvLndlYnNvY2tldC5vcmc6NDQzLycpO1xuICAgICAgICAgICAgd2Vic29ja2V0Lm9ub3BlbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIERldGVjdFJUQy5pc1dlYlNvY2tldHNCbG9ja2VkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgc3RhcnR0aW1lID0gKG5ldyBEYXRlKS5nZXRUaW1lKCk7XG4gICAgICAgICAgICAgICAgd2Vic29ja2V0LnNlbmQoJ3BpbmcnKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB3ZWJzb2NrZXQub25tZXNzYWdlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgRGV0ZWN0UlRDLldlYnNvY2tldExhdGVuY3kgPSAobmV3IERhdGUpLmdldFRpbWUoKSAtIHN0YXJ0dGltZSArICdtcyc7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICB3ZWJzb2NrZXQuY2xvc2UoKTtcbiAgICAgICAgICAgICAgICB3ZWJzb2NrZXQgPSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHdlYnNvY2tldC5vbmVycm9yID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgRGV0ZWN0UlRDLmlzV2ViU29ja2V0c0Jsb2NrZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBEZXRlY3RSVEMuaXNXZWJTb2NrZXRzQmxvY2tlZCA9IHRydWU7XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8vIC0tLS0tLS1cbiAgICBEZXRlY3RSVEMubG9hZCA9IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgfHwgZnVuY3Rpb24oKSB7fTtcbiAgICAgICAgY2hlY2tEZXZpY2VTdXBwb3J0KGNhbGxiYWNrKTtcbiAgICB9O1xuXG4gICAgLy8gY2hlY2sgZm9yIG1pY3JvcGhvbmUvY2FtZXJhIHN1cHBvcnQhXG4gICAgaWYgKHR5cGVvZiBjaGVja0RldmljZVN1cHBvcnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgLy8gY2hlY2tEZXZpY2VTdXBwb3J0KCk7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBNZWRpYURldmljZXMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIERldGVjdFJUQy5NZWRpYURldmljZXMgPSBNZWRpYURldmljZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgRGV0ZWN0UlRDLk1lZGlhRGV2aWNlcyA9IFtdO1xuICAgIH1cblxuICAgIERldGVjdFJUQy5oYXNNaWNyb3Bob25lID0gaGFzTWljcm9waG9uZTtcbiAgICBEZXRlY3RSVEMuaGFzU3BlYWtlcnMgPSBoYXNTcGVha2VycztcbiAgICBEZXRlY3RSVEMuaGFzV2ViY2FtID0gaGFzV2ViY2FtO1xuXG4gICAgRGV0ZWN0UlRDLmlzV2Vic2l0ZUhhc1dlYmNhbVBlcm1pc3Npb25zID0gaXNXZWJzaXRlSGFzV2ViY2FtUGVybWlzc2lvbnM7XG4gICAgRGV0ZWN0UlRDLmlzV2Vic2l0ZUhhc01pY3JvcGhvbmVQZXJtaXNzaW9ucyA9IGlzV2Vic2l0ZUhhc01pY3JvcGhvbmVQZXJtaXNzaW9ucztcblxuICAgIERldGVjdFJUQy5hdWRpb0lucHV0RGV2aWNlcyA9IGF1ZGlvSW5wdXREZXZpY2VzO1xuICAgIERldGVjdFJUQy5hdWRpb091dHB1dERldmljZXMgPSBhdWRpb091dHB1dERldmljZXM7XG4gICAgRGV0ZWN0UlRDLnZpZGVvSW5wdXREZXZpY2VzID0gdmlkZW9JbnB1dERldmljZXM7XG5cbiAgICAvLyAtLS0tLS1cbiAgICB2YXIgaXNTZXRTaW5rSWRTdXBwb3J0ZWQgPSBmYWxzZTtcbiAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgZG9jdW1lbnQuY3JlYXRlRWxlbWVudCA9PT0gJ2Z1bmN0aW9uJyAmJiAnc2V0U2lua0lkJyBpbiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpKSB7XG4gICAgICAgIGlzU2V0U2lua0lkU3VwcG9ydGVkID0gdHJ1ZTtcbiAgICB9XG4gICAgRGV0ZWN0UlRDLmlzU2V0U2lua0lkU3VwcG9ydGVkID0gaXNTZXRTaW5rSWRTdXBwb3J0ZWQ7XG5cbiAgICAvLyAtLS0tLVxuICAgIHZhciBpc1JUUFNlbmRlclJlcGxhY2VUcmFja3NTdXBwb3J0ZWQgPSBmYWxzZTtcbiAgICBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIuaXNGaXJlZm94ICYmIHR5cGVvZiBtb3pSVENQZWVyQ29ubmVjdGlvbiAhPT0gJ3VuZGVmaW5lZCcgLyomJiBEZXRlY3RSVEMuYnJvd3Nlci52ZXJzaW9uID4gMzkqLyApIHtcbiAgICAgICAgLypnbG9iYWwgbW96UlRDUGVlckNvbm5lY3Rpb246dHJ1ZSAqL1xuICAgICAgICBpZiAoJ2dldFNlbmRlcnMnIGluIG1velJUQ1BlZXJDb25uZWN0aW9uLnByb3RvdHlwZSkge1xuICAgICAgICAgICAgaXNSVFBTZW5kZXJSZXBsYWNlVHJhY2tzU3VwcG9ydGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIuaXNDaHJvbWUgJiYgdHlwZW9mIHdlYmtpdFJUQ1BlZXJDb25uZWN0aW9uICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAvKmdsb2JhbCB3ZWJraXRSVENQZWVyQ29ubmVjdGlvbjp0cnVlICovXG4gICAgICAgIGlmICgnZ2V0U2VuZGVycycgaW4gd2Via2l0UlRDUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlKSB7XG4gICAgICAgICAgICBpc1JUUFNlbmRlclJlcGxhY2VUcmFja3NTdXBwb3J0ZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIERldGVjdFJUQy5pc1JUUFNlbmRlclJlcGxhY2VUcmFja3NTdXBwb3J0ZWQgPSBpc1JUUFNlbmRlclJlcGxhY2VUcmFja3NTdXBwb3J0ZWQ7XG5cbiAgICAvLy0tLS0tLVxuICAgIHZhciBpc1JlbW90ZVN0cmVhbVByb2Nlc3NpbmdTdXBwb3J0ZWQgPSBmYWxzZTtcbiAgICBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIuaXNGaXJlZm94ICYmIERldGVjdFJUQy5icm93c2VyLnZlcnNpb24gPiAzOCkge1xuICAgICAgICBpc1JlbW90ZVN0cmVhbVByb2Nlc3NpbmdTdXBwb3J0ZWQgPSB0cnVlO1xuICAgIH1cbiAgICBEZXRlY3RSVEMuaXNSZW1vdGVTdHJlYW1Qcm9jZXNzaW5nU3VwcG9ydGVkID0gaXNSZW1vdGVTdHJlYW1Qcm9jZXNzaW5nU3VwcG9ydGVkO1xuXG4gICAgLy8tLS0tLS0tXG4gICAgdmFyIGlzQXBwbHlDb25zdHJhaW50c1N1cHBvcnRlZCA9IGZhbHNlO1xuXG4gICAgLypnbG9iYWwgTWVkaWFTdHJlYW1UcmFjazp0cnVlICovXG4gICAgaWYgKHR5cGVvZiBNZWRpYVN0cmVhbVRyYWNrICE9PSAndW5kZWZpbmVkJyAmJiAnYXBwbHlDb25zdHJhaW50cycgaW4gTWVkaWFTdHJlYW1UcmFjay5wcm90b3R5cGUpIHtcbiAgICAgICAgaXNBcHBseUNvbnN0cmFpbnRzU3VwcG9ydGVkID0gdHJ1ZTtcbiAgICB9XG4gICAgRGV0ZWN0UlRDLmlzQXBwbHlDb25zdHJhaW50c1N1cHBvcnRlZCA9IGlzQXBwbHlDb25zdHJhaW50c1N1cHBvcnRlZDtcblxuICAgIC8vLS0tLS0tLVxuICAgIHZhciBpc011bHRpTW9uaXRvclNjcmVlbkNhcHR1cmluZ1N1cHBvcnRlZCA9IGZhbHNlO1xuICAgIGlmIChEZXRlY3RSVEMuYnJvd3Nlci5pc0ZpcmVmb3ggJiYgRGV0ZWN0UlRDLmJyb3dzZXIudmVyc2lvbiA+PSA0Mykge1xuICAgICAgICAvLyB2ZXJzaW9uIDQzIG1lcmVseSBzdXBwb3J0cyBwbGF0Zm9ybXMgZm9yIG11bHRpLW1vbml0b3JzXG4gICAgICAgIC8vIHZlcnNpb24gNDQgd2lsbCBzdXBwb3J0IGV4YWN0IG11bHRpLW1vbml0b3Igc2VsZWN0aW9uIGkuZS4geW91IGNhbiBzZWxlY3QgYW55IG1vbml0b3IgZm9yIHNjcmVlbiBjYXB0dXJpbmcuXG4gICAgICAgIGlzTXVsdGlNb25pdG9yU2NyZWVuQ2FwdHVyaW5nU3VwcG9ydGVkID0gdHJ1ZTtcbiAgICB9XG4gICAgRGV0ZWN0UlRDLmlzTXVsdGlNb25pdG9yU2NyZWVuQ2FwdHVyaW5nU3VwcG9ydGVkID0gaXNNdWx0aU1vbml0b3JTY3JlZW5DYXB0dXJpbmdTdXBwb3J0ZWQ7XG5cbiAgICBEZXRlY3RSVEMuaXNQcm9taXNlc1N1cHBvcnRlZCA9ICEhKCdQcm9taXNlJyBpbiB3aW5kb3cpO1xuXG4gICAgaWYgKHR5cGVvZiBEZXRlY3RSVEMgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHdpbmRvdy5EZXRlY3RSVEMgPSB7fTtcbiAgICB9XG5cbiAgICB2YXIgTWVkaWFTdHJlYW0gPSB3aW5kb3cuTWVkaWFTdHJlYW07XG5cbiAgICBpZiAodHlwZW9mIE1lZGlhU3RyZWFtID09PSAndW5kZWZpbmVkJyAmJiB0eXBlb2Ygd2Via2l0TWVkaWFTdHJlYW0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIE1lZGlhU3RyZWFtID0gd2Via2l0TWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBNZWRpYVN0cmVhbSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgRGV0ZWN0UlRDLk1lZGlhU3RyZWFtID0gT2JqZWN0LmtleXMoTWVkaWFTdHJlYW0ucHJvdG90eXBlKTtcbiAgICB9IGVsc2UgRGV0ZWN0UlRDLk1lZGlhU3RyZWFtID0gZmFsc2U7XG5cbiAgICBpZiAodHlwZW9mIE1lZGlhU3RyZWFtVHJhY2sgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIERldGVjdFJUQy5NZWRpYVN0cmVhbVRyYWNrID0gT2JqZWN0LmtleXMoTWVkaWFTdHJlYW1UcmFjay5wcm90b3R5cGUpO1xuICAgIH0gZWxzZSBEZXRlY3RSVEMuTWVkaWFTdHJlYW1UcmFjayA9IGZhbHNlO1xuXG4gICAgdmFyIFJUQ1BlZXJDb25uZWN0aW9uID0gd2luZG93LlJUQ1BlZXJDb25uZWN0aW9uIHx8IHdpbmRvdy5tb3pSVENQZWVyQ29ubmVjdGlvbiB8fCB3aW5kb3cud2Via2l0UlRDUGVlckNvbm5lY3Rpb247XG5cbiAgICBpZiAodHlwZW9mIFJUQ1BlZXJDb25uZWN0aW9uICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBEZXRlY3RSVEMuUlRDUGVlckNvbm5lY3Rpb24gPSBPYmplY3Qua2V5cyhSVENQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUpO1xuICAgIH0gZWxzZSBEZXRlY3RSVEMuUlRDUGVlckNvbm5lY3Rpb24gPSBmYWxzZTtcblxuICAgIHdpbmRvdy5EZXRlY3RSVEMgPSBEZXRlY3RSVEM7XG5cbiAgICBpZiAodHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgLyogJiYgISFtb2R1bGUuZXhwb3J0cyovICkge1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IERldGVjdFJUQztcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZSgnRGV0ZWN0UlRDJywgW10sIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIERldGVjdFJUQztcbiAgICAgICAgfSk7XG4gICAgfVxufSkoKTsiLCJmdW5jdGlvbiBNYXBwZXIoKVxue1xuICB2YXIgc291cmNlcyA9IHt9O1xuXG5cbiAgdGhpcy5mb3JFYWNoID0gZnVuY3Rpb24oY2FsbGJhY2spXG4gIHtcbiAgICBmb3IodmFyIGtleSBpbiBzb3VyY2VzKVxuICAgIHtcbiAgICAgIHZhciBzb3VyY2UgPSBzb3VyY2VzW2tleV07XG5cbiAgICAgIGZvcih2YXIga2V5MiBpbiBzb3VyY2UpXG4gICAgICAgIGNhbGxiYWNrKHNvdXJjZVtrZXkyXSk7XG4gICAgfTtcbiAgfTtcblxuICB0aGlzLmdldCA9IGZ1bmN0aW9uKGlkLCBzb3VyY2UpXG4gIHtcbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuXG4gICAgcmV0dXJuIGlkc1tpZF07XG4gIH07XG5cbiAgdGhpcy5yZW1vdmUgPSBmdW5jdGlvbihpZCwgc291cmNlKVxuICB7XG4gICAgdmFyIGlkcyA9IHNvdXJjZXNbc291cmNlXTtcbiAgICBpZihpZHMgPT0gdW5kZWZpbmVkKVxuICAgICAgcmV0dXJuO1xuXG4gICAgZGVsZXRlIGlkc1tpZF07XG5cbiAgICAvLyBDaGVjayBpdCdzIGVtcHR5XG4gICAgZm9yKHZhciBpIGluIGlkcyl7cmV0dXJuIGZhbHNlfVxuXG4gICAgZGVsZXRlIHNvdXJjZXNbc291cmNlXTtcbiAgfTtcblxuICB0aGlzLnNldCA9IGZ1bmN0aW9uKHZhbHVlLCBpZCwgc291cmNlKVxuICB7XG4gICAgaWYodmFsdWUgPT0gdW5kZWZpbmVkKVxuICAgICAgcmV0dXJuIHRoaXMucmVtb3ZlKGlkLCBzb3VyY2UpO1xuXG4gICAgdmFyIGlkcyA9IHNvdXJjZXNbc291cmNlXTtcbiAgICBpZihpZHMgPT0gdW5kZWZpbmVkKVxuICAgICAgc291cmNlc1tzb3VyY2VdID0gaWRzID0ge307XG5cbiAgICBpZHNbaWRdID0gdmFsdWU7XG4gIH07XG59O1xuXG5cbk1hcHBlci5wcm90b3R5cGUucG9wID0gZnVuY3Rpb24oaWQsIHNvdXJjZSlcbntcbiAgdmFyIHZhbHVlID0gdGhpcy5nZXQoaWQsIHNvdXJjZSk7XG4gIGlmKHZhbHVlID09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuXG4gIHRoaXMucmVtb3ZlKGlkLCBzb3VyY2UpO1xuXG4gIHJldHVybiB2YWx1ZTtcbn07XG5cblxubW9kdWxlLmV4cG9ydHMgPSBNYXBwZXI7XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIEpzb25ScGNDbGllbnQgID0gcmVxdWlyZSgnLi9qc29ucnBjY2xpZW50Jyk7XG5cblxuZXhwb3J0cy5Kc29uUnBjQ2xpZW50ICA9IEpzb25ScGNDbGllbnQ7IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBScGNCdWlsZGVyID0gcmVxdWlyZSgnLi4vJyk7XG52YXIgV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbiA9IHJlcXVpcmUoJy4vdHJhbnNwb3J0cy93ZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uJyk7XG5cbkRhdGUubm93ID0gRGF0ZS5ub3cgfHwgZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuICtuZXcgRGF0ZTtcbn07XG5cbnZhciBQSU5HX0lOVEVSVkFMID0gNTAwMDtcblxudmFyIFJFQ09OTkVDVElORyA9ICdSRUNPTk5FQ1RJTkcnO1xudmFyIENPTk5FQ1RFRCA9ICdDT05ORUNURUQnO1xudmFyIERJU0NPTk5FQ1RFRCA9ICdESVNDT05ORUNURUQnO1xuXG52YXIgTG9nZ2VyID0gY29uc29sZTtcblxuLyoqXG4gKlxuICogaGVhcnRiZWF0OiBpbnRlcnZhbCBpbiBtcyBmb3IgZWFjaCBoZWFydGJlYXQgbWVzc2FnZSxcbiAqIHNlbmRDbG9zZU1lc3NhZ2UgOiB0cnVlIC8gZmFsc2UsIGJlZm9yZSBjbG9zaW5nIHRoZSBjb25uZWN0aW9uLCBpdCBzZW5kcyBhIGNsb3NlU2Vzc2lvbiBtZXNzYWdlXG4gKiA8cHJlPlxuICogd3MgOiB7XG4gKiBcdHVyaSA6IFVSSSB0byBjb25udGVjdCB0byxcbiAqICB1c2VTb2NrSlMgOiB0cnVlICh1c2UgU29ja0pTKSAvIGZhbHNlICh1c2UgV2ViU29ja2V0KSBieSBkZWZhdWx0LFxuICogXHRvbmNvbm5lY3RlZCA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiBjb25uZWN0aW9uIGlzIHN1Y2Nlc3NmdWwsXG4gKiBcdG9uZGlzY29ubmVjdCA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY29ubmVjdGlvbiBpcyBsb3N0LFxuICogXHRvbnJlY29ubmVjdGluZyA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY2xpZW50IGlzIHJlY29ubmVjdGluZyxcbiAqIFx0b25yZWNvbm5lY3RlZCA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY2xpZW50IHN1Y2Nlc2Z1bGx5IHJlY29ubmVjdHMsXG4gKiBcdG9uZXJyb3IgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlcmUgaXMgYW4gZXJyb3JcbiAqIH0sXG4gKiBycGMgOiB7XG4gKiBcdHJlcXVlc3RUaW1lb3V0IDogdGltZW91dCBmb3IgYSByZXF1ZXN0LFxuICogXHRzZXNzaW9uU3RhdHVzQ2hhbmdlZDogY2FsbGJhY2sgbWV0aG9kIGZvciBjaGFuZ2VzIGluIHNlc3Npb24gc3RhdHVzLFxuICogXHRtZWRpYVJlbmVnb3RpYXRpb246IG1lZGlhUmVuZWdvdGlhdGlvblxuICogfVxuICogPC9wcmU+XG4gKi9cbmZ1bmN0aW9uIEpzb25ScGNDbGllbnQoY29uZmlndXJhdGlvbikge1xuXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdmFyIHdzQ29uZmlnID0gY29uZmlndXJhdGlvbi53cztcblxuICAgIHZhciBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gLTE7XG5cbiAgICB2YXIgcGluZ05leHROdW0gPSAwO1xuICAgIHZhciBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgIHZhciBwaW5nUG9uZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICB2YXIgcGluZ0ludGVydmFsO1xuXG4gICAgdmFyIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgIHZhciBvbnJlY29ubmVjdGluZyA9IHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nO1xuICAgIHZhciBvbnJlY29ubmVjdGVkID0gd3NDb25maWcub25yZWNvbm5lY3RlZDtcbiAgICB2YXIgb25jb25uZWN0ZWQgPSB3c0NvbmZpZy5vbmNvbm5lY3RlZDtcbiAgICB2YXIgb25lcnJvciA9IHdzQ29uZmlnLm9uZXJyb3I7XG5cbiAgICBjb25maWd1cmF0aW9uLnJwYy5wdWxsID0gZnVuY3Rpb24ocGFyYW1zLCByZXF1ZXN0KSB7XG4gICAgICAgIHJlcXVlc3QucmVwbHkobnVsbCwgXCJwdXNoXCIpO1xuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTlJFQ09OTkVDVElORyAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gUkVDT05ORUNUSU5HKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBSRUNPTk5FQ1RJTkcgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05SRUNPTk5FQ1RJTkcgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBzdGF0dXMgPSBSRUNPTk5FQ1RJTkc7XG4gICAgICAgIGlmIChvbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgb25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0ZWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OUkVDT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OUkVDT05ORUNURUQgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdHVzID0gQ09OTkVDVEVEO1xuXG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKTtcbiAgICAgICAgdXNlUGluZygpO1xuXG4gICAgICAgIGlmIChvbnJlY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbnJlY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbmNvbm5lY3RlZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05DT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OQ09OTkVDVEVEIG1lc3NhZ2UuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHN0YXR1cyA9IENPTk5FQ1RFRDtcblxuICAgICAgICBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgICAgICB1c2VQaW5nKCk7XG5cbiAgICAgICAgaWYgKG9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbmNvbm5lY3RlZCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25lcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTkVSUk9SIC0tLS0tLS0tLS0tXCIpO1xuXG4gICAgICAgIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgICAgICBpZiAob25lcnJvcikge1xuICAgICAgICAgICAgb25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgd3MgPSBuZXcgV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbih3c0NvbmZpZyk7XG5cbiAgICBMb2dnZXIuZGVidWcoJ0Nvbm5lY3Rpbmcgd2Vic29ja2V0IHRvIFVSSTogJyArIHdzQ29uZmlnLnVyaSk7XG5cbiAgICB2YXIgcnBjQnVpbGRlck9wdGlvbnMgPSB7XG4gICAgICAgIHJlcXVlc3RfdGltZW91dDogY29uZmlndXJhdGlvbi5ycGMucmVxdWVzdFRpbWVvdXQsXG4gICAgICAgIHBpbmdfcmVxdWVzdF90aW1lb3V0OiBjb25maWd1cmF0aW9uLnJwYy5oZWFydGJlYXRSZXF1ZXN0VGltZW91dFxuICAgIH07XG5cbiAgICB2YXIgcnBjID0gbmV3IFJwY0J1aWxkZXIoUnBjQnVpbGRlci5wYWNrZXJzLkpzb25SUEMsIHJwY0J1aWxkZXJPcHRpb25zLCB3cyxcbiAgICAgICAgZnVuY3Rpb24ocmVxdWVzdCkge1xuXG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlY2VpdmVkIHJlcXVlc3Q6ICcgKyBKU09OLnN0cmluZ2lmeShyZXF1ZXN0KSk7XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdmFyIGZ1bmMgPSBjb25maWd1cmF0aW9uLnJwY1tyZXF1ZXN0Lm1ldGhvZF07XG5cbiAgICAgICAgICAgICAgICBpZiAoZnVuYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIk1ldGhvZCBcIiArIHJlcXVlc3QubWV0aG9kICsgXCIgbm90IHJlZ2lzdGVyZWQgaW4gY2xpZW50XCIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmMocmVxdWVzdC5wYXJhbXMsIHJlcXVlc3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcignRXhjZXB0aW9uIHByb2Nlc3NpbmcgcmVxdWVzdDogJyArIEpTT04uc3RyaW5naWZ5KHJlcXVlc3QpKTtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZXJyb3IoZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICB0aGlzLnNlbmQgPSBmdW5jdGlvbihtZXRob2QsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKG1ldGhvZCAhPT0gJ3BpbmcnKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlcXVlc3Q6IG1ldGhvZDonICsgbWV0aG9kICsgXCIgcGFyYW1zOlwiICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcmVxdWVzdFRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIHJwYy5lbmNvZGUobWV0aG9kLCBwYXJhbXMsIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SOlwiICsgZXJyb3IubWVzc2FnZSArIFwiIGluIFJlcXVlc3Q6IG1ldGhvZDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgKyBcIiBwYXJhbXM6XCIgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpICsgXCIgcmVxdWVzdDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvci5yZXF1ZXN0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SIERBVEE6XCIgKyBKU09OLnN0cmluZ2lmeShlcnJvci5kYXRhKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICAgICAgICAgIGVycm9yLnJlcXVlc3RUaW1lID0gcmVxdWVzdFRpbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0ICE9IHVuZGVmaW5lZCAmJiByZXN1bHQudmFsdWUgIT09ICdwb25nJykge1xuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1Jlc3BvbnNlOiAnICsgSlNPTi5zdHJpbmdpZnkocmVzdWx0KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gXCIgKyBwaW5nTmV4dE51bSArICcgKG9sZD0nICtcbiAgICAgICAgICAgIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gKyAnKScpO1xuICAgICAgICBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gcGluZ05leHROdW07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2VuZFBpbmcoKSB7XG4gICAgICAgIGlmIChlbmFibGVkUGluZ3MpIHtcbiAgICAgICAgICAgIHZhciBwYXJhbXMgPSBudWxsO1xuICAgICAgICAgICAgaWYgKHBpbmdOZXh0TnVtID09IDAgfHwgcGluZ05leHROdW0gPT0gbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgIHBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJ2YWw6IGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0IHx8IFBJTkdfSU5URVJWQUxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGluZ05leHROdW0rKztcblxuICAgICAgICAgICAgc2VsZi5zZW5kKCdwaW5nJywgcGFyYW1zLCAoZnVuY3Rpb24ocGluZ051bSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiRXJyb3IgaW4gcGluZyByZXF1ZXN0ICNcIiArIHBpbmdOdW0gKyBcIiAoXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yLm1lc3NhZ2UgKyBcIilcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocGluZ051bSA+IG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmFibGVkUGluZ3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU2VydmVyIGRpZCBub3QgcmVzcG9uZCB0byBwaW5nIG1lc3NhZ2UgI1wiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGluZ051bSArIFwiLiBSZWNvbm5lY3RpbmcuLi4gXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdzLnJlY29ubmVjdFdzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KShwaW5nTmV4dE51bSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVHJ5aW5nIHRvIHNlbmQgcGluZywgYnV0IHBpbmcgaXMgbm90IGVuYWJsZWRcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICogSWYgY29uZmlndXJhdGlvbi5oZWFyYmVhdCBoYXMgYW55IHZhbHVlLCB0aGUgcGluZy1wb25nIHdpbGwgd29yayB3aXRoIHRoZSBpbnRlcnZhbFxuICAgICogb2YgY29uZmlndXJhdGlvbi5oZWFyYmVhdFxuICAgICovXG4gICAgZnVuY3Rpb24gdXNlUGluZygpIHtcbiAgICAgICAgaWYgKCFwaW5nUG9uZ1N0YXJ0ZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlN0YXJ0aW5nIHBpbmcgKGlmIGNvbmZpZ3VyZWQpXCIpXG4gICAgICAgICAgICBwaW5nUG9uZ1N0YXJ0ZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBpZiAoY29uZmlndXJhdGlvbi5oZWFydGJlYXQgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcGluZ0ludGVydmFsID0gc2V0SW50ZXJ2YWwoc2VuZFBpbmcsIGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0KTtcbiAgICAgICAgICAgICAgICBzZW5kUGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJDbG9zaW5nIGpzb25ScGNDbGllbnQgZXhwbGljaXRseSBieSBjbGllbnRcIik7XG5cbiAgICAgICAgaWYgKHBpbmdJbnRlcnZhbCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsZWFyaW5nIHBpbmcgaW50ZXJ2YWxcIik7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHBpbmdJbnRlcnZhbCk7XG4gICAgICAgIH1cbiAgICAgICAgcGluZ1BvbmdTdGFydGVkID0gZmFsc2U7XG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuXG4gICAgICAgIGlmIChjb25maWd1cmF0aW9uLnNlbmRDbG9zZU1lc3NhZ2UpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlNlbmRpbmcgY2xvc2UgbWVzc2FnZVwiKVxuICAgICAgICAgICAgdGhpcy5zZW5kKCdjbG9zZVNlc3Npb24nLCBudWxsLCBmdW5jdGlvbihlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVycm9yIHNlbmRpbmcgY2xvc2UgbWVzc2FnZTogXCIgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB3cy5jbG9zZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG5cdFx0XHR3cy5jbG9zZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVGhpcyBtZXRob2QgaXMgb25seSBmb3IgdGVzdGluZ1xuICAgIHRoaXMuZm9yY2VDbG9zZSA9IGZ1bmN0aW9uKG1pbGxpcykge1xuICAgICAgICB3cy5mb3JjZUNsb3NlKG1pbGxpcyk7XG4gICAgfVxuXG4gICAgdGhpcy5yZWNvbm5lY3QgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgd3MucmVjb25uZWN0V3MoKTtcbiAgICB9XG59XG5cblxubW9kdWxlLmV4cG9ydHMgPSBKc29uUnBjQ2xpZW50O1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uICA9IHJlcXVpcmUoJy4vd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xuXG5cbmV4cG9ydHMuV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbiAgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uOyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTMtMjAxNSBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBCcm93c2VyV2ViU29ja2V0ID0gZ2xvYmFsLldlYlNvY2tldCB8fCBnbG9iYWwuTW96V2ViU29ja2V0O1xuXG52YXIgTG9nZ2VyID0gY29uc29sZTtcblxuLyoqXG4gKiBHZXQgZWl0aGVyIHRoZSBgV2ViU29ja2V0YCBvciBgTW96V2ViU29ja2V0YCBnbG9iYWxzXG4gKiBpbiB0aGUgYnJvd3NlciBvciB0cnkgdG8gcmVzb2x2ZSBXZWJTb2NrZXQtY29tcGF0aWJsZVxuICogaW50ZXJmYWNlIGV4cG9zZWQgYnkgYHdzYCBmb3IgTm9kZS1saWtlIGVudmlyb25tZW50LlxuICovXG5cbi8qdmFyIFdlYlNvY2tldCA9IEJyb3dzZXJXZWJTb2NrZXQ7XG5pZiAoIVdlYlNvY2tldCAmJiB0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xuICAgIHRyeSB7XG4gICAgICAgIFdlYlNvY2tldCA9IHJlcXVpcmUoJ3dzJyk7XG4gICAgfSBjYXRjaCAoZSkgeyB9XG59Ki9cblxuLy92YXIgU29ja0pTID0gcmVxdWlyZSgnc29ja2pzLWNsaWVudCcpO1xuXG52YXIgTUFYX1JFVFJJRVMgPSAyMDAwOyAvLyBGb3JldmVyLi4uXG52YXIgUkVUUllfVElNRV9NUyA9IDMwMDA7IC8vIEZJWE1FOiBJbXBsZW1lbnQgZXhwb25lbnRpYWwgd2FpdCB0aW1lcy4uLlxuXG52YXIgQ09OTkVDVElORyA9IDA7XG52YXIgT1BFTiA9IDE7XG52YXIgQ0xPU0lORyA9IDI7XG52YXIgQ0xPU0VEID0gMztcblxuLypcbmNvbmZpZyA9IHtcblx0XHR1cmkgOiB3c1VyaSxcblx0XHR1c2VTb2NrSlMgOiB0cnVlICh1c2UgU29ja0pTKSAvIGZhbHNlICh1c2UgV2ViU29ja2V0KSBieSBkZWZhdWx0LFxuXHRcdG9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcblx0XHRvbmRpc2Nvbm5lY3QgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgbG9zdCxcblx0XHRvbnJlY29ubmVjdGluZyA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY2xpZW50IGlzIHJlY29ubmVjdGluZyxcblx0XHRvbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2VzZnVsbHkgcmVjb25uZWN0cyxcblx0fTtcbiovXG5mdW5jdGlvbiBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uKGNvbmZpZykge1xuXG4gICAgdmFyIGNsb3NpbmcgPSBmYWxzZTtcbiAgICB2YXIgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcjtcbiAgICB2YXIgd3NVcmkgPSBjb25maWcudXJpO1xuICAgIHZhciB1c2VTb2NrSlMgPSBjb25maWcudXNlU29ja0pTO1xuICAgIHZhciByZWNvbm5lY3RpbmcgPSBmYWxzZTtcblxuICAgIHZhciBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IGZhbHNlO1xuXG4gICAgdmFyIHdzO1xuXG4gICAgaWYgKHVzZVNvY2tKUykge1xuICAgICAgICB3cyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHdzID0gbmV3IFdlYlNvY2tldCh3c1VyaSk7XG4gICAgfVxuXG4gICAgd3Mub25vcGVuID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGxvZ0Nvbm5lY3RlZCh3cywgd3NVcmkpO1xuICAgICAgICBpZiAoY29uZmlnLm9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBjb25maWcub25jb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmVycm9yID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmVycm9yKFwiQ291bGQgbm90IGNvbm5lY3QgdG8gXCIgKyB3c1VyaSArIFwiIChpbnZva2luZyBvbmVycm9yIGlmIGRlZmluZWQpXCIsIGVycm9yKTtcbiAgICAgICAgaWYgKGNvbmZpZy5vbmVycm9yKSB7XG4gICAgICAgICAgICBjb25maWcub25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gbG9nQ29ubmVjdGVkKHdzLCB3c1VyaSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiV2ViU29ja2V0IGNvbm5lY3RlZCB0byBcIiArIHdzVXJpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHJlY29ubmVjdGlvbk9uQ2xvc2UgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHdzLnJlYWR5U3RhdGUgPT09IENMT1NFRCkge1xuICAgICAgICAgICAgaWYgKGNsb3NpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCBieSB1c2VyXCIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCB1bmV4cGVjdGVjbHkuIFJlY29ubmVjdGluZy4uLlwiKTtcbiAgICAgICAgICAgICAgICByZWNvbm5lY3RUb1NhbWVVcmkoTUFYX1JFVFJJRVMsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ2xvc2UgY2FsbGJhY2sgZnJvbSBwcmV2aW91cyB3ZWJzb2NrZXQuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHdzLm9uY2xvc2UgPSByZWNvbm5lY3Rpb25PbkNsb3NlO1xuXG4gICAgZnVuY3Rpb24gcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwicmVjb25uZWN0VG9TYW1lVXJpIChhdHRlbXB0ICNcIiArIG51bVJldHJpZXMgKyBcIiwgbWF4PVwiICsgbWF4UmV0cmllcyArIFwiKVwiKTtcblxuICAgICAgICBpZiAobnVtUmV0cmllcyA9PT0gMSkge1xuICAgICAgICAgICAgaWYgKHJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIExvZ2dlci53YXJuKFwiVHJ5aW5nIHRvIHJlY29ubmVjdFRvTmV3VXJpIHdoZW4gcmVjb25uZWN0aW5nLi4uIElnbm9yaW5nIHRoaXMgcmVjb25uZWN0aW9uLlwiKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNvbmZpZy5vbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5vbnJlY29ubmVjdGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZvcmNpbmdEaXNjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCB3c1VyaSk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChjb25maWcubmV3V3NVcmlPblJlY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5uZXdXc1VyaU9uUmVjb25uZWN0aW9uKGZ1bmN0aW9uKGVycm9yLCBuZXdXc1VyaSkge1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIFJFVFJZX1RJTUVfTVMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgbmV3V3NVcmkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgd3NVcmkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVE9ETyBUZXN0IHJldHJpZXMuIEhvdyB0byBmb3JjZSBub3QgY29ubmVjdGlvbj9cbiAgICBmdW5jdGlvbiByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCByZWNvbm5lY3RXc1VyaSkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJSZWNvbm5lY3Rpb24gYXR0ZW1wdCAjXCIgKyBudW1SZXRyaWVzKTtcblxuICAgICAgICB3cy5jbG9zZSgpO1xuXG4gICAgICAgIHdzVXJpID0gcmVjb25uZWN0V3NVcmkgfHwgd3NVcmk7XG5cbiAgICAgICAgdmFyIG5ld1dzO1xuICAgICAgICBpZiAodXNlU29ja0pTKSB7XG4gICAgICAgICAgICBuZXdXcyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3V3MgPSBuZXcgV2ViU29ja2V0KHdzVXJpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5ld1dzLm9ub3BlbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiUmVjb25uZWN0ZWQgYWZ0ZXIgXCIgKyBudW1SZXRyaWVzICsgXCIgYXR0ZW1wdHMuLi5cIik7XG4gICAgICAgICAgICBsb2dDb25uZWN0ZWQobmV3V3MsIHdzVXJpKTtcbiAgICAgICAgICAgIHJlY29ubmVjdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcigpO1xuICAgICAgICAgICAgaWYgKGNvbmZpZy5vbnJlY29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICBjb25maWcub25yZWNvbm5lY3RlZCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBuZXdXcy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgb25FcnJvck9yQ2xvc2UgPSBmdW5jdGlvbihlcnJvcikge1xuICAgICAgICAgICAgTG9nZ2VyLndhcm4oXCJSZWNvbm5lY3Rpb24gZXJyb3I6IFwiLCBlcnJvcik7XG5cbiAgICAgICAgICAgIGlmIChudW1SZXRyaWVzID09PSBtYXhSZXRyaWVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbmZpZy5vbmRpc2Nvbm5lY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uZmlnLm9uZGlzY29ubmVjdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICB9LCBSRVRSWV9USU1FX01TKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBuZXdXcy5vbmVycm9yID0gb25FcnJvck9yQ2xvc2U7XG5cbiAgICAgICAgd3MgPSBuZXdXcztcbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGNsb3NpbmcgPSB0cnVlO1xuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cblxuICAgIC8vIFRoaXMgbWV0aG9kIGlzIG9ubHkgZm9yIHRlc3RpbmdcbiAgICB0aGlzLmZvcmNlQ2xvc2UgPSBmdW5jdGlvbihtaWxsaXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogRm9yY2UgV2ViU29ja2V0IGNsb3NlXCIpO1xuXG4gICAgICAgIGlmIChtaWxsaXMpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IENoYW5nZSB3c1VyaSBmb3IgXCIgKyBtaWxsaXMgKyBcIiBtaWxsaXMgdG8gc2ltdWxhdGUgbmV0IGZhaWx1cmVcIik7XG4gICAgICAgICAgICB2YXIgZ29vZFdzVXJpID0gd3NVcmk7XG4gICAgICAgICAgICB3c1VyaSA9IFwid3NzOi8vMjEuMjM0LjEyLjM0LjQ6NDQzL1wiO1xuXG4gICAgICAgICAgICBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IHRydWU7XG5cbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogUmVjb3ZlciBnb29kIHdzVXJpIFwiICsgZ29vZFdzVXJpKTtcbiAgICAgICAgICAgICAgICB3c1VyaSA9IGdvb2RXc1VyaTtcblxuICAgICAgICAgICAgICAgIGZvcmNpbmdEaXNjb25uZWN0aW9uID0gZmFsc2U7XG5cbiAgICAgICAgICAgIH0sIG1pbGxpcyk7XG4gICAgICAgIH1cblxuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cbiAgICB0aGlzLnJlY29ubmVjdFdzID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcInJlY29ubmVjdFdzXCIpO1xuICAgICAgICByZWNvbm5lY3RUb1NhbWVVcmkoTUFYX1JFVFJJRVMsIDEsIHdzVXJpKTtcbiAgICB9O1xuXG4gICAgdGhpcy5zZW5kID0gZnVuY3Rpb24obWVzc2FnZSkge1xuICAgICAgICB3cy5zZW5kKG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbih0eXBlLCBjYWxsYmFjaykge1xuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB3cy5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKCk7XG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cblxudmFyIGRlZmluZVByb3BlcnR5X0lFOCA9IGZhbHNlXG5pZihPYmplY3QuZGVmaW5lUHJvcGVydHkpXG57XG4gIHRyeVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCBcInhcIiwge30pO1xuICB9XG4gIGNhdGNoKGUpXG4gIHtcbiAgICBkZWZpbmVQcm9wZXJ0eV9JRTggPSB0cnVlXG4gIH1cbn1cblxuLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRnVuY3Rpb24vYmluZFxuaWYgKCFGdW5jdGlvbi5wcm90b3R5cGUuYmluZCkge1xuICBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKG9UaGlzKSB7XG4gICAgaWYgKHR5cGVvZiB0aGlzICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBjbG9zZXN0IHRoaW5nIHBvc3NpYmxlIHRvIHRoZSBFQ01BU2NyaXB0IDVcbiAgICAgIC8vIGludGVybmFsIElzQ2FsbGFibGUgZnVuY3Rpb25cbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Z1bmN0aW9uLnByb3RvdHlwZS5iaW5kIC0gd2hhdCBpcyB0cnlpbmcgdG8gYmUgYm91bmQgaXMgbm90IGNhbGxhYmxlJyk7XG4gICAgfVxuXG4gICAgdmFyIGFBcmdzICAgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxuICAgICAgICBmVG9CaW5kID0gdGhpcyxcbiAgICAgICAgZk5PUCAgICA9IGZ1bmN0aW9uKCkge30sXG4gICAgICAgIGZCb3VuZCAgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gZlRvQmluZC5hcHBseSh0aGlzIGluc3RhbmNlb2YgZk5PUCAmJiBvVGhpc1xuICAgICAgICAgICAgICAgICA/IHRoaXNcbiAgICAgICAgICAgICAgICAgOiBvVGhpcyxcbiAgICAgICAgICAgICAgICAgYUFyZ3MuY29uY2F0KEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKTtcbiAgICAgICAgfTtcblxuICAgIGZOT1AucHJvdG90eXBlID0gdGhpcy5wcm90b3R5cGU7XG4gICAgZkJvdW5kLnByb3RvdHlwZSA9IG5ldyBmTk9QKCk7XG5cbiAgICByZXR1cm4gZkJvdW5kO1xuICB9O1xufVxuXG5cbnZhciBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXI7XG5cbnZhciBpbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJyk7XG5cbnZhciBwYWNrZXJzID0gcmVxdWlyZSgnLi9wYWNrZXJzJyk7XG52YXIgTWFwcGVyID0gcmVxdWlyZSgnLi9NYXBwZXInKTtcblxuXG52YXIgQkFTRV9USU1FT1VUID0gNTAwMDtcblxuXG5mdW5jdGlvbiB1bmlmeVJlc3BvbnNlTWV0aG9kcyhyZXNwb25zZU1ldGhvZHMpXG57XG4gIGlmKCFyZXNwb25zZU1ldGhvZHMpIHJldHVybiB7fTtcblxuICBmb3IodmFyIGtleSBpbiByZXNwb25zZU1ldGhvZHMpXG4gIHtcbiAgICB2YXIgdmFsdWUgPSByZXNwb25zZU1ldGhvZHNba2V5XTtcblxuICAgIGlmKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJylcbiAgICAgIHJlc3BvbnNlTWV0aG9kc1trZXldID1cbiAgICAgIHtcbiAgICAgICAgcmVzcG9uc2U6IHZhbHVlXG4gICAgICB9XG4gIH07XG5cbiAgcmV0dXJuIHJlc3BvbnNlTWV0aG9kcztcbn07XG5cbmZ1bmN0aW9uIHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydClcbntcbiAgaWYoIXRyYW5zcG9ydCkgcmV0dXJuO1xuXG4gIC8vIFRyYW5zcG9ydCBhcyBhIGZ1bmN0aW9uXG4gIGlmKHRyYW5zcG9ydCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB7c2VuZDogdHJhbnNwb3J0fTtcblxuICAvLyBXZWJTb2NrZXQgJiBEYXRhQ2hhbm5lbFxuICBpZih0cmFuc3BvcnQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB0cmFuc3BvcnQ7XG5cbiAgLy8gTWVzc2FnZSBBUEkgKEludGVyLXdpbmRvdyAmIFdlYldvcmtlcilcbiAgaWYodHJhbnNwb3J0LnBvc3RNZXNzYWdlIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICB0cmFuc3BvcnQuc2VuZCA9IHRyYW5zcG9ydC5wb3N0TWVzc2FnZTtcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuICB9XG5cbiAgLy8gU3RyZWFtIEFQSVxuICBpZih0cmFuc3BvcnQud3JpdGUgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIHRyYW5zcG9ydC5zZW5kID0gdHJhbnNwb3J0LndyaXRlO1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cblxuICAvLyBUcmFuc3BvcnRzIHRoYXQgb25seSBjYW4gcmVjZWl2ZSBtZXNzYWdlcywgYnV0IG5vdCBzZW5kXG4gIGlmKHRyYW5zcG9ydC5vbm1lc3NhZ2UgIT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICBpZih0cmFuc3BvcnQucGF1c2UgaW5zdGFuY2VvZiBGdW5jdGlvbikgcmV0dXJuO1xuXG4gIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRyYW5zcG9ydCBpcyBub3QgYSBmdW5jdGlvbiBub3IgYSB2YWxpZCBvYmplY3RcIik7XG59O1xuXG5cbi8qKlxuICogUmVwcmVzZW50YXRpb24gb2YgYSBSUEMgbm90aWZpY2F0aW9uXG4gKlxuICogQGNsYXNzXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZCAtbWV0aG9kIG9mIHRoZSBub3RpZmljYXRpb25cbiAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAqL1xuZnVuY3Rpb24gUnBjTm90aWZpY2F0aW9uKG1ldGhvZCwgcGFyYW1zKVxue1xuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gIHtcbiAgICB0aGlzLm1ldGhvZCA9IG1ldGhvZFxuICAgIHRoaXMucGFyYW1zID0gcGFyYW1zXG4gIH1cbiAgZWxzZVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdtZXRob2QnLCB7dmFsdWU6IG1ldGhvZCwgZW51bWVyYWJsZTogdHJ1ZX0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAncGFyYW1zJywge3ZhbHVlOiBwYXJhbXMsIGVudW1lcmFibGU6IHRydWV9KTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEBjbGFzc1xuICpcbiAqIEBjb25zdHJ1Y3RvclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwYWNrZXJcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gW29wdGlvbnNdXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29uUmVxdWVzdF1cbiAqL1xuZnVuY3Rpb24gUnBjQnVpbGRlcihwYWNrZXIsIG9wdGlvbnMsIHRyYW5zcG9ydCwgb25SZXF1ZXN0KVxue1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgaWYoIXBhY2tlcilcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBub3QgZGVmaW5lZCcpO1xuXG4gIGlmKCFwYWNrZXIucGFjayB8fCAhcGFja2VyLnVucGFjaylcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBpbnZhbGlkJyk7XG5cbiAgdmFyIHJlc3BvbnNlTWV0aG9kcyA9IHVuaWZ5UmVzcG9uc2VNZXRob2RzKHBhY2tlci5yZXNwb25zZU1ldGhvZHMpO1xuXG5cbiAgaWYob3B0aW9ucyBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgaWYodHJhbnNwb3J0ICE9IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgb25SZXF1ZXN0XCIpO1xuXG4gICAgb25SZXF1ZXN0ID0gb3B0aW9ucztcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgb3B0aW9ucyAgID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmKG9wdGlvbnMgJiYgb3B0aW9ucy5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICBpZih0cmFuc3BvcnQgJiYgISh0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbikpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJPbmx5IGEgZnVuY3Rpb24gY2FuIGJlIGFmdGVyIHRyYW5zcG9ydFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSBvcHRpb25zO1xuICAgIG9wdGlvbnMgICA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIGlmKG9uUmVxdWVzdCAhPSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIG9uUmVxdWVzdFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gIH07XG5cbiAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgaWYob25SZXF1ZXN0ICYmICEob25SZXF1ZXN0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblxuICBFdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcblxuICBpZihvblJlcXVlc3QpXG4gICAgdGhpcy5vbigncmVxdWVzdCcsIG9uUmVxdWVzdCk7XG5cblxuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgdGhpcy5wZWVySUQgPSBvcHRpb25zLnBlZXJJRFxuICBlbHNlXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdwZWVySUQnLCB7dmFsdWU6IG9wdGlvbnMucGVlcklEfSk7XG5cbiAgdmFyIG1heF9yZXRyaWVzID0gb3B0aW9ucy5tYXhfcmV0cmllcyB8fCAwO1xuXG5cbiAgZnVuY3Rpb24gdHJhbnNwb3J0TWVzc2FnZShldmVudClcbiAge1xuICAgIHNlbGYuZGVjb2RlKGV2ZW50LmRhdGEgfHwgZXZlbnQpO1xuICB9O1xuXG4gIHRoaXMuZ2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24oKVxuICB7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuICB0aGlzLnNldFRyYW5zcG9ydCA9IGZ1bmN0aW9uKHZhbHVlKVxuICB7XG4gICAgLy8gUmVtb3ZlIGxpc3RlbmVyIGZyb20gb2xkIHRyYW5zcG9ydFxuICAgIGlmKHRyYW5zcG9ydClcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodHJhbnNwb3J0LnJlbW92ZUV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgdHJhbnNwb3J0TWVzc2FnZSk7XG5cbiAgICAgIC8vIE5vZGUuanMgU3RyZWFtcyBBUElcbiAgICAgIGVsc2UgaWYodHJhbnNwb3J0LnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICB0cmFuc3BvcnQucmVtb3ZlTGlzdGVuZXIoJ2RhdGEnLCB0cmFuc3BvcnRNZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgLy8gU2V0IGxpc3RlbmVyIG9uIG5ldyB0cmFuc3BvcnRcbiAgICBpZih2YWx1ZSlcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodmFsdWUuYWRkRXZlbnRMaXN0ZW5lcilcbiAgICAgICAgdmFsdWUuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuXG4gICAgICAvLyBOb2RlLmpzIFN0cmVhbXMgQVBJXG4gICAgICBlbHNlIGlmKHZhbHVlLmFkZExpc3RlbmVyKVxuICAgICAgICB2YWx1ZS5hZGRMaXN0ZW5lcignZGF0YScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gIH1cblxuICBpZighZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICB7XG4gICAgICBnZXQ6IHRoaXMuZ2V0VHJhbnNwb3J0LmJpbmQodGhpcyksXG4gICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICB9KVxuXG4gIHRoaXMuc2V0VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cblxuICB2YXIgcmVxdWVzdF90aW1lb3V0ICAgICAgPSBvcHRpb25zLnJlcXVlc3RfdGltZW91dCAgICAgIHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIHBpbmdfcmVxdWVzdF90aW1lb3V0ID0gb3B0aW9ucy5waW5nX3JlcXVlc3RfdGltZW91dCB8fCByZXF1ZXN0X3RpbWVvdXQ7XG4gIHZhciByZXNwb25zZV90aW1lb3V0ICAgICA9IG9wdGlvbnMucmVzcG9uc2VfdGltZW91dCAgICAgfHwgQkFTRV9USU1FT1VUO1xuICB2YXIgZHVwbGljYXRlc190aW1lb3V0ICAgPSBvcHRpb25zLmR1cGxpY2F0ZXNfdGltZW91dCAgIHx8IEJBU0VfVElNRU9VVDtcblxuXG4gIHZhciByZXF1ZXN0SUQgPSAwO1xuXG4gIHZhciByZXF1ZXN0cyAgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciByZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciBwcm9jZXNzZWRSZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG5cbiAgdmFyIG1lc3NhZ2UyS2V5ID0ge307XG5cblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIHByZXZlbnQgdG8gcHJvY2VzcyBkdXBsaWNhdGUgcmVxdWVzdCBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVSZXNwb25zZShtZXNzYWdlLCBpZCwgZGVzdClcbiAge1xuICAgIHZhciByZXNwb25zZSA9XG4gICAge1xuICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgIC8qKiBUaW1lb3V0IHRvIGF1dG8tY2xlYW4gb2xkIHJlc3BvbnNlcyAqL1xuICAgICAgdGltZW91dDogc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAgICB7XG4gICAgICAgIHJlc3BvbnNlcy5yZW1vdmUoaWQsIGRlc3QpO1xuICAgICAgfSxcbiAgICAgIHJlc3BvbnNlX3RpbWVvdXQpXG4gICAgfTtcblxuICAgIHJlc3BvbnNlcy5zZXQocmVzcG9uc2UsIGlkLCBkZXN0KTtcbiAgfTtcblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIGlnbm9yZSBkdXBsaWNhdGVkIG1lc3NhZ2VzIGxhdGVyXG4gICAqL1xuICBmdW5jdGlvbiBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGFjaywgZnJvbSlcbiAge1xuICAgIHZhciB0aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAge1xuICAgICAgcHJvY2Vzc2VkUmVzcG9uc2VzLnJlbW92ZShhY2ssIGZyb20pO1xuICAgIH0sXG4gICAgZHVwbGljYXRlc190aW1lb3V0KTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5zZXQodGltZW91dCwgYWNrLCBmcm9tKTtcbiAgfTtcblxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRhdGlvbiBvZiBhIFJQQyByZXF1ZXN0XG4gICAqXG4gICAqIEBjbGFzc1xuICAgKiBAZXh0ZW5kcyBScGNOb3RpZmljYXRpb25cbiAgICpcbiAgICogQGNvbnN0cnVjdG9yXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBpZCAtIGlkZW50aWZpZXIgb2YgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIFtmcm9tXSAtIHNvdXJjZSBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqL1xuICBmdW5jdGlvbiBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZCwgZnJvbSwgdHJhbnNwb3J0KVxuICB7XG4gICAgUnBjTm90aWZpY2F0aW9uLmNhbGwodGhpcywgbWV0aG9kLCBwYXJhbXMpO1xuXG4gICAgdGhpcy5nZXRUcmFuc3BvcnQgPSBmdW5jdGlvbigpXG4gICAge1xuICAgICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgICB9XG4gICAgdGhpcy5zZXRUcmFuc3BvcnQgPSBmdW5jdGlvbih2YWx1ZSlcbiAgICB7XG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgaWYoIWRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICAgIHtcbiAgICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICAgIH0pXG5cbiAgICB2YXIgcmVzcG9uc2UgPSByZXNwb25zZXMuZ2V0KGlkLCBmcm9tKTtcblxuICAgIC8qKlxuICAgICAqIEBjb25zdGFudCB7Qm9vbGVhbn0gZHVwbGljYXRlZFxuICAgICAqL1xuICAgIGlmKCEodHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCkpKVxuICAgIHtcbiAgICAgIGlmKGRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgICAgdGhpcy5kdXBsaWNhdGVkID0gQm9vbGVhbihyZXNwb25zZSlcbiAgICAgIGVsc2VcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdkdXBsaWNhdGVkJyxcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiBCb29sZWFuKHJlc3BvbnNlKVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgcmVzcG9uc2VNZXRob2QgPSByZXNwb25zZU1ldGhvZHNbbWV0aG9kXTtcblxuICAgIHRoaXMucGFjayA9IHBhY2tlci5wYWNrLmJpbmQocGFja2VyLCB0aGlzLCBpZClcblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgcmVzcG9uc2UgdG8gdGhpcyByZXF1ZXN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Vycm9yfSBbZXJyb3JdXG4gICAgICogQHBhcmFtIHsqfSBbcmVzdWx0XVxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICB0aGlzLnJlcGx5ID0gZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCwgdHJhbnNwb3J0KVxuICAgIHtcbiAgICAgIC8vIEZpeCBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgICBpZihlcnJvciBpbnN0YW5jZW9mIEZ1bmN0aW9uIHx8IGVycm9yICYmIGVycm9yLnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICAgIHtcbiAgICAgICAgaWYocmVzdWx0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IGVycm9yO1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgICBlcnJvciA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgZWxzZSBpZihyZXN1bHQgaW5zdGFuY2VvZiBGdW5jdGlvblxuICAgICAgfHwgcmVzdWx0ICYmIHJlc3VsdC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgICB7XG4gICAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSByZXN1bHQ7XG4gICAgICAgIHJlc3VsdCA9IG51bGw7XG4gICAgICB9O1xuXG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICAvLyBEdXBsaWNhdGVkIHJlcXVlc3QsIHJlbW92ZSBvbGQgcmVzcG9uc2UgdGltZW91dFxuICAgICAgaWYocmVzcG9uc2UpXG4gICAgICAgIGNsZWFyVGltZW91dChyZXNwb25zZS50aW1lb3V0KTtcblxuICAgICAgaWYoZnJvbSAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgIGVycm9yLmRlc3QgPSBmcm9tO1xuXG4gICAgICAgIGlmKHJlc3VsdClcbiAgICAgICAgICByZXN1bHQuZGVzdCA9IGZyb207XG4gICAgICB9O1xuXG4gICAgICB2YXIgbWVzc2FnZTtcblxuICAgICAgLy8gTmV3IHJlcXVlc3Qgb3Igb3ZlcnJpZGVuIG9uZSwgY3JlYXRlIG5ldyByZXNwb25zZSB3aXRoIHByb3ZpZGVkIGRhdGFcbiAgICAgIGlmKGVycm9yIHx8IHJlc3VsdCAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZClcbiAgICAgICAge1xuICAgICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgICAgZXJyb3IuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIHJlc3VsdC5mcm9tID0gc2VsZi5wZWVySUQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcm90b2NvbCBpbmRpY2F0ZXMgdGhhdCByZXNwb25zZXMgaGFzIG93biByZXF1ZXN0IG1ldGhvZHNcbiAgICAgICAgaWYocmVzcG9uc2VNZXRob2QpXG4gICAgICAgIHtcbiAgICAgICAgICBpZihyZXNwb25zZU1ldGhvZC5lcnJvciA9PSB1bmRlZmluZWQgJiYgZXJyb3IpXG4gICAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXJyb3I6IGVycm9yXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHZhciBtZXRob2QgPSBlcnJvclxuICAgICAgICAgICAgICAgICAgICAgICA/IHJlc3BvbnNlTWV0aG9kLmVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgIDogcmVzcG9uc2VNZXRob2QucmVzcG9uc2U7XG5cbiAgICAgICAgICAgIG1lc3NhZ2UgPVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgICAgICAgcGFyYW1zOiBlcnJvciB8fCByZXN1bHRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICB7XG4gICAgICAgICAgICBlcnJvcjogIGVycm9yLFxuICAgICAgICAgICAgcmVzdWx0OiByZXN1bHRcbiAgICAgICAgICB9O1xuXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIER1cGxpY2F0ZSAmIG5vdC1vdmVycmlkZW4gcmVxdWVzdCwgcmUtc2VuZCBvbGQgcmVzcG9uc2VcbiAgICAgIGVsc2UgaWYocmVzcG9uc2UpXG4gICAgICAgIG1lc3NhZ2UgPSByZXNwb25zZS5tZXNzYWdlO1xuXG4gICAgICAvLyBOZXcgZW1wdHkgcmVwbHksIHJlc3BvbnNlIG51bGwgdmFsdWVcbiAgICAgIGVsc2VcbiAgICAgICAgbWVzc2FnZSA9IHBhY2tlci5wYWNrKHtyZXN1bHQ6IG51bGx9LCBpZCk7XG5cbiAgICAgIC8vIFN0b3JlIHRoZSByZXNwb25zZSB0byBwcmV2ZW50IHRvIHByb2Nlc3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QgbGF0ZXJcbiAgICAgIHN0b3JlUmVzcG9uc2UobWVzc2FnZSwgaWQsIGZyb20pO1xuXG4gICAgICAvLyBSZXR1cm4gdGhlIHN0b3JlZCByZXNwb25zZSBzbyBpdCBjYW4gYmUgZGlyZWN0bHkgc2VuZCBiYWNrXG4gICAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKSB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuXG4gICAgICBpZih0cmFuc3BvcnQpXG4gICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChtZXNzYWdlKTtcblxuICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgfVxuICB9O1xuICBpbmhlcml0cyhScGNSZXF1ZXN0LCBScGNOb3RpZmljYXRpb24pO1xuXG5cbiAgZnVuY3Rpb24gY2FuY2VsKG1lc3NhZ2UpXG4gIHtcbiAgICB2YXIga2V5ID0gbWVzc2FnZTJLZXlbbWVzc2FnZV07XG4gICAgaWYoIWtleSkgcmV0dXJuO1xuXG4gICAgZGVsZXRlIG1lc3NhZ2UyS2V5W21lc3NhZ2VdO1xuXG4gICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5wb3Aoa2V5LmlkLCBrZXkuZGVzdCk7XG4gICAgaWYoIXJlcXVlc3QpIHJldHVybjtcblxuICAgIGNsZWFyVGltZW91dChyZXF1ZXN0LnRpbWVvdXQpO1xuXG4gICAgLy8gU3RhcnQgZHVwbGljYXRlZCByZXNwb25zZXMgdGltZW91dFxuICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2Uoa2V5LmlkLCBrZXkuZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEFsbG93IHRvIGNhbmNlbCBhIHJlcXVlc3QgYW5kIGRvbid0IHdhaXQgZm9yIGEgcmVzcG9uc2VcbiAgICpcbiAgICogSWYgYG1lc3NhZ2VgIGlzIG5vdCBnaXZlbiwgY2FuY2VsIGFsbCB0aGUgcmVxdWVzdFxuICAgKi9cbiAgdGhpcy5jYW5jZWwgPSBmdW5jdGlvbihtZXNzYWdlKVxuICB7XG4gICAgaWYobWVzc2FnZSkgcmV0dXJuIGNhbmNlbChtZXNzYWdlKTtcblxuICAgIGZvcih2YXIgbWVzc2FnZSBpbiBtZXNzYWdlMktleSlcbiAgICAgIGNhbmNlbChtZXNzYWdlKTtcbiAgfTtcblxuXG4gIHRoaXMuY2xvc2UgPSBmdW5jdGlvbigpXG4gIHtcbiAgICAvLyBQcmV2ZW50IHRvIHJlY2VpdmUgbmV3IG1lc3NhZ2VzXG4gICAgdmFyIHRyYW5zcG9ydCA9IHRoaXMuZ2V0VHJhbnNwb3J0KCk7XG4gICAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5jbG9zZSlcbiAgICAgICB0cmFuc3BvcnQuY2xvc2UoKTtcblxuICAgIC8vIFJlcXVlc3QgJiBwcm9jZXNzZWQgcmVzcG9uc2VzXG4gICAgdGhpcy5jYW5jZWwoKTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5mb3JFYWNoKGNsZWFyVGltZW91dCk7XG5cbiAgICAvLyBSZXNwb25zZXNcbiAgICByZXNwb25zZXMuZm9yRWFjaChmdW5jdGlvbihyZXNwb25zZSlcbiAgICB7XG4gICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG4gICAgfSk7XG4gIH07XG5cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGFuZCBlbmNvZGUgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIFtkZXN0XSAtIGRlc3RpbmF0aW9uIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdIC0gdHJhbnNwb3J0IHdoZXJlIHRvIHNlbmQgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIFtjYWxsYmFja10gLSBmdW5jdGlvbiBjYWxsZWQgd2hlbiBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdCBpc1xuICAgKiAgIHJlY2VpdmVkLiBJZiBub3QgZGVmaW5lZCwgYSBub3RpZmljYXRpb24gd2lsbCBiZSBzZW5kIGluc3RlYWRcbiAgICpcbiAgICogQHJldHVybnMge3N0cmluZ30gQSByYXcgSnNvblJQQyAyLjAgcmVxdWVzdCBvciBub3RpZmljYXRpb24gc3RyaW5nXG4gICAqL1xuICB0aGlzLmVuY29kZSA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBkZXN0LCB0cmFuc3BvcnQsIGNhbGxiYWNrKVxuICB7XG4gICAgLy8gRml4IG9wdGlvbmFsIHBhcmFtZXRlcnNcbiAgICBpZihwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihkZXN0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgY2FsbGJhY2sgID0gcGFyYW1zO1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCAgICAgID0gdW5kZWZpbmVkO1xuICAgICAgcGFyYW1zICAgID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGVsc2UgaWYoZGVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHtcbiAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IGRlc3Q7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgICBkZXN0ICAgICAgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgZWxzZSBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihjYWxsYmFjayAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IHRyYW5zcG9ydDtcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgaWYoc2VsZi5wZWVySUQgIT0gdW5kZWZpbmVkKVxuICAgIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICB9O1xuXG4gICAgaWYoZGVzdCAhPSB1bmRlZmluZWQpXG4gICAge1xuICAgICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuXG4gICAgICBwYXJhbXMuZGVzdCA9IGRlc3Q7XG4gICAgfTtcblxuICAgIC8vIEVuY29kZSBtZXNzYWdlXG4gICAgdmFyIG1lc3NhZ2UgPVxuICAgIHtcbiAgICAgIG1ldGhvZDogbWV0aG9kLFxuICAgICAgcGFyYW1zOiBwYXJhbXNcbiAgICB9O1xuXG4gICAgaWYoY2FsbGJhY2spXG4gICAge1xuICAgICAgdmFyIGlkID0gcmVxdWVzdElEKys7XG4gICAgICB2YXIgcmV0cmllZCA9IDA7XG5cbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG5cbiAgICAgIGZ1bmN0aW9uIGRpc3BhdGNoQ2FsbGJhY2soZXJyb3IsIHJlc3VsdClcbiAgICAgIHtcbiAgICAgICAgc2VsZi5jYW5jZWwobWVzc2FnZSk7XG5cbiAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgcmVxdWVzdCA9XG4gICAgICB7XG4gICAgICAgIG1lc3NhZ2U6ICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgY2FsbGJhY2s6ICAgICAgICBkaXNwYXRjaENhbGxiYWNrLFxuICAgICAgICByZXNwb25zZU1ldGhvZHM6IHJlc3BvbnNlTWV0aG9kc1ttZXRob2RdIHx8IHt9XG4gICAgICB9O1xuXG4gICAgICB2YXIgZW5jb2RlX3RyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgIGZ1bmN0aW9uIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJ0ID0gKG1ldGhvZCA9PT0gJ3BpbmcnID8gcGluZ19yZXF1ZXN0X3RpbWVvdXQgOiByZXF1ZXN0X3RpbWVvdXQpO1xuICAgICAgICByZXF1ZXN0LnRpbWVvdXQgPSBzZXRUaW1lb3V0KHRpbWVvdXQsIHJ0Kk1hdGgucG93KDIsIHJldHJpZWQrKykpO1xuICAgICAgICBtZXNzYWdlMktleVttZXNzYWdlXSA9IHtpZDogaWQsIGRlc3Q6IGRlc3R9O1xuICAgICAgICByZXF1ZXN0cy5zZXQocmVxdWVzdCwgaWQsIGRlc3QpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IHRyYW5zcG9ydCB8fCBlbmNvZGVfdHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICB9O1xuXG4gICAgICBmdW5jdGlvbiByZXRyeSh0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgY29uc29sZS53YXJuKHJldHJpZWQrJyByZXRyeSBmb3IgcmVxdWVzdCBtZXNzYWdlOicsbWVzc2FnZSk7XG5cbiAgICAgICAgdmFyIHRpbWVvdXQgPSBwcm9jZXNzZWRSZXNwb25zZXMucG9wKGlkLCBkZXN0KTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXG4gICAgICAgIHJldHVybiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gdGltZW91dCgpXG4gICAgICB7XG4gICAgICAgIGlmKHJldHJpZWQgPCBtYXhfcmV0cmllcylcbiAgICAgICAgICByZXR1cm4gcmV0cnkodHJhbnNwb3J0KTtcblxuICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ1JlcXVlc3QgaGFzIHRpbWVkIG91dCcpO1xuICAgICAgICAgICAgZXJyb3IucmVxdWVzdCA9IG1lc3NhZ2U7XG5cbiAgICAgICAgZXJyb3IucmV0cnkgPSByZXRyeTtcblxuICAgICAgICBkaXNwYXRjaENhbGxiYWNrKGVycm9yKVxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydCk7XG4gICAgfTtcblxuICAgIC8vIFJldHVybiB0aGUgcGFja2VkIG1lc3NhZ2VcbiAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSk7XG5cbiAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKTtcbiAgICBpZih0cmFuc3BvcnQpXG4gICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfTtcblxuICAvKipcbiAgICogRGVjb2RlIGFuZCBwcm9jZXNzIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBtZXNzYWdlXG4gICAqXG4gICAqIEByZXR1cm5zIHtScGNOb3RpZmljYXRpb258UnBjUmVxdWVzdHx1bmRlZmluZWR9IC0gdGhlIHJlcHJlc2VudGF0aW9uIG9mIHRoZVxuICAgKiAgIG5vdGlmaWNhdGlvbiBvciB0aGUgcmVxdWVzdC4gSWYgYSByZXNwb25zZSB3YXMgcHJvY2Vzc2VkLCBpdCB3aWxsIHJldHVyblxuICAgKiAgIGB1bmRlZmluZWRgIHRvIG5vdGlmeSB0aGF0IGl0IHdhcyBwcm9jZXNzZWRcbiAgICpcbiAgICogQHRocm93cyB7VHlwZUVycm9yfSAtIE1lc3NhZ2UgaXMgbm90IGRlZmluZWRcbiAgICovXG4gIHRoaXMuZGVjb2RlID0gZnVuY3Rpb24obWVzc2FnZSwgdHJhbnNwb3J0KVxuICB7XG4gICAgaWYoIW1lc3NhZ2UpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWVzc2FnZSBpcyBub3QgZGVmaW5lZFwiKTtcblxuICAgIHRyeVxuICAgIHtcbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIudW5wYWNrKG1lc3NhZ2UpO1xuICAgIH1cbiAgICBjYXRjaChlKVxuICAgIHtcbiAgICAgIC8vIElnbm9yZSBpbnZhbGlkIG1lc3NhZ2VzXG4gICAgICByZXR1cm4gY29uc29sZS5kZWJ1ZyhlLCBtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdmFyIGlkICAgICA9IG1lc3NhZ2UuaWQ7XG4gICAgdmFyIGFjayAgICA9IG1lc3NhZ2UuYWNrO1xuICAgIHZhciBtZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcbiAgICB2YXIgcGFyYW1zID0gbWVzc2FnZS5wYXJhbXMgfHwge307XG5cbiAgICB2YXIgZnJvbSA9IHBhcmFtcy5mcm9tO1xuICAgIHZhciBkZXN0ID0gcGFyYW1zLmRlc3Q7XG5cbiAgICAvLyBJZ25vcmUgbWVzc2FnZXMgc2VuZCBieSB1c1xuICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZCAmJiBmcm9tID09IHNlbGYucGVlcklEKSByZXR1cm47XG5cbiAgICAvLyBOb3RpZmljYXRpb25cbiAgICBpZihpZCA9PSB1bmRlZmluZWQgJiYgYWNrID09IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICB2YXIgbm90aWZpY2F0aW9uID0gbmV3IFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcyk7XG5cbiAgICAgIGlmKHNlbGYuZW1pdCgncmVxdWVzdCcsIG5vdGlmaWNhdGlvbikpIHJldHVybjtcbiAgICAgIHJldHVybiBub3RpZmljYXRpb247XG4gICAgfTtcblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlcXVlc3QoKVxuICAgIHtcbiAgICAgIC8vIElmIHdlIGhhdmUgYSB0cmFuc3BvcnQgYW5kIGl0J3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QsIHJlcGx5IGlubWVkaWF0bHlcbiAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCkgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKTtcbiAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG4gICAgICAgIGlmKHJlc3BvbnNlKVxuICAgICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChyZXNwb25zZS5tZXNzYWdlKTtcbiAgICAgIH07XG5cbiAgICAgIHZhciBpZEFjayA9IChpZCAhPSB1bmRlZmluZWQpID8gaWQgOiBhY2s7XG4gICAgICB2YXIgcmVxdWVzdCA9IG5ldyBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZEFjaywgZnJvbSwgdHJhbnNwb3J0KTtcblxuICAgICAgaWYoc2VsZi5lbWl0KCdyZXF1ZXN0JywgcmVxdWVzdCkpIHJldHVybjtcbiAgICAgIHJldHVybiByZXF1ZXN0O1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdClcbiAgICB7XG4gICAgICByZXF1ZXN0LmNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBkdXBsaWNhdGVkUmVzcG9uc2UodGltZW91dClcbiAgICB7XG4gICAgICBjb25zb2xlLndhcm4oXCJSZXNwb25zZSBhbHJlYWR5IHByb2Nlc3NlZFwiLCBtZXNzYWdlKTtcblxuICAgICAgLy8gVXBkYXRlIGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2UoYWNrLCBmcm9tKTtcbiAgICB9O1xuXG5cbiAgICAvLyBSZXF1ZXN0LCBvciByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICBpZihtZXRob2QpXG4gICAge1xuICAgICAgLy8gQ2hlY2sgaWYgaXQncyBhIHJlc3BvbnNlIHdpdGggb3duIG1ldGhvZFxuICAgICAgaWYoZGVzdCA9PSB1bmRlZmluZWQgfHwgZGVzdCA9PSBzZWxmLnBlZXJJRClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgICAgaWYocmVxdWVzdClcbiAgICAgICAge1xuICAgICAgICAgIHZhciByZXNwb25zZU1ldGhvZHMgPSByZXF1ZXN0LnJlc3BvbnNlTWV0aG9kcztcblxuICAgICAgICAgIGlmKG1ldGhvZCA9PSByZXNwb25zZU1ldGhvZHMuZXJyb3IpXG4gICAgICAgICAgICByZXR1cm4gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIHBhcmFtcyk7XG5cbiAgICAgICAgICBpZihtZXRob2QgPT0gcmVzcG9uc2VNZXRob2RzLnJlc3BvbnNlKVxuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXNwb25zZShyZXF1ZXN0LCBudWxsLCBwYXJhbXMpO1xuXG4gICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXF1ZXN0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkUmVzcG9uc2VzLmdldChhY2ssIGZyb20pO1xuICAgICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgICAgcmV0dXJuIGR1cGxpY2F0ZWRSZXNwb25zZShwcm9jZXNzZWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZXF1ZXN0XG4gICAgICByZXR1cm4gcHJvY2Vzc1JlcXVlc3QoKTtcbiAgICB9O1xuXG4gICAgdmFyIGVycm9yICA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgdmFyIHJlc3VsdCA9IG1lc3NhZ2UucmVzdWx0O1xuXG4gICAgLy8gSWdub3JlIHJlc3BvbnNlcyBub3Qgc2VuZCB0byB1c1xuICAgIGlmKGVycm9yICAmJiBlcnJvci5kZXN0ICAmJiBlcnJvci5kZXN0ICAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuICAgIGlmKHJlc3VsdCAmJiByZXN1bHQuZGVzdCAmJiByZXN1bHQuZGVzdCAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gUmVzcG9uc2VcbiAgICB2YXIgcmVxdWVzdCA9IHJlcXVlc3RzLmdldChhY2ssIGZyb20pO1xuICAgIGlmKCFyZXF1ZXN0KVxuICAgIHtcbiAgICAgIHZhciBwcm9jZXNzZWQgPSBwcm9jZXNzZWRSZXNwb25zZXMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgIHJldHVybiBkdXBsaWNhdGVkUmVzcG9uc2UocHJvY2Vzc2VkKTtcblxuICAgICAgcmV0dXJuIGNvbnNvbGUud2FybihcIk5vIGNhbGxiYWNrIHdhcyBkZWZpbmVkIGZvciB0aGlzIG1lc3NhZ2VcIiwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFByb2Nlc3MgcmVzcG9uc2VcbiAgICBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdCk7XG4gIH07XG59O1xuaW5oZXJpdHMoUnBjQnVpbGRlciwgRXZlbnRFbWl0dGVyKTtcblxuXG5ScGNCdWlsZGVyLlJwY05vdGlmaWNhdGlvbiA9IFJwY05vdGlmaWNhdGlvbjtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFJwY0J1aWxkZXI7XG5cbnZhciBjbGllbnRzID0gcmVxdWlyZSgnLi9jbGllbnRzJyk7XG52YXIgdHJhbnNwb3J0cyA9IHJlcXVpcmUoJy4vY2xpZW50cy90cmFuc3BvcnRzJyk7XG5cblJwY0J1aWxkZXIuY2xpZW50cyA9IGNsaWVudHM7XG5ScGNCdWlsZGVyLmNsaWVudHMudHJhbnNwb3J0cyA9IHRyYW5zcG9ydHM7XG5ScGNCdWlsZGVyLnBhY2tlcnMgPSBwYWNrZXJzO1xuIiwiLyoqXG4gKiBKc29uUlBDIDIuMCBwYWNrZXJcbiAqL1xuXG4vKipcbiAqIFBhY2sgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG1lc3NhZ2UgLSBvYmplY3QgdG8gYmUgcGFja2FnZWQuIEl0IHJlcXVpcmVzIHRvIGhhdmUgYWxsIHRoZVxuICogICBmaWVsZHMgbmVlZGVkIGJ5IHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIHRoYXQgaXQncyBnb2luZyB0byBiZSBnZW5lcmF0ZWRcbiAqXG4gKiBAcmV0dXJuIHtTdHJpbmd9IC0gdGhlIHN0cmluZ2lmaWVkIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqL1xuZnVuY3Rpb24gcGFjayhtZXNzYWdlLCBpZClcbntcbiAgdmFyIHJlc3VsdCA9XG4gIHtcbiAgICBqc29ucnBjOiBcIjIuMFwiXG4gIH07XG5cbiAgLy8gUmVxdWVzdFxuICBpZihtZXNzYWdlLm1ldGhvZClcbiAge1xuICAgIHJlc3VsdC5tZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcblxuICAgIGlmKG1lc3NhZ2UucGFyYW1zKVxuICAgICAgcmVzdWx0LnBhcmFtcyA9IG1lc3NhZ2UucGFyYW1zO1xuXG4gICAgLy8gUmVxdWVzdCBpcyBhIG5vdGlmaWNhdGlvblxuICAgIGlmKGlkICE9IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5pZCA9IGlkO1xuICB9XG5cbiAgLy8gUmVzcG9uc2VcbiAgZWxzZSBpZihpZCAhPSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihtZXNzYWdlLmVycm9yKVxuICAgIHtcbiAgICAgIGlmKG1lc3NhZ2UucmVzdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJCb3RoIHJlc3VsdCBhbmQgZXJyb3IgYXJlIGRlZmluZWRcIik7XG5cbiAgICAgIHJlc3VsdC5lcnJvciA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgfVxuICAgIGVsc2UgaWYobWVzc2FnZS5yZXN1bHQgIT09IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5yZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWRcIik7XG5cbiAgICByZXN1bHQuaWQgPSBpZDtcbiAgfTtcblxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocmVzdWx0KTtcbn07XG5cbi8qKlxuICogVW5wYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIC0gc3RyaW5nIHdpdGggdGhlIGNvbnRlbnQgb2YgdGhlIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAdGhyb3dzIHtUeXBlRXJyb3J9IC0gSW52YWxpZCBKc29uUlBDIHZlcnNpb25cbiAqXG4gKiBAcmV0dXJuIHtPYmplY3R9IC0gb2JqZWN0IGZpbGxlZCB3aXRoIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIGNvbnRlbnRcbiAqL1xuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpXG57XG4gIHZhciByZXN1bHQgPSBtZXNzYWdlO1xuXG4gIGlmKHR5cGVvZiBtZXNzYWdlID09PSAnc3RyaW5nJyB8fCBtZXNzYWdlIGluc3RhbmNlb2YgU3RyaW5nKSB7XG4gICAgcmVzdWx0ID0gSlNPTi5wYXJzZShtZXNzYWdlKTtcbiAgfVxuXG4gIC8vIENoZWNrIGlmIGl0J3MgYSB2YWxpZCBtZXNzYWdlXG5cbiAgdmFyIHZlcnNpb24gPSByZXN1bHQuanNvbnJwYztcbiAgaWYodmVyc2lvbiAhPT0gJzIuMCcpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgSnNvblJQQyB2ZXJzaW9uICdcIiArIHZlcnNpb24gKyBcIic6IFwiICsgbWVzc2FnZSk7XG5cbiAgLy8gUmVzcG9uc2VcbiAgaWYocmVzdWx0Lm1ldGhvZCA9PSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihyZXN1bHQuaWQgPT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgbWVzc2FnZTogXCIrbWVzc2FnZSk7XG5cbiAgICB2YXIgcmVzdWx0X2RlZmluZWQgPSByZXN1bHQucmVzdWx0ICE9PSB1bmRlZmluZWQ7XG4gICAgdmFyIGVycm9yX2RlZmluZWQgID0gcmVzdWx0LmVycm9yICAhPT0gdW5kZWZpbmVkO1xuXG4gICAgLy8gQ2hlY2sgb25seSByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZCwgbm90IGJvdGggb3Igbm9uZVxuICAgIGlmKHJlc3VsdF9kZWZpbmVkICYmIGVycm9yX2RlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQm90aCByZXN1bHQgYW5kIGVycm9yIGFyZSBkZWZpbmVkOiBcIittZXNzYWdlKTtcblxuICAgIGlmKCFyZXN1bHRfZGVmaW5lZCAmJiAhZXJyb3JfZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZDogXCIrbWVzc2FnZSk7XG5cbiAgICByZXN1bHQuYWNrID0gcmVzdWx0LmlkO1xuICAgIGRlbGV0ZSByZXN1bHQuaWQ7XG4gIH1cblxuICAvLyBSZXR1cm4gdW5wYWNrZWQgbWVzc2FnZVxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuXG5leHBvcnRzLnBhY2sgICA9IHBhY2s7XG5leHBvcnRzLnVucGFjayA9IHVucGFjaztcbiIsImZ1bmN0aW9uIHBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5mdW5jdGlvbiB1bnBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5cbmV4cG9ydHMucGFjayAgID0gcGFjaztcbmV4cG9ydHMudW5wYWNrID0gdW5wYWNrO1xuIiwidmFyIEpzb25SUEMgPSByZXF1aXJlKCcuL0pzb25SUEMnKTtcbnZhciBYbWxSUEMgID0gcmVxdWlyZSgnLi9YbWxSUEMnKTtcblxuXG5leHBvcnRzLkpzb25SUEMgPSBKc29uUlBDO1xuZXhwb3J0cy5YbWxSUEMgID0gWG1sUlBDO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNC0yMDE1IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG52YXIgZnJlZWljZSA9IHJlcXVpcmUoJ2ZyZWVpY2UnKVxudmFyIGluaGVyaXRzID0gcmVxdWlyZSgnaW5oZXJpdHMnKVxudmFyIFVBUGFyc2VyID0gcmVxdWlyZSgndWEtcGFyc2VyLWpzJylcbnZhciB1dWlkID0gcmVxdWlyZSgndXVpZCcpXG52YXIgaGFyayA9IHJlcXVpcmUoJ2hhcmsnKVxuXG52YXIgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnZXZlbnRzJykuRXZlbnRFbWl0dGVyXG52YXIgcmVjdXJzaXZlID0gcmVxdWlyZSgnbWVyZ2UnKS5yZWN1cnNpdmUuYmluZCh1bmRlZmluZWQsIHRydWUpXG52YXIgc2RwVHJhbnNsYXRvciA9IHJlcXVpcmUoJ3NkcC10cmFuc2xhdG9yJylcbnZhciBsb2dnZXIgPSB3aW5kb3cuTG9nZ2VyIHx8IGNvbnNvbGVcblxuLy8gdmFyIGdVTSA9IG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhIHx8IGZ1bmN0aW9uIChjb25zdHJhaW50cykge1xuLy8gICByZXR1cm4gbmV3IFByb21pc2UobmF2aWdhdG9yLmdldFVzZXJNZWRpYShjb25zdHJhaW50cywgZnVuY3Rpb24gKHN0cmVhbSkge1xuLy8gICAgIHZpZGVvU3RyZWFtID0gc3RyZWFtXG4vLyAgICAgc3RhcnQoKVxuLy8gICB9KS5lcm9yKGNhbGxiYWNrKSk7XG4vLyB9XG5cbi8qdHJ5IHtcbiAgcmVxdWlyZSgna3VyZW50by1icm93c2VyLWV4dGVuc2lvbnMnKVxufSBjYXRjaCAoZXJyb3IpIHtcbiAgaWYgKHR5cGVvZiBnZXRTY3JlZW5Db25zdHJhaW50cyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBsb2dnZXIud2Fybignc2NyZWVuIHNoYXJpbmcgaXMgbm90IGF2YWlsYWJsZScpXG5cbiAgICBnZXRTY3JlZW5Db25zdHJhaW50cyA9IGZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKHNlbmRTb3VyY2UsIGNhbGxiYWNrKSB7XG4gICAgICBjYWxsYmFjayhuZXcgRXJyb3IoXCJUaGlzIGxpYnJhcnkgaXMgbm90IGVuYWJsZWQgZm9yIHNjcmVlbiBzaGFyaW5nXCIpKVxuICAgIH1cbiAgfVxufSovXG5cbnZhciBNRURJQV9DT05TVFJBSU5UUyA9IHtcbiAgYXVkaW86IHRydWUsXG4gIHZpZGVvOiB7XG4gICAgd2lkdGg6IDY0MCxcbiAgICBmcmFtZXJhdGU6IDE1XG4gIH1cbn1cblxuLy8gU29tZWhvdywgdGhlIFVBUGFyc2VyIGNvbnN0cnVjdG9yIGdldHMgYW4gZW1wdHkgd2luZG93IG9iamVjdC5cbi8vIFdlIG5lZWQgdG8gcGFzcyB0aGUgdXNlciBhZ2VudCBzdHJpbmcgaW4gb3JkZXIgdG8gZ2V0IGluZm9ybWF0aW9uXG52YXIgdWEgPSAod2luZG93ICYmIHdpbmRvdy5uYXZpZ2F0b3IpID8gd2luZG93Lm5hdmlnYXRvci51c2VyQWdlbnQgOiAnJ1xudmFyIHBhcnNlciA9IG5ldyBVQVBhcnNlcih1YSlcbnZhciBicm93c2VyID0gcGFyc2VyLmdldEJyb3dzZXIoKVxuXG52YXIgdXNlUGxhbkIgPSBmYWxzZVxuaWYgKGJyb3dzZXIubmFtZSA9PT0gJ0Nocm9tZScgfHwgYnJvd3Nlci5uYW1lID09PSAnQ2hyb21pdW0nKSB7XG4gIGxvZ2dlci5kZWJ1Zyhicm93c2VyLm5hbWUgKyBcIjogdXNpbmcgU0RQIFBsYW5CXCIpXG4gIHVzZVBsYW5CID0gdHJ1ZVxufVxuXG5mdW5jdGlvbiBub29wKGVycm9yKSB7XG4gIGlmIChlcnJvcikgbG9nZ2VyLmVycm9yKGVycm9yKVxufVxuXG5mdW5jdGlvbiB0cmFja1N0b3AodHJhY2spIHtcbiAgdHJhY2suc3RvcCAmJiB0cmFjay5zdG9wKClcbn1cblxuZnVuY3Rpb24gc3RyZWFtU3RvcChzdHJlYW0pIHtcbiAgc3RyZWFtLmdldFRyYWNrcygpLmZvckVhY2godHJhY2tTdG9wKVxufVxuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBTZXNzaW9uRGVzY3JpcHRpb24gb2JqZWN0LlxuICovXG52YXIgZHVtcFNEUCA9IGZ1bmN0aW9uIChkZXNjcmlwdGlvbikge1xuICBpZiAodHlwZW9mIGRlc2NyaXB0aW9uID09PSAndW5kZWZpbmVkJyB8fCBkZXNjcmlwdGlvbiA9PT0gbnVsbCkge1xuICAgIHJldHVybiAnJ1xuICB9XG5cbiAgcmV0dXJuICd0eXBlOiAnICsgZGVzY3JpcHRpb24udHlwZSArICdcXHJcXG4nICsgZGVzY3JpcHRpb24uc2RwXG59XG5cbmZ1bmN0aW9uIGJ1ZmZlcml6ZUNhbmRpZGF0ZXMocGMsIG9uZXJyb3IpIHtcbiAgdmFyIGNhbmRpZGF0ZXNRdWV1ZSA9IFtdXG5cbiAgcGMuYWRkRXZlbnRMaXN0ZW5lcignc2lnbmFsaW5nc3RhdGVjaGFuZ2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMuc2lnbmFsaW5nU3RhdGUgPT09ICdzdGFibGUnKSB7XG4gICAgICB3aGlsZSAoY2FuZGlkYXRlc1F1ZXVlLmxlbmd0aCkge1xuICAgICAgICB2YXIgZW50cnkgPSBjYW5kaWRhdGVzUXVldWUuc2hpZnQoKVxuXG4gICAgICAgIHRoaXMuYWRkSWNlQ2FuZGlkYXRlKGVudHJ5LmNhbmRpZGF0ZSwgZW50cnkuY2FsbGJhY2ssIGVudHJ5LmNhbGxiYWNrKVxuICAgICAgfVxuICAgIH1cbiAgfSlcblxuICByZXR1cm4gZnVuY3Rpb24gKGNhbmRpZGF0ZSwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IGNhbGxiYWNrIHx8IG9uZXJyb3JcblxuICAgIHN3aXRjaCAocGMuc2lnbmFsaW5nU3RhdGUpIHtcbiAgICBjYXNlICdjbG9zZWQnOlxuICAgICAgY2FsbGJhY2sobmV3IEVycm9yKCdQZWVyQ29ubmVjdGlvbiBvYmplY3QgaXMgY2xvc2VkJykpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnc3RhYmxlJzpcbiAgICAgIGlmIChwYy5yZW1vdGVEZXNjcmlwdGlvbikge1xuICAgICAgICBwYy5hZGRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlLCBjYWxsYmFjaywgY2FsbGJhY2spO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgZGVmYXVsdDpcbiAgICAgIGNhbmRpZGF0ZXNRdWV1ZS5wdXNoKHtcbiAgICAgICAgY2FuZGlkYXRlOiBjYW5kaWRhdGUsXG4gICAgICAgIGNhbGxiYWNrOiBjYWxsYmFja1xuICAgICAgfSlcbiAgICB9XG4gIH1cbn1cblxuLyogU2ltdWxjYXN0IHV0aWxpdGllcyAqL1xuXG5mdW5jdGlvbiByZW1vdmVGSURGcm9tT2ZmZXIoc2RwKSB7XG4gIHZhciBuID0gc2RwLmluZGV4T2YoXCJhPXNzcmMtZ3JvdXA6RklEXCIpO1xuXG4gIGlmIChuID4gMCkge1xuICAgIHJldHVybiBzZHAuc2xpY2UoMCwgbik7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHNkcDtcbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRTaW11bGNhc3RJbmZvKHZpZGVvU3RyZWFtKSB7XG4gIHZhciB2aWRlb1RyYWNrcyA9IHZpZGVvU3RyZWFtLmdldFZpZGVvVHJhY2tzKCk7XG4gIGlmICghdmlkZW9UcmFja3MubGVuZ3RoKSB7XG4gICAgbG9nZ2VyLndhcm4oJ05vIHZpZGVvIHRyYWNrcyBhdmFpbGFibGUgaW4gdGhlIHZpZGVvIHN0cmVhbScpXG4gICAgcmV0dXJuICcnXG4gIH1cbiAgdmFyIGxpbmVzID0gW1xuICAgICdhPXgtZ29vZ2xlLWZsYWc6Y29uZmVyZW5jZScsXG4gICAgJ2E9c3NyYy1ncm91cDpTSU0gMSAyIDMnLFxuICAgICdhPXNzcmM6MSBjbmFtZTpsb2NhbFZpZGVvJyxcbiAgICAnYT1zc3JjOjEgbXNpZDonICsgdmlkZW9TdHJlYW0uaWQgKyAnICcgKyB2aWRlb1RyYWNrc1swXS5pZCxcbiAgICAnYT1zc3JjOjEgbXNsYWJlbDonICsgdmlkZW9TdHJlYW0uaWQsXG4gICAgJ2E9c3NyYzoxIGxhYmVsOicgKyB2aWRlb1RyYWNrc1swXS5pZCxcbiAgICAnYT1zc3JjOjIgY25hbWU6bG9jYWxWaWRlbycsXG4gICAgJ2E9c3NyYzoyIG1zaWQ6JyArIHZpZGVvU3RyZWFtLmlkICsgJyAnICsgdmlkZW9UcmFja3NbMF0uaWQsXG4gICAgJ2E9c3NyYzoyIG1zbGFiZWw6JyArIHZpZGVvU3RyZWFtLmlkLFxuICAgICdhPXNzcmM6MiBsYWJlbDonICsgdmlkZW9UcmFja3NbMF0uaWQsXG4gICAgJ2E9c3NyYzozIGNuYW1lOmxvY2FsVmlkZW8nLFxuICAgICdhPXNzcmM6MyBtc2lkOicgKyB2aWRlb1N0cmVhbS5pZCArICcgJyArIHZpZGVvVHJhY2tzWzBdLmlkLFxuICAgICdhPXNzcmM6MyBtc2xhYmVsOicgKyB2aWRlb1N0cmVhbS5pZCxcbiAgICAnYT1zc3JjOjMgbGFiZWw6JyArIHZpZGVvVHJhY2tzWzBdLmlkXG4gIF07XG5cbiAgbGluZXMucHVzaCgnJyk7XG5cbiAgcmV0dXJuIGxpbmVzLmpvaW4oJ1xcbicpO1xufVxuXG4vKipcbiAqIFdyYXBwZXIgb2JqZWN0IG9mIGFuIFJUQ1BlZXJDb25uZWN0aW9uLiBUaGlzIG9iamVjdCBpcyBhaW1lZCB0byBzaW1wbGlmeSB0aGVcbiAqIGRldmVsb3BtZW50IG9mIFdlYlJUQy1iYXNlZCBhcHBsaWNhdGlvbnMuXG4gKlxuICogQGNvbnN0cnVjdG9yIG1vZHVsZTprdXJlbnRvVXRpbHMuV2ViUnRjUGVlclxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtb2RlIE1vZGUgaW4gd2hpY2ggdGhlIFBlZXJDb25uZWN0aW9uIHdpbGwgYmUgY29uZmlndXJlZC5cbiAqICBWYWxpZCB2YWx1ZXMgYXJlOiAncmVjdicsICdzZW5kJywgYW5kICdzZW5kUmVjdidcbiAqIEBwYXJhbSBsb2NhbFZpZGVvIFZpZGVvIHRhZyBmb3IgdGhlIGxvY2FsIHN0cmVhbVxuICogQHBhcmFtIHJlbW90ZVZpZGVvIFZpZGVvIHRhZyBmb3IgdGhlIHJlbW90ZSBzdHJlYW1cbiAqIEBwYXJhbSB7TWVkaWFTdHJlYW19IHZpZGVvU3RyZWFtIFN0cmVhbSB0byBiZSB1c2VkIGFzIHByaW1hcnkgc291cmNlXG4gKiAgKHR5cGljYWxseSB2aWRlbyBhbmQgYXVkaW8sIG9yIG9ubHkgdmlkZW8gaWYgY29tYmluZWQgd2l0aCBhdWRpb1N0cmVhbSkgZm9yXG4gKiAgbG9jYWxWaWRlbyBhbmQgdG8gYmUgYWRkZWQgYXMgc3RyZWFtIHRvIHRoZSBSVENQZWVyQ29ubmVjdGlvblxuICogQHBhcmFtIHtNZWRpYVN0cmVhbX0gYXVkaW9TdHJlYW0gU3RyZWFtIHRvIGJlIHVzZWQgYXMgc2Vjb25kIHNvdXJjZVxuICogICh0eXBpY2FsbHkgZm9yIGF1ZGlvKSBmb3IgbG9jYWxWaWRlbyBhbmQgdG8gYmUgYWRkZWQgYXMgc3RyZWFtIHRvIHRoZVxuICogIFJUQ1BlZXJDb25uZWN0aW9uXG4gKi9cbmZ1bmN0aW9uIFdlYlJ0Y1BlZXIobW9kZSwgb3B0aW9ucywgY2FsbGJhY2spIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFdlYlJ0Y1BlZXIpKSB7XG4gICAgcmV0dXJuIG5ldyBXZWJSdGNQZWVyKG1vZGUsIG9wdGlvbnMsIGNhbGxiYWNrKVxuICB9XG5cbiAgV2ViUnRjUGVlci5zdXBlcl8uY2FsbCh0aGlzKVxuXG4gIGlmIChvcHRpb25zIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICBjYWxsYmFjayA9IG9wdGlvbnNcbiAgICBvcHRpb25zID0gdW5kZWZpbmVkXG4gIH1cblxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuICBjYWxsYmFjayA9IChjYWxsYmFjayB8fCBub29wKS5iaW5kKHRoaXMpXG5cbiAgdmFyIHNlbGYgPSB0aGlzXG4gIHZhciBsb2NhbFZpZGVvID0gb3B0aW9ucy5sb2NhbFZpZGVvXG4gIHZhciByZW1vdGVWaWRlbyA9IG9wdGlvbnMucmVtb3RlVmlkZW9cbiAgdmFyIHZpZGVvU3RyZWFtID0gb3B0aW9ucy52aWRlb1N0cmVhbVxuICB2YXIgYXVkaW9TdHJlYW0gPSBvcHRpb25zLmF1ZGlvU3RyZWFtXG4gIHZhciBtZWRpYUNvbnN0cmFpbnRzID0gb3B0aW9ucy5tZWRpYUNvbnN0cmFpbnRzXG5cbiAgdmFyIGNvbm5lY3Rpb25Db25zdHJhaW50cyA9IG9wdGlvbnMuY29ubmVjdGlvbkNvbnN0cmFpbnRzXG4gIHZhciBwYyA9IG9wdGlvbnMucGVlckNvbm5lY3Rpb25cbiAgdmFyIHNlbmRTb3VyY2UgPSBvcHRpb25zLnNlbmRTb3VyY2UgfHwgJ3dlYmNhbSdcblxuICB2YXIgZGF0YUNoYW5uZWxDb25maWcgPSBvcHRpb25zLmRhdGFDaGFubmVsQ29uZmlnXG4gIHZhciB1c2VEYXRhQ2hhbm5lbHMgPSBvcHRpb25zLmRhdGFDaGFubmVscyB8fCBmYWxzZVxuICB2YXIgZGF0YUNoYW5uZWxcblxuICB2YXIgZ3VpZCA9IHV1aWQudjQoKVxuICB2YXIgY29uZmlndXJhdGlvbiA9IHJlY3Vyc2l2ZSh7XG4gICAgICBpY2VTZXJ2ZXJzOiBmcmVlaWNlKClcbiAgICB9LFxuICAgIG9wdGlvbnMuY29uZmlndXJhdGlvbilcblxuICB2YXIgb25pY2VjYW5kaWRhdGUgPSBvcHRpb25zLm9uaWNlY2FuZGlkYXRlXG4gIGlmIChvbmljZWNhbmRpZGF0ZSkgdGhpcy5vbignaWNlY2FuZGlkYXRlJywgb25pY2VjYW5kaWRhdGUpXG5cbiAgdmFyIG9uY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IG9wdGlvbnMub25jYW5kaWRhdGVnYXRoZXJpbmdkb25lXG4gIGlmIChvbmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUpIHtcbiAgICB0aGlzLm9uKCdjYW5kaWRhdGVnYXRoZXJpbmdkb25lJywgb25jYW5kaWRhdGVnYXRoZXJpbmdkb25lKVxuICB9XG5cbiAgdmFyIHNpbXVsY2FzdCA9IG9wdGlvbnMuc2ltdWxjYXN0XG4gIHZhciBtdWx0aXN0cmVhbSA9IG9wdGlvbnMubXVsdGlzdHJlYW1cbiAgdmFyIGludGVyb3AgPSBuZXcgc2RwVHJhbnNsYXRvci5JbnRlcm9wKClcbiAgdmFyIGNhbmRpZGF0ZXNRdWV1ZU91dCA9IFtdXG4gIHZhciBjYW5kaWRhdGVnYXRoZXJpbmdkb25lID0gZmFsc2VcblxuICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyh0aGlzLCB7XG4gICAgJ3BlZXJDb25uZWN0aW9uJzoge1xuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBwY1xuICAgICAgfVxuICAgIH0sXG5cbiAgICAnaWQnOiB7XG4gICAgICB2YWx1ZTogb3B0aW9ucy5pZCB8fCBndWlkLFxuICAgICAgd3JpdGFibGU6IGZhbHNlXG4gICAgfSxcblxuICAgICdyZW1vdGVWaWRlbyc6IHtcbiAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gcmVtb3RlVmlkZW9cbiAgICAgIH1cbiAgICB9LFxuXG4gICAgJ2xvY2FsVmlkZW8nOiB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGxvY2FsVmlkZW9cbiAgICAgIH1cbiAgICB9LFxuXG4gICAgJ2RhdGFDaGFubmVsJzoge1xuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBkYXRhQ2hhbm5lbFxuICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBAbWVtYmVyIHsoZXh0ZXJuYWw6SW1hZ2VEYXRhfHVuZGVmaW5lZCl9IGN1cnJlbnRGcmFtZVxuICAgICAqL1xuICAgICdjdXJyZW50RnJhbWUnOiB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gW1RvRG9dIEZpbmQgc29sdXRpb24gd2hlbiB3ZSBoYXZlIGEgcmVtb3RlIHN0cmVhbSBidXQgd2UgZGlkbid0IHNldFxuICAgICAgICAvLyBhIHJlbW90ZVZpZGVvIHRhZ1xuICAgICAgICBpZiAoIXJlbW90ZVZpZGVvKSByZXR1cm47XG5cbiAgICAgICAgaWYgKHJlbW90ZVZpZGVvLnJlYWR5U3RhdGUgPCByZW1vdGVWaWRlby5IQVZFX0NVUlJFTlRfREFUQSlcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIHZpZGVvIHN0cmVhbSBkYXRhIGF2YWlsYWJsZScpXG5cbiAgICAgICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpXG4gICAgICAgIGNhbnZhcy53aWR0aCA9IHJlbW90ZVZpZGVvLnZpZGVvV2lkdGhcbiAgICAgICAgY2FudmFzLmhlaWdodCA9IHJlbW90ZVZpZGVvLnZpZGVvSGVpZ2h0XG5cbiAgICAgICAgY2FudmFzLmdldENvbnRleHQoJzJkJykuZHJhd0ltYWdlKHJlbW90ZVZpZGVvLCAwLCAwKVxuXG4gICAgICAgIHJldHVybiBjYW52YXNcbiAgICAgIH1cbiAgICB9XG4gIH0pXG5cbiAgLy8gSW5pdCBQZWVyQ29ubmVjdGlvblxuICBpZiAoIXBjKSB7XG4gICAgcGMgPSBuZXcgUlRDUGVlckNvbm5lY3Rpb24oY29uZmlndXJhdGlvbik7XG4gICAgaWYgKHVzZURhdGFDaGFubmVscyAmJiAhZGF0YUNoYW5uZWwpIHtcbiAgICAgIHZhciBkY0lkID0gJ1dlYlJ0Y1BlZXItJyArIHNlbGYuaWRcbiAgICAgIHZhciBkY09wdGlvbnMgPSB1bmRlZmluZWRcbiAgICAgIGlmIChkYXRhQ2hhbm5lbENvbmZpZykge1xuICAgICAgICBkY0lkID0gZGF0YUNoYW5uZWxDb25maWcuaWQgfHwgZGNJZFxuICAgICAgICBkY09wdGlvbnMgPSBkYXRhQ2hhbm5lbENvbmZpZy5vcHRpb25zXG4gICAgICB9XG4gICAgICBkYXRhQ2hhbm5lbCA9IHBjLmNyZWF0ZURhdGFDaGFubmVsKGRjSWQsIGRjT3B0aW9ucyk7XG4gICAgICBpZiAoZGF0YUNoYW5uZWxDb25maWcpIHtcbiAgICAgICAgZGF0YUNoYW5uZWwub25vcGVuID0gZGF0YUNoYW5uZWxDb25maWcub25vcGVuO1xuICAgICAgICBkYXRhQ2hhbm5lbC5vbmNsb3NlID0gZGF0YUNoYW5uZWxDb25maWcub25jbG9zZTtcbiAgICAgICAgZGF0YUNoYW5uZWwub25tZXNzYWdlID0gZGF0YUNoYW5uZWxDb25maWcub25tZXNzYWdlO1xuICAgICAgICBkYXRhQ2hhbm5lbC5vbmJ1ZmZlcmVkYW1vdW50bG93ID0gZGF0YUNoYW5uZWxDb25maWcub25idWZmZXJlZGFtb3VudGxvdztcbiAgICAgICAgZGF0YUNoYW5uZWwub25lcnJvciA9IGRhdGFDaGFubmVsQ29uZmlnLm9uZXJyb3IgfHwgbm9vcDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwYy5hZGRFdmVudExpc3RlbmVyKCdpY2VjYW5kaWRhdGUnLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB2YXIgY2FuZGlkYXRlID0gZXZlbnQuY2FuZGlkYXRlXG5cbiAgICBpZiAoRXZlbnRFbWl0dGVyLmxpc3RlbmVyQ291bnQoc2VsZiwgJ2ljZWNhbmRpZGF0ZScpIHx8XG4gICAgICBFdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudChcbiAgICAgICAgc2VsZiwgJ2NhbmRpZGF0ZWdhdGhlcmluZ2RvbmUnKSkge1xuICAgICAgaWYgKGNhbmRpZGF0ZSkge1xuICAgICAgICB2YXIgY2FuZFxuXG4gICAgICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgICAgIGNhbmQgPSBpbnRlcm9wLmNhbmRpZGF0ZVRvVW5pZmllZFBsYW4oY2FuZGlkYXRlKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNhbmQgPSBjYW5kaWRhdGVcbiAgICAgICAgfVxuXG4gICAgICAgIHNlbGYuZW1pdCgnaWNlY2FuZGlkYXRlJywgY2FuZClcbiAgICAgICAgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IGZhbHNlXG4gICAgICB9IGVsc2UgaWYgKCFjYW5kaWRhdGVnYXRoZXJpbmdkb25lKSB7XG4gICAgICAgIHNlbGYuZW1pdCgnY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScpXG4gICAgICAgIGNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSB0cnVlXG4gICAgICB9XG4gICAgfSBlbHNlIGlmICghY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSkge1xuICAgICAgLy8gTm90IGxpc3RlbmluZyB0byAnaWNlY2FuZGlkYXRlJyBvciAnY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScgZXZlbnRzLCBxdWV1ZVxuICAgICAgLy8gdGhlIGNhbmRpZGF0ZSB1bnRpbCBvbmUgb2YgdGhlbSBpcyBsaXN0ZW5lZFxuICAgICAgY2FuZGlkYXRlc1F1ZXVlT3V0LnB1c2goY2FuZGlkYXRlKVxuXG4gICAgICBpZiAoIWNhbmRpZGF0ZSkgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IHRydWVcbiAgICB9XG4gIH0pXG5cbiAgcGMub250cmFjayA9IG9wdGlvbnMub25hZGRzdHJlYW1cbiAgcGMub25uZWdvdGlhdGlvbm5lZWRlZCA9IG9wdGlvbnMub25uZWdvdGlhdGlvbm5lZWRlZFxuICB0aGlzLm9uKCduZXdMaXN0ZW5lcicsIGZ1bmN0aW9uIChldmVudCwgbGlzdGVuZXIpIHtcbiAgICBpZiAoZXZlbnQgPT09ICdpY2VjYW5kaWRhdGUnIHx8IGV2ZW50ID09PSAnY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScpIHtcbiAgICAgIHdoaWxlIChjYW5kaWRhdGVzUXVldWVPdXQubGVuZ3RoKSB7XG4gICAgICAgIHZhciBjYW5kaWRhdGUgPSBjYW5kaWRhdGVzUXVldWVPdXQuc2hpZnQoKVxuXG4gICAgICAgIGlmICghY2FuZGlkYXRlID09PSAoZXZlbnQgPT09ICdjYW5kaWRhdGVnYXRoZXJpbmdkb25lJykpIHtcbiAgICAgICAgICBsaXN0ZW5lcihjYW5kaWRhdGUpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH0pXG5cbiAgdmFyIGFkZEljZUNhbmRpZGF0ZSA9IGJ1ZmZlcml6ZUNhbmRpZGF0ZXMocGMpXG5cbiAgLyoqXG4gICAqIENhbGxiYWNrIGZ1bmN0aW9uIGludm9rZWQgd2hlbiBhbiBJQ0UgY2FuZGlkYXRlIGlzIHJlY2VpdmVkLiBEZXZlbG9wZXJzIGFyZVxuICAgKiBleHBlY3RlZCB0byBpbnZva2UgdGhpcyBmdW5jdGlvbiBpbiBvcmRlciB0byBjb21wbGV0ZSB0aGUgU0RQIG5lZ290aWF0aW9uLlxuICAgKlxuICAgKiBAZnVuY3Rpb24gbW9kdWxlOmt1cmVudG9VdGlscy5XZWJSdGNQZWVyLnByb3RvdHlwZS5hZGRJY2VDYW5kaWRhdGVcbiAgICpcbiAgICogQHBhcmFtIGljZUNhbmRpZGF0ZSAtIExpdGVyYWwgb2JqZWN0IHdpdGggdGhlIElDRSBjYW5kaWRhdGUgZGVzY3JpcHRpb25cbiAgICogQHBhcmFtIGNhbGxiYWNrIC0gQ2FsbGVkIHdoZW4gdGhlIElDRSBjYW5kaWRhdGUgaGFzIGJlZW4gYWRkZWQuXG4gICAqL1xuICB0aGlzLmFkZEljZUNhbmRpZGF0ZSA9IGZ1bmN0aW9uIChpY2VDYW5kaWRhdGUsIGNhbGxiYWNrKSB7XG4gICAgdmFyIGNhbmRpZGF0ZVxuXG4gICAgaWYgKG11bHRpc3RyZWFtICYmIHVzZVBsYW5CKSB7XG4gICAgICBjYW5kaWRhdGUgPSBpbnRlcm9wLmNhbmRpZGF0ZVRvUGxhbkIoaWNlQ2FuZGlkYXRlKVxuICAgIH0gZWxzZSB7XG4gICAgICBjYW5kaWRhdGUgPSBuZXcgUlRDSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZSlcbiAgICB9XG5cbiAgICBsb2dnZXIuZGVidWcoJ1JlbW90ZSBJQ0UgY2FuZGlkYXRlIHJlY2VpdmVkJywgaWNlQ2FuZGlkYXRlKVxuICAgIGNhbGxiYWNrID0gKGNhbGxiYWNrIHx8IG5vb3ApLmJpbmQodGhpcylcbiAgICBhZGRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlLCBjYWxsYmFjaylcbiAgfVxuXG4gIHRoaXMuZ2VuZXJhdGVPZmZlciA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2suYmluZCh0aGlzKVxuXG4gICAgdmFyIG9mZmVyQXVkaW8gPSB0cnVlXG4gICAgdmFyIG9mZmVyVmlkZW8gPSB0cnVlXG4gICAgLy8gQ29uc3RyYWludHMgbXVzdCBoYXZlIGJvdGggYmxvY2tzXG4gICAgaWYgKG1lZGlhQ29uc3RyYWludHMpIHtcbiAgICAgIG9mZmVyQXVkaW8gPSAodHlwZW9mIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPT09ICdib29sZWFuJykgP1xuICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIDogdHJ1ZVxuICAgICAgb2ZmZXJWaWRlbyA9ICh0eXBlb2YgbWVkaWFDb25zdHJhaW50cy52aWRlbyA9PT0gJ2Jvb2xlYW4nKSA/XG4gICAgICAgIG1lZGlhQ29uc3RyYWludHMudmlkZW8gOiB0cnVlXG4gICAgfVxuXG4gICAgdmFyIGJyb3dzZXJEZXBlbmRhbnRDb25zdHJhaW50cyA9IHtcbiAgICAgIG9mZmVyVG9SZWNlaXZlQXVkaW86IChtb2RlICE9PSAnc2VuZG9ubHknICYmIG9mZmVyQXVkaW8pLFxuICAgICAgb2ZmZXJUb1JlY2VpdmVWaWRlbzogKG1vZGUgIT09ICdzZW5kb25seScgJiYgb2ZmZXJWaWRlbylcbiAgICB9XG5cbiAgICAvL0ZJWE1FOiBjbGFyaWZ5IHBvc3NpYmxlIGNvbnN0cmFpbnRzIHBhc3NlZCB0byBjcmVhdGVPZmZlcigpXG4gICAgLyp2YXIgY29uc3RyYWludHMgPSByZWN1cnNpdmUoYnJvd3NlckRlcGVuZGFudENvbnN0cmFpbnRzLFxuICAgICAgY29ubmVjdGlvbkNvbnN0cmFpbnRzKSovXG5cbiAgICB2YXIgY29uc3RyYWludHMgPSBicm93c2VyRGVwZW5kYW50Q29uc3RyYWludHM7XG5cbiAgICBsb2dnZXIuZGVidWcoJ2NvbnN0cmFpbnRzOiAnICsgSlNPTi5zdHJpbmdpZnkoY29uc3RyYWludHMpKVxuXG4gICAgcGMuY3JlYXRlT2ZmZXIoY29uc3RyYWludHMpLnRoZW4oZnVuY3Rpb24gKG9mZmVyKSB7XG4gICAgICBsb2dnZXIuZGVidWcoJ0NyZWF0ZWQgU0RQIG9mZmVyJylcbiAgICAgIG9mZmVyID0gbWFuZ2xlU2RwVG9BZGRTaW11bGNhc3Qob2ZmZXIpXG4gICAgICByZXR1cm4gcGMuc2V0TG9jYWxEZXNjcmlwdGlvbihvZmZlcilcbiAgICB9KS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBsb2NhbERlc2NyaXB0aW9uID0gcGMubG9jYWxEZXNjcmlwdGlvblxuICAgICAgbG9nZ2VyLmRlYnVnKCdMb2NhbCBkZXNjcmlwdGlvbiBzZXQnLCBsb2NhbERlc2NyaXB0aW9uLnNkcClcbiAgICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgICBsb2NhbERlc2NyaXB0aW9uID0gaW50ZXJvcC50b1VuaWZpZWRQbGFuKGxvY2FsRGVzY3JpcHRpb24pXG4gICAgICAgIGxvZ2dlci5kZWJ1Zygnb2ZmZXI6Om9yaWdQbGFuQi0+VW5pZmllZFBsYW4nLCBkdW1wU0RQKFxuICAgICAgICAgIGxvY2FsRGVzY3JpcHRpb24pKVxuICAgICAgfVxuICAgICAgY2FsbGJhY2sobnVsbCwgbG9jYWxEZXNjcmlwdGlvbi5zZHAsIHNlbGYucHJvY2Vzc0Fuc3dlci5iaW5kKFxuICAgICAgICBzZWxmKSlcbiAgICB9KS5jYXRjaChjYWxsYmFjaylcbiAgfVxuXG4gIHRoaXMuZ2V0TG9jYWxTZXNzaW9uRGVzY3JpcHRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gcGMubG9jYWxEZXNjcmlwdGlvblxuICB9XG5cbiAgdGhpcy5nZXRSZW1vdGVTZXNzaW9uRGVzY3JpcHRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gcGMucmVtb3RlRGVzY3JpcHRpb25cbiAgfVxuXG4gIGZ1bmN0aW9uIHNldFJlbW90ZVZpZGVvKCkge1xuICAgIGlmIChyZW1vdGVWaWRlbykge1xuICAgICAgdmFyIHN0cmVhbSA9IHBjLmdldFJlbW90ZVN0cmVhbXMoKVswXVxuICAgICAgdmFyIHVybCA9IHN0cmVhbSA/IFVSTC5jcmVhdGVPYmplY3RVUkwoc3RyZWFtKSA6ICcnXG5cbiAgICAgIHJlbW90ZVZpZGVvLnBhdXNlKClcbiAgICAgIHJlbW90ZVZpZGVvLnNyYyA9IHVybFxuICAgICAgcmVtb3RlVmlkZW8ubG9hZCgpXG5cbiAgICAgIGxvZ2dlci5kZWJ1ZygnUmVtb3RlIFVSTDonLCB1cmwpXG4gICAgfVxuICB9XG5cbiAgdGhpcy5zaG93TG9jYWxWaWRlbyA9IGZ1bmN0aW9uICgpIHtcbiAgICBsb2NhbFZpZGVvLnNyYyA9IFVSTC5jcmVhdGVPYmplY3RVUkwodmlkZW9TdHJlYW0pXG4gICAgbG9jYWxWaWRlby5tdXRlZCA9IHRydWVcbiAgfVxuXG4gIHRoaXMuc2VuZCA9IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgaWYgKGRhdGFDaGFubmVsICYmIGRhdGFDaGFubmVsLnJlYWR5U3RhdGUgPT09ICdvcGVuJykge1xuICAgICAgZGF0YUNoYW5uZWwuc2VuZChkYXRhKVxuICAgIH0gZWxzZSB7XG4gICAgICBsb2dnZXIud2FybihcbiAgICAgICAgJ1RyeWluZyB0byBzZW5kIGRhdGEgb3ZlciBhIG5vbi1leGlzdGluZyBvciBjbG9zZWQgZGF0YSBjaGFubmVsJylcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2FsbGJhY2sgZnVuY3Rpb24gaW52b2tlZCB3aGVuIGEgU0RQIGFuc3dlciBpcyByZWNlaXZlZC4gRGV2ZWxvcGVycyBhcmVcbiAgICogZXhwZWN0ZWQgdG8gaW52b2tlIHRoaXMgZnVuY3Rpb24gaW4gb3JkZXIgdG8gY29tcGxldGUgdGhlIFNEUCBuZWdvdGlhdGlvbi5cbiAgICpcbiAgICogQGZ1bmN0aW9uIG1vZHVsZTprdXJlbnRvVXRpbHMuV2ViUnRjUGVlci5wcm90b3R5cGUucHJvY2Vzc0Fuc3dlclxuICAgKlxuICAgKiBAcGFyYW0gc2RwQW5zd2VyIC0gRGVzY3JpcHRpb24gb2Ygc2RwQW5zd2VyXG4gICAqIEBwYXJhbSBjYWxsYmFjayAtXG4gICAqICAgICAgICAgICAgSW52b2tlZCBhZnRlciB0aGUgU0RQIGFuc3dlciBpcyBwcm9jZXNzZWQsIG9yIHRoZXJlIGlzIGFuIGVycm9yLlxuICAgKi9cbiAgdGhpcy5wcm9jZXNzQW5zd2VyID0gZnVuY3Rpb24gKHNkcEFuc3dlciwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IChjYWxsYmFjayB8fCBub29wKS5iaW5kKHRoaXMpXG5cbiAgICB2YXIgYW5zd2VyID0gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICB0eXBlOiAnYW5zd2VyJyxcbiAgICAgIHNkcDogc2RwQW5zd2VyXG4gICAgfSlcblxuICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgdmFyIHBsYW5CQW5zd2VyID0gaW50ZXJvcC50b1BsYW5CKGFuc3dlcilcbiAgICAgIGxvZ2dlci5kZWJ1ZygnYXNud2VyOjpwbGFuQicsIGR1bXBTRFAocGxhbkJBbnN3ZXIpKVxuICAgICAgYW5zd2VyID0gcGxhbkJBbnN3ZXJcbiAgICB9XG5cbiAgICBsb2dnZXIuZGVidWcoJ1NEUCBhbnN3ZXIgcmVjZWl2ZWQsIHNldHRpbmcgcmVtb3RlIGRlc2NyaXB0aW9uJylcblxuICAgIGlmIChwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgIHJldHVybiBjYWxsYmFjaygnUGVlckNvbm5lY3Rpb24gaXMgY2xvc2VkJylcbiAgICB9XG5cbiAgICBwYy5zZXRSZW1vdGVEZXNjcmlwdGlvbihhbnN3ZXIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgc2V0UmVtb3RlVmlkZW8oKVxuXG4gICAgICAgIGNhbGxiYWNrKClcbiAgICAgIH0sXG4gICAgICBjYWxsYmFjaylcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayBmdW5jdGlvbiBpbnZva2VkIHdoZW4gYSBTRFAgb2ZmZXIgaXMgcmVjZWl2ZWQuIERldmVsb3BlcnMgYXJlXG4gICAqIGV4cGVjdGVkIHRvIGludm9rZSB0aGlzIGZ1bmN0aW9uIGluIG9yZGVyIHRvIGNvbXBsZXRlIHRoZSBTRFAgbmVnb3RpYXRpb24uXG4gICAqXG4gICAqIEBmdW5jdGlvbiBtb2R1bGU6a3VyZW50b1V0aWxzLldlYlJ0Y1BlZXIucHJvdG90eXBlLnByb2Nlc3NPZmZlclxuICAgKlxuICAgKiBAcGFyYW0gc2RwT2ZmZXIgLSBEZXNjcmlwdGlvbiBvZiBzZHBPZmZlclxuICAgKiBAcGFyYW0gY2FsbGJhY2sgLSBDYWxsZWQgd2hlbiB0aGUgcmVtb3RlIGRlc2NyaXB0aW9uIGhhcyBiZWVuIHNldFxuICAgKiAgc3VjY2Vzc2Z1bGx5LlxuICAgKi9cbiAgdGhpcy5wcm9jZXNzT2ZmZXIgPSBmdW5jdGlvbiAoc2RwT2ZmZXIsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSBjYWxsYmFjay5iaW5kKHRoaXMpXG5cbiAgICB2YXIgb2ZmZXIgPSBuZXcgUlRDU2Vzc2lvbkRlc2NyaXB0aW9uKHtcbiAgICAgIHR5cGU6ICdvZmZlcicsXG4gICAgICBzZHA6IHNkcE9mZmVyXG4gICAgfSlcblxuICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgdmFyIHBsYW5CT2ZmZXIgPSBpbnRlcm9wLnRvUGxhbkIob2ZmZXIpXG4gICAgICBsb2dnZXIuZGVidWcoJ29mZmVyOjpwbGFuQicsIGR1bXBTRFAocGxhbkJPZmZlcikpXG4gICAgICBvZmZlciA9IHBsYW5CT2ZmZXJcbiAgICB9XG5cbiAgICBsb2dnZXIuZGVidWcoJ1NEUCBvZmZlciByZWNlaXZlZCwgc2V0dGluZyByZW1vdGUgZGVzY3JpcHRpb24nKVxuXG4gICAgaWYgKHBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKCdQZWVyQ29ubmVjdGlvbiBpcyBjbG9zZWQnKVxuICAgIH1cblxuICAgIHBjLnNldFJlbW90ZURlc2NyaXB0aW9uKG9mZmVyKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBzZXRSZW1vdGVWaWRlbygpXG4gICAgfSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gcGMuY3JlYXRlQW5zd2VyKClcbiAgICB9KS50aGVuKGZ1bmN0aW9uIChhbnN3ZXIpIHtcbiAgICAgIGFuc3dlciA9IG1hbmdsZVNkcFRvQWRkU2ltdWxjYXN0KGFuc3dlcilcbiAgICAgIGxvZ2dlci5kZWJ1ZygnQ3JlYXRlZCBTRFAgYW5zd2VyJylcbiAgICAgIHJldHVybiBwYy5zZXRMb2NhbERlc2NyaXB0aW9uKGFuc3dlcilcbiAgICB9KS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBsb2NhbERlc2NyaXB0aW9uID0gcGMubG9jYWxEZXNjcmlwdGlvblxuICAgICAgaWYgKG11bHRpc3RyZWFtICYmIHVzZVBsYW5CKSB7XG4gICAgICAgIGxvY2FsRGVzY3JpcHRpb24gPSBpbnRlcm9wLnRvVW5pZmllZFBsYW4obG9jYWxEZXNjcmlwdGlvbilcbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdhbnN3ZXI6Om9yaWdQbGFuQi0+VW5pZmllZFBsYW4nLCBkdW1wU0RQKFxuICAgICAgICAgIGxvY2FsRGVzY3JpcHRpb24pKVxuICAgICAgfVxuICAgICAgbG9nZ2VyLmRlYnVnKCdMb2NhbCBkZXNjcmlwdGlvbiBzZXQnLCBsb2NhbERlc2NyaXB0aW9uLnNkcClcbiAgICAgIGNhbGxiYWNrKG51bGwsIGxvY2FsRGVzY3JpcHRpb24uc2RwKVxuICAgIH0pLmNhdGNoKGNhbGxiYWNrKVxuICB9XG5cbiAgZnVuY3Rpb24gbWFuZ2xlU2RwVG9BZGRTaW11bGNhc3QoYW5zd2VyKSB7XG4gICAgaWYgKHNpbXVsY2FzdCkge1xuICAgICAgaWYgKGJyb3dzZXIubmFtZSA9PT0gJ0Nocm9tZScgfHwgYnJvd3Nlci5uYW1lID09PSAnQ2hyb21pdW0nKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnQWRkaW5nIG11bHRpY2FzdCBpbmZvJylcbiAgICAgICAgYW5zd2VyID0gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICAgICAgJ3R5cGUnOiBhbnN3ZXIudHlwZSxcbiAgICAgICAgICAnc2RwJzogcmVtb3ZlRklERnJvbU9mZmVyKGFuc3dlci5zZHApICsgZ2V0U2ltdWxjYXN0SW5mbyhcbiAgICAgICAgICAgIHZpZGVvU3RyZWFtKVxuICAgICAgICB9KVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ1NpbXVsY2FzdCBpcyBvbmx5IGF2YWlsYWJsZSBpbiBDaHJvbWUgYnJvd3Nlci4nKVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBhbnN3ZXJcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIGZ1bmN0aW9uIGNyZWF0ZXMgdGhlIFJUQ1BlZXJDb25uZWN0aW9uIG9iamVjdCB0YWtpbmcgaW50byBhY2NvdW50IHRoZVxuICAgKiBwcm9wZXJ0aWVzIHJlY2VpdmVkIGluIHRoZSBjb25zdHJ1Y3Rvci4gSXQgc3RhcnRzIHRoZSBTRFAgbmVnb3RpYXRpb25cbiAgICogcHJvY2VzczogZ2VuZXJhdGVzIHRoZSBTRFAgb2ZmZXIgYW5kIGludm9rZXMgdGhlIG9uc2Rwb2ZmZXIgY2FsbGJhY2suIFRoaXNcbiAgICogY2FsbGJhY2sgaXMgZXhwZWN0ZWQgdG8gc2VuZCB0aGUgU0RQIG9mZmVyLCBpbiBvcmRlciB0byBvYnRhaW4gYW4gU0RQXG4gICAqIGFuc3dlciBmcm9tIGFub3RoZXIgcGVlci5cbiAgICovXG4gIGZ1bmN0aW9uIHN0YXJ0KCkge1xuICAgIGlmIChwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgIGNhbGxiYWNrKFxuICAgICAgICAnVGhlIHBlZXIgY29ubmVjdGlvbiBvYmplY3QgaXMgaW4gXCJjbG9zZWRcIiBzdGF0ZS4gVGhpcyBpcyBtb3N0IGxpa2VseSBkdWUgdG8gYW4gaW52b2NhdGlvbiBvZiB0aGUgZGlzcG9zZSBtZXRob2QgYmVmb3JlIGFjY2VwdGluZyBpbiB0aGUgZGlhbG9ndWUnXG4gICAgICApXG4gICAgfVxuXG4gICAgaWYgKHZpZGVvU3RyZWFtICYmIGxvY2FsVmlkZW8pIHtcbiAgICAgIHNlbGYuc2hvd0xvY2FsVmlkZW8oKVxuICAgIH1cblxuICAgIGlmICh2aWRlb1N0cmVhbSkge1xuICAgICAgcGMuYWRkU3RyZWFtKHZpZGVvU3RyZWFtKVxuICAgIH1cblxuICAgIGlmIChhdWRpb1N0cmVhbSkge1xuICAgICAgcGMuYWRkU3RyZWFtKGF1ZGlvU3RyZWFtKVxuICAgIH1cblxuICAgIC8vIFtIYWNrXSBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NDQzNTU4XG4gICAgdmFyIGJyb3dzZXIgPSBwYXJzZXIuZ2V0QnJvd3NlcigpXG4gICAgaWYgKG1vZGUgPT09ICdzZW5kb25seScgJiZcbiAgICAgIChicm93c2VyLm5hbWUgPT09ICdDaHJvbWUnIHx8IGJyb3dzZXIubmFtZSA9PT0gJ0Nocm9taXVtJykgJiZcbiAgICAgIGJyb3dzZXIubWFqb3IgPT09IDM5KSB7XG4gICAgICBtb2RlID0gJ3NlbmRyZWN2J1xuICAgIH1cblxuICAgIGNhbGxiYWNrKClcbiAgfVxuXG4gIGlmIChtb2RlICE9PSAncmVjdm9ubHknICYmICF2aWRlb1N0cmVhbSAmJiAhYXVkaW9TdHJlYW0pIHtcbiAgICBmdW5jdGlvbiBnZXRNZWRpYShjb25zdHJhaW50cykge1xuICAgICAgaWYgKGNvbnN0cmFpbnRzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29uc3RyYWludHMgPSBNRURJQV9DT05TVFJBSU5UU1xuICAgICAgfVxuXG4gICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cykudGhlbihmdW5jdGlvbiAoc3RyZWFtKSB7XG4gICAgICAgIHZpZGVvU3RyZWFtID0gc3RyZWFtXG4gICAgICAgIHN0YXJ0KClcbiAgICAgIH0pLmNhdGNoKGNhbGxiYWNrKTtcbiAgICB9XG4gICAgaWYgKHNlbmRTb3VyY2UgPT09ICd3ZWJjYW0nKSB7XG4gICAgICBnZXRNZWRpYShtZWRpYUNvbnN0cmFpbnRzKVxuICAgIH0gZWxzZSB7XG4gICAgICBnZXRTY3JlZW5Db25zdHJhaW50cyhzZW5kU291cmNlLCBmdW5jdGlvbiAoZXJyb3IsIGNvbnN0cmFpbnRzXykge1xuICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGVycm9yKVxuXG4gICAgICAgIGNvbnN0cmFpbnRzID0gW21lZGlhQ29uc3RyYWludHNdXG4gICAgICAgIGNvbnN0cmFpbnRzLnVuc2hpZnQoY29uc3RyYWludHNfKVxuICAgICAgICBnZXRNZWRpYShyZWN1cnNpdmUuYXBwbHkodW5kZWZpbmVkLCBjb25zdHJhaW50cykpXG4gICAgICB9LCBndWlkKVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBzZXRUaW1lb3V0KHN0YXJ0LCAwKVxuICB9XG5cbiAgdGhpcy5vbignX2Rpc3Bvc2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKGxvY2FsVmlkZW8pIHtcbiAgICAgIGxvY2FsVmlkZW8ucGF1c2UoKVxuICAgICAgbG9jYWxWaWRlby5zcmMgPSAnJ1xuICAgICAgbG9jYWxWaWRlby5sb2FkKClcbiAgICAgIC8vVW5tdXRlIGxvY2FsIHZpZGVvIGluIGNhc2UgdGhlIHZpZGVvIHRhZyBpcyBsYXRlciB1c2VkIGZvciByZW1vdGUgdmlkZW9cbiAgICAgIGxvY2FsVmlkZW8ubXV0ZWQgPSBmYWxzZVxuICAgIH1cbiAgICBpZiAocmVtb3RlVmlkZW8pIHtcbiAgICAgIHJlbW90ZVZpZGVvLnBhdXNlKClcbiAgICAgIHJlbW90ZVZpZGVvLnNyYyA9ICcnXG4gICAgICByZW1vdGVWaWRlby5sb2FkKClcbiAgICB9XG4gICAgc2VsZi5yZW1vdmVBbGxMaXN0ZW5lcnMoKVxuXG4gICAgaWYgKHdpbmRvdy5jYW5jZWxDaG9vc2VEZXNrdG9wTWVkaWEgIT09IHVuZGVmaW5lZCkge1xuICAgICAgd2luZG93LmNhbmNlbENob29zZURlc2t0b3BNZWRpYShndWlkKVxuICAgIH1cbiAgfSlcbn1cbmluaGVyaXRzKFdlYlJ0Y1BlZXIsIEV2ZW50RW1pdHRlcilcblxuZnVuY3Rpb24gY3JlYXRlRW5hYmxlRGVzY3JpcHRvcih0eXBlKSB7XG4gIHZhciBtZXRob2QgPSAnZ2V0JyArIHR5cGUgKyAnVHJhY2tzJ1xuXG4gIHJldHVybiB7XG4gICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFtUb0RvXSBTaG91bGQgcmV0dXJuIHVuZGVmaW5lZCBpZiBub3QgYWxsIHRyYWNrcyBoYXZlIHRoZSBzYW1lIHZhbHVlP1xuXG4gICAgICBpZiAoIXRoaXMucGVlckNvbm5lY3Rpb24pIHJldHVyblxuXG4gICAgICB2YXIgc3RyZWFtcyA9IHRoaXMucGVlckNvbm5lY3Rpb24uZ2V0TG9jYWxTdHJlYW1zKClcbiAgICAgIGlmICghc3RyZWFtcy5sZW5ndGgpIHJldHVyblxuXG4gICAgICBmb3IgKHZhciBpID0gMCwgc3RyZWFtOyBzdHJlYW0gPSBzdHJlYW1zW2ldOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYWNrcyA9IHN0cmVhbVttZXRob2RdKClcbiAgICAgICAgZm9yICh2YXIgaiA9IDAsIHRyYWNrOyB0cmFjayA9IHRyYWNrc1tqXTsgaisrKVxuICAgICAgICAgIGlmICghdHJhY2suZW5hYmxlZCkgcmV0dXJuIGZhbHNlXG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0cnVlXG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgZnVuY3Rpb24gdHJhY2tTZXRFbmFibGUodHJhY2spIHtcbiAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlXG4gICAgICB9XG5cbiAgICAgIHRoaXMucGVlckNvbm5lY3Rpb24uZ2V0TG9jYWxTdHJlYW1zKCkuZm9yRWFjaChmdW5jdGlvbiAoc3RyZWFtKSB7XG4gICAgICAgIHN0cmVhbVttZXRob2RdKCkuZm9yRWFjaCh0cmFja1NldEVuYWJsZSlcbiAgICAgIH0pXG4gICAgfVxuICB9XG59XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKFdlYlJ0Y1BlZXIucHJvdG90eXBlLCB7XG4gICdlbmFibGVkJzoge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gdGhpcy5hdWRpb0VuYWJsZWQgJiYgdGhpcy52aWRlb0VuYWJsZWRcbiAgICB9LFxuICAgIHNldDogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICB0aGlzLmF1ZGlvRW5hYmxlZCA9IHRoaXMudmlkZW9FbmFibGVkID0gdmFsdWVcbiAgICB9XG4gIH0sXG4gICdhdWRpb0VuYWJsZWQnOiBjcmVhdGVFbmFibGVEZXNjcmlwdG9yKCdBdWRpbycpLFxuICAndmlkZW9FbmFibGVkJzogY3JlYXRlRW5hYmxlRGVzY3JpcHRvcignVmlkZW8nKVxufSlcblxuV2ViUnRjUGVlci5wcm90b3R5cGUuZ2V0TG9jYWxTdHJlYW0gPSBmdW5jdGlvbiAoaW5kZXgpIHtcbiAgaWYgKHRoaXMucGVlckNvbm5lY3Rpb24pIHtcbiAgICByZXR1cm4gdGhpcy5wZWVyQ29ubmVjdGlvbi5nZXRMb2NhbFN0cmVhbXMoKVtpbmRleCB8fCAwXVxuICB9XG59XG5cbldlYlJ0Y1BlZXIucHJvdG90eXBlLmdldFJlbW90ZVN0cmVhbSA9IGZ1bmN0aW9uIChpbmRleCkge1xuICBpZiAodGhpcy5wZWVyQ29ubmVjdGlvbikge1xuICAgIHJldHVybiB0aGlzLnBlZXJDb25uZWN0aW9uLmdldFJlbW90ZVN0cmVhbXMoKVtpbmRleCB8fCAwXVxuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFRoaXMgbWV0aG9kIGZyZWVzIHRoZSByZXNvdXJjZXMgdXNlZCBieSBXZWJSdGNQZWVyLlxuICpcbiAqIEBmdW5jdGlvbiBtb2R1bGU6a3VyZW50b1V0aWxzLldlYlJ0Y1BlZXIucHJvdG90eXBlLmRpc3Bvc2VcbiAqL1xuV2ViUnRjUGVlci5wcm90b3R5cGUuZGlzcG9zZSA9IGZ1bmN0aW9uICgpIHtcbiAgbG9nZ2VyLmRlYnVnKCdEaXNwb3NpbmcgV2ViUnRjUGVlcicpXG5cbiAgdmFyIHBjID0gdGhpcy5wZWVyQ29ubmVjdGlvblxuICB2YXIgZGMgPSB0aGlzLmRhdGFDaGFubmVsXG4gIHRyeSB7XG4gICAgaWYgKGRjKSB7XG4gICAgICBpZiAoZGMuc2lnbmFsaW5nU3RhdGUgPT09ICdjbG9zZWQnKSByZXR1cm5cblxuICAgICAgZGMuY2xvc2UoKVxuICAgIH1cblxuICAgIGlmIChwYykge1xuICAgICAgaWYgKHBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykgcmV0dXJuXG5cbiAgICAgIHBjLmdldExvY2FsU3RyZWFtcygpLmZvckVhY2goc3RyZWFtU3RvcClcblxuICAgICAgLy8gRklYTUUgVGhpcyBpcyBub3QgeWV0IGltcGxlbWVudGVkIGluIGZpcmVmb3hcbiAgICAgIC8vIGlmKHZpZGVvU3RyZWFtKSBwYy5yZW1vdmVTdHJlYW0odmlkZW9TdHJlYW0pO1xuICAgICAgLy8gaWYoYXVkaW9TdHJlYW0pIHBjLnJlbW92ZVN0cmVhbShhdWRpb1N0cmVhbSk7XG5cbiAgICAgIHBjLmNsb3NlKClcbiAgICB9XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGxvZ2dlci53YXJuKCdFeGNlcHRpb24gZGlzcG9zaW5nIHdlYnJ0YyBwZWVyICcgKyBlcnIpXG4gIH1cblxuICB0aGlzLmVtaXQoJ19kaXNwb3NlJylcbn1cblxuLy9cbi8vIFNwZWNpYWxpemVkIGNoaWxkIGNsYXNzZXNcbi8vXG5cbmZ1bmN0aW9uIFdlYlJ0Y1BlZXJSZWN2b25seShvcHRpb25zLCBjYWxsYmFjaykge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgV2ViUnRjUGVlclJlY3Zvbmx5KSkge1xuICAgIHJldHVybiBuZXcgV2ViUnRjUGVlclJlY3Zvbmx5KG9wdGlvbnMsIGNhbGxiYWNrKVxuICB9XG5cbiAgV2ViUnRjUGVlclJlY3Zvbmx5LnN1cGVyXy5jYWxsKHRoaXMsICdyZWN2b25seScsIG9wdGlvbnMsIGNhbGxiYWNrKVxufVxuaW5oZXJpdHMoV2ViUnRjUGVlclJlY3Zvbmx5LCBXZWJSdGNQZWVyKVxuXG5mdW5jdGlvbiBXZWJSdGNQZWVyU2VuZG9ubHkob3B0aW9ucywgY2FsbGJhY2spIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFdlYlJ0Y1BlZXJTZW5kb25seSkpIHtcbiAgICByZXR1cm4gbmV3IFdlYlJ0Y1BlZXJTZW5kb25seShvcHRpb25zLCBjYWxsYmFjaylcbiAgfVxuXG4gIFdlYlJ0Y1BlZXJTZW5kb25seS5zdXBlcl8uY2FsbCh0aGlzLCAnc2VuZG9ubHknLCBvcHRpb25zLCBjYWxsYmFjaylcbn1cbmluaGVyaXRzKFdlYlJ0Y1BlZXJTZW5kb25seSwgV2ViUnRjUGVlcilcblxuZnVuY3Rpb24gV2ViUnRjUGVlclNlbmRyZWN2KG9wdGlvbnMsIGNhbGxiYWNrKSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBXZWJSdGNQZWVyU2VuZHJlY3YpKSB7XG4gICAgcmV0dXJuIG5ldyBXZWJSdGNQZWVyU2VuZHJlY3Yob3B0aW9ucywgY2FsbGJhY2spXG4gIH1cblxuICBXZWJSdGNQZWVyU2VuZHJlY3Yuc3VwZXJfLmNhbGwodGhpcywgJ3NlbmRyZWN2Jywgb3B0aW9ucywgY2FsbGJhY2spXG59XG5pbmhlcml0cyhXZWJSdGNQZWVyU2VuZHJlY3YsIFdlYlJ0Y1BlZXIpXG5cbmZ1bmN0aW9uIGhhcmtVdGlscyhzdHJlYW0sIG9wdGlvbnMpIHtcbiAgcmV0dXJuIGhhcmsoc3RyZWFtLCBvcHRpb25zKTtcbn1cblxuZXhwb3J0cy5idWZmZXJpemVDYW5kaWRhdGVzID0gYnVmZmVyaXplQ2FuZGlkYXRlc1xuXG5leHBvcnRzLldlYlJ0Y1BlZXJSZWN2b25seSA9IFdlYlJ0Y1BlZXJSZWN2b25seVxuZXhwb3J0cy5XZWJSdGNQZWVyU2VuZG9ubHkgPSBXZWJSdGNQZWVyU2VuZG9ubHlcbmV4cG9ydHMuV2ViUnRjUGVlclNlbmRyZWN2ID0gV2ViUnRjUGVlclNlbmRyZWN2XG5leHBvcnRzLmhhcmsgPSBoYXJrVXRpbHNcbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG4vKipcbiAqIFRoaXMgbW9kdWxlIGNvbnRhaW5zIGEgc2V0IG9mIHJldXNhYmxlIGNvbXBvbmVudHMgdGhhdCBoYXZlIGJlZW4gZm91bmQgdXNlZnVsXG4gKiBkdXJpbmcgdGhlIGRldmVsb3BtZW50IG9mIHRoZSBXZWJSVEMgYXBwbGljYXRpb25zIHdpdGggS3VyZW50by5cbiAqIFxuICogQG1vZHVsZSBrdXJlbnRvVXRpbHNcbiAqIFxuICogQGNvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKiBAbGljZW5zZSBBTHYyXG4gKi9cblxudmFyIFdlYlJ0Y1BlZXIgPSByZXF1aXJlKCcuL1dlYlJ0Y1BlZXInKTtcblxuZXhwb3J0cy5XZWJSdGNQZWVyID0gV2ViUnRjUGVlcjtcbiIsImltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdSc7XG5cbi8vVGhpcyBleHBvcnQgd2l0aCAtLXN0YW5kYWxvbmUgb3B0aW9uIGFsbG93cyB1c2luZyBPcGVuVmlkdSBmcm9tIGJvd3NlciB3aXRoIG5hbWVzcGFjZVxuLy9leHBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuXG4vL1RoaXMgXCJoYWNrXCIgYWxsb3dzIHRvIHVzZSBPcGVuVmlkdSBmcm9tIHRoZSBnbG9iYWwgc3BhY2Ugd2luZG93XG5pZih3aW5kb3cpe1xuICAgIHdpbmRvd1tcIk9wZW5WaWR1XCJdID0gT3BlblZpZHU7XG59XG5cbi8vQ29tbWFuZCB0byBnZW5lcmF0ZSBidW5kbGUuanMgd2l0aG91dCBuYW1lc3BhY2Vcbi8vd2F0Y2hpZnkgTWFpbi50cyAtcCBbIHRzaWZ5IF0gLS1leGNsdWRlIGt1cmVudG8tYnJvd3Nlci1leHRlbnNpb25zIC0tZGVidWcgLW8gLi4vc3RhdGljL2pzL09wZW5WaWR1LmpzIC12IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNyBPcGVuVmlkdSAoaHR0cDovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuaW1wb3J0IHsgT3BlblZpZHVJbnRlcm5hbCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvT3BlblZpZHVJbnRlcm5hbCc7XG5cbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi9QdWJsaXNoZXInO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TdHJlYW0nO1xuaW1wb3J0IHsgTG9jYWxSZWNvcmRlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvTG9jYWxSZWNvcmRlcic7XG5cbmltcG9ydCAqIGFzIGFkYXB0ZXIgZnJvbSAnd2VicnRjLWFkYXB0ZXInO1xuaW1wb3J0ICogYXMgc2NyZWVuU2hhcmluZyBmcm9tICcuLi9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcuanMnO1xuaW1wb3J0ICogYXMgc2NyZWVuU2hhcmluZ0F1dG8gZnJvbSAnLi4vU2NyZWVuU2hhcmluZy9TY3JlZW4tQ2FwdHVyaW5nLUF1dG8uanMnO1xuaW1wb3J0ICogYXMgRGV0ZWN0UlRDIGZyb20gJy4uL0t1cmVudG9VdGlscy9EZXRlY3RSVEMnO1xuXG5pZiAod2luZG93KSB7XG4gICAgd2luZG93W1wiYWRhcHRlclwiXSA9IGFkYXB0ZXI7XG59XG5cbmV4cG9ydCBjbGFzcyBPcGVuVmlkdSB7XG5cbiAgICBvcGVuVmlkdTogT3BlblZpZHVJbnRlcm5hbDtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLm9wZW5WaWR1ID0gbmV3IE9wZW5WaWR1SW50ZXJuYWwoKTtcbiAgICAgICAgY29uc29sZS5pbmZvKFwiJ09wZW5WaWR1JyBpbml0aWFsaXplZFwiKTtcbiAgICB9O1xuXG4gICAgaW5pdFNlc3Npb24oYXBpS2V5OiBzdHJpbmcsIHNlc3Npb25JZDogc3RyaW5nKTogU2Vzc2lvbjtcbiAgICBpbml0U2Vzc2lvbihzZXNzaW9uSWQ6IHN0cmluZyk6IFNlc3Npb247XG5cbiAgICBpbml0U2Vzc2lvbihwYXJhbTEsIHBhcmFtMj8pOiBhbnkge1xuICAgICAgICBpZiAodHlwZW9mIHBhcmFtMiA9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFNlc3Npb24odGhpcy5vcGVuVmlkdS5pbml0U2Vzc2lvbihwYXJhbTIpLCB0aGlzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgU2Vzc2lvbih0aGlzLm9wZW5WaWR1LmluaXRTZXNzaW9uKHBhcmFtMSksIHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaW5pdFB1Ymxpc2hlcihwYXJlbnRJZDogc3RyaW5nKTogUHVibGlzaGVyO1xuICAgIGluaXRQdWJsaXNoZXIocGFyZW50SWQ6IHN0cmluZywgY2FtZXJhT3B0aW9uczogYW55KTogUHVibGlzaGVyO1xuICAgIGluaXRQdWJsaXNoZXIocGFyZW50SWQ6IHN0cmluZywgY2FtZXJhT3B0aW9uczogYW55LCBjYWxsYmFjazogYW55KTogUHVibGlzaGVyO1xuXG4gICAgaW5pdFB1Ymxpc2hlcihwYXJlbnRJZDogc3RyaW5nLCBjYW1lcmFPcHRpb25zPzogYW55LCBjYWxsYmFjaz86IEZ1bmN0aW9uKTogYW55IHtcblxuICAgICAgICBsZXQgcHVibGlzaGVyOiBQdWJsaXNoZXI7XG4gICAgICAgIGlmIChjYW1lcmFPcHRpb25zICE9IG51bGwpIHtcblxuICAgICAgICAgICAgY2FtZXJhT3B0aW9ucy5hdWRpbyA9IGNhbWVyYU9wdGlvbnMuYXVkaW8gIT0gbnVsbCA/IGNhbWVyYU9wdGlvbnMuYXVkaW8gOiB0cnVlO1xuICAgICAgICAgICAgY2FtZXJhT3B0aW9ucy52aWRlbyA9IGNhbWVyYU9wdGlvbnMudmlkZW8gIT0gbnVsbCA/IGNhbWVyYU9wdGlvbnMudmlkZW8gOiB0cnVlO1xuXG4gICAgICAgICAgICBpZiAoIWNhbWVyYU9wdGlvbnMuc2NyZWVuKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBXZWJjYW0gYW5kL29yIG1pY3JvcGhvbmUgaXMgYmVpbmcgcmVxdWVzdGVkXG5cbiAgICAgICAgICAgICAgICBsZXQgY2FtZXJhT3B0aW9uc0F1eCA9IHtcbiAgICAgICAgICAgICAgICAgICAgc2VuZEF1ZGlvOiBjYW1lcmFPcHRpb25zLmF1ZGlvICE9IG51bGwgPyBjYW1lcmFPcHRpb25zLmF1ZGlvIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgc2VuZFZpZGVvOiBjYW1lcmFPcHRpb25zLnZpZGVvICE9IG51bGwgPyBjYW1lcmFPcHRpb25zLnZpZGVvIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgYWN0aXZlQXVkaW86IGNhbWVyYU9wdGlvbnMuYXVkaW9BY3RpdmUgIT0gbnVsbCA/IGNhbWVyYU9wdGlvbnMuYXVkaW9BY3RpdmUgOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBhY3RpdmVWaWRlbzogY2FtZXJhT3B0aW9ucy52aWRlb0FjdGl2ZSAhPSBudWxsID8gY2FtZXJhT3B0aW9ucy52aWRlb0FjdGl2ZSA6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIGRhdGFDaGFubmVsOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzOiB0aGlzLm9wZW5WaWR1LmdlbmVyYXRlTWVkaWFDb25zdHJhaW50cyhjYW1lcmFPcHRpb25zKVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgY2FtZXJhT3B0aW9ucyA9IGNhbWVyYU9wdGlvbnNBdXg7XG5cbiAgICAgICAgICAgICAgICBwdWJsaXNoZXIgPSBuZXcgUHVibGlzaGVyKHRoaXMub3BlblZpZHUuaW5pdFB1Ymxpc2hlclRhZ2dlZChwYXJlbnRJZCwgY2FtZXJhT3B0aW9ucywgdHJ1ZSwgY2FsbGJhY2spLCBwYXJlbnRJZCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIGluaXRpYWxpemVkXCIpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHB1Ymxpc2hlcjtcblxuICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgIC8vIFNjcmVlbiBzaGFyZSBpcyBiZWluZyByZXF1ZXN0ZWRcblxuICAgICAgICAgICAgICAgIHB1Ymxpc2hlciA9IG5ldyBQdWJsaXNoZXIodGhpcy5vcGVuVmlkdS5pbml0UHVibGlzaGVyU2NyZWVuKHBhcmVudElkLCB0cnVlLCBjYWxsYmFjayksIHBhcmVudElkLCB0cnVlKTtcbiAgICAgICAgICAgICAgICBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIubmFtZSA9PT0gJ0ZpcmVmb3gnICYmIERldGVjdFJUQy5icm93c2VyLnZlcnNpb24gPj0gNTIpIHtcbiAgICAgICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZ0F1dG8uZ2V0U2NyZWVuSWQoKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbWVyYU9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VuZEF1ZGlvOiBjYW1lcmFPcHRpb25zLmF1ZGlvLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRWaWRlbzogY2FtZXJhT3B0aW9ucy52aWRlbyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY3RpdmVBdWRpbzogY2FtZXJhT3B0aW9ucy5hdWRpb0FjdGl2ZSAhPSBudWxsID8gY2FtZXJhT3B0aW9ucy5hdWRpb0FjdGl2ZSA6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWN0aXZlVmlkZW86IGNhbWVyYU9wdGlvbnMudmlkZW9BY3RpdmUgIT0gbnVsbCA/IGNhbWVyYU9wdGlvbnMudmlkZW9BY3RpdmUgOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFDaGFubmVsOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlkZW86IHNjcmVlbkNvbnN0cmFpbnRzLnZpZGVvLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpbzogZmFsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0uY29uZmlndXJlU2NyZWVuT3B0aW9ucyhjYW1lcmFPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIGluaXRpYWxpemVkXCIpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLmVlLmVtaXRFdmVudCgnY2FuLXJlcXVlc3Qtc2NyZWVuJyk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcHVibGlzaGVyO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIubmFtZSA9PT0gJ0Nocm9tZScpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gU2NyZWVuIGlzIGJlaW5nIHJlcXVlc3RlZFxuXG4gICAgICAgICAgICAgICAgICAgIC8qc2NyZWVuU2hhcmluZy5pc0Nocm9tZUV4dGVuc2lvbkF2YWlsYWJsZSgoYXZhaWxhYmlsaXR5KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGF2YWlsYWJpbGl0eSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2F2YWlsYWJsZSc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignRVhURU5TSU9OIEFWQUlMQUJMRSEhIScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nLmdldFNjcmVlbkNvbnN0cmFpbnRzKChlcnJvciwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oc2NyZWVuQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndW5hdmFpbGFibGUnOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0VYVEVOU0lPTiBOT1QgQVZBSUxBQkxFISEhJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2lzRmlyZWZveCc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignSVQgSVMgRklSRUZPWCEhIScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nLmdldFNjcmVlbkNvbnN0cmFpbnRzKChlcnJvciwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oc2NyZWVuQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pOyovXG4gICAgICAgICAgICAgICAgICAgIHNjcmVlblNoYXJpbmdBdXRvLmdldFNjcmVlbklkKChlcnJvciwgc291cmNlSWQsIHNjcmVlbkNvbnN0cmFpbnRzKSA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVELCAnaHR0cHM6Ly9jaHJvbWUuZ29vZ2xlLmNvbS93ZWJzdG9yZS9kZXRhaWwvc2NyZWVuLWNhcHR1cmluZy9hamhpZmRkaW1rYXBnY2lmZ2NvZG1tZmRsa25haGZmaycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjYWxsYmFjaykgY2FsbGJhY2soZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgPT09ICdwZXJtaXNzaW9uLWRlbmllZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQsICdZb3UgbXVzdCBhbGxvdyBhY2Nlc3MgdG8gb25lIHdpbmRvdyBvZiB5b3VyIGRlc2t0b3AnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2FsbGJhY2spIGNhbGxiYWNrKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbWVyYU9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VuZEF1ZGlvOiBjYW1lcmFPcHRpb25zLmF1ZGlvICE9IG51bGwgPyBjYW1lcmFPcHRpb25zLmF1ZGlvIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kVmlkZW86IGNhbWVyYU9wdGlvbnMudmlkZW8gIT0gbnVsbCA/IGNhbWVyYU9wdGlvbnMudmlkZW8gOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjdGl2ZUF1ZGlvOiBjYW1lcmFPcHRpb25zLmF1ZGlvQWN0aXZlICE9IG51bGwgPyBjYW1lcmFPcHRpb25zLmF1ZGlvQWN0aXZlIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY3RpdmVWaWRlbzogY2FtZXJhT3B0aW9ucy52aWRlb0FjdGl2ZSAhPSBudWxsID8gY2FtZXJhT3B0aW9ucy52aWRlb0FjdGl2ZSA6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YUNoYW5uZWw6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWRlbzogc2NyZWVuQ29uc3RyYWludHMudmlkZW8sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvOiBmYWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5jb25maWd1cmVTY3JlZW5PcHRpb25zKGNhbWVyYU9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLmVlLmVtaXRFdmVudCgnY2FuLXJlcXVlc3Qtc2NyZWVuJyk7XG4gICAgICAgICAgICAgICAgICAgIH0sIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignZ2V0U2NyZWVuSWQgZXJyb3InLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBpbml0aWFsaXplZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHB1Ymxpc2hlcjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdTY3JlZW4gc2hhcmluZyBub3Qgc3VwcG9ydGVkIG9uICcgKyBEZXRlY3RSVEMuYnJvd3Nlci5uYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhY2FsbGJhY2spIGNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQsICdTY3JlZW4gc2hhcmluZyBub3Qgc3VwcG9ydGVkIG9uICcgKyBEZXRlY3RSVEMuYnJvd3Nlci5uYW1lICsgJyAnICsgRGV0ZWN0UlRDLmJyb3dzZXIudmVyc2lvbikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNhbWVyYU9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgc2VuZEF1ZGlvOiB0cnVlLFxuICAgICAgICAgICAgICAgIHNlbmRWaWRlbzogdHJ1ZSxcbiAgICAgICAgICAgICAgICBhY3RpdmVBdWRpbzogdHJ1ZSxcbiAgICAgICAgICAgICAgICBhY3RpdmVWaWRlbzogdHJ1ZSxcbiAgICAgICAgICAgICAgICBkYXRhQ2hhbm5lbDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzOiB7XG4gICAgICAgICAgICAgICAgICAgIGF1ZGlvOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICB2aWRlbzogeyB3aWR0aDogeyBpZGVhbDogMTI4MCB9IH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwdWJsaXNoZXIgPSBuZXcgUHVibGlzaGVyKHRoaXMub3BlblZpZHUuaW5pdFB1Ymxpc2hlclRhZ2dlZChwYXJlbnRJZCwgY2FtZXJhT3B0aW9ucywgdHJ1ZSwgY2FsbGJhY2spLCBwYXJlbnRJZCwgZmFsc2UpO1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiJ1B1Ymxpc2hlcicgaW5pdGlhbGl6ZWRcIik7XG5cbiAgICAgICAgICAgIHJldHVybiBwdWJsaXNoZXI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZWluaXRQdWJsaXNoZXIocHVibGlzaGVyOiBQdWJsaXNoZXIpOiBhbnkge1xuICAgICAgICBpZiAocHVibGlzaGVyLnN0cmVhbS50eXBlT2ZWaWRlbyAhPT0gJ1NDUkVFTicpIHtcbiAgICAgICAgICAgIHB1Ymxpc2hlciA9IG5ldyBQdWJsaXNoZXIodGhpcy5vcGVuVmlkdS5pbml0UHVibGlzaGVyVGFnZ2VkKHB1Ymxpc2hlci5zdHJlYW0uZ2V0UGFyZW50SWQoKSwgcHVibGlzaGVyLnN0cmVhbS5vdXRib3VuZE9wdGlvbnMsIGZhbHNlKSwgcHVibGlzaGVyLnN0cmVhbS5nZXRQYXJlbnRJZCgpLCBmYWxzZSk7XG4gICAgICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBpbml0aWFsaXplZFwiKTtcbiAgICAgICAgICAgIHJldHVybiBwdWJsaXNoZXI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwdWJsaXNoZXIgPSBuZXcgUHVibGlzaGVyKHRoaXMub3BlblZpZHUuaW5pdFB1Ymxpc2hlclNjcmVlbihwdWJsaXNoZXIuc3RyZWFtLmdldFBhcmVudElkKCksIGZhbHNlKSwgcHVibGlzaGVyLnN0cmVhbS5nZXRQYXJlbnRJZCgpLCB0cnVlKTtcbiAgICAgICAgICAgIGlmIChEZXRlY3RSVEMuYnJvd3Nlci5uYW1lID09PSAnRmlyZWZveCcgJiYgRGV0ZWN0UlRDLmJyb3dzZXIudmVyc2lvbiA+PSA1Mikge1xuICAgICAgICAgICAgICAgIHNjcmVlblNoYXJpbmdBdXRvLmdldFNjcmVlbklkKChlcnJvciwgc291cmNlSWQsIHNjcmVlbkNvbnN0cmFpbnRzKSA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5vdXRib3VuZE9wdGlvbnMubWVkaWFDb25zdHJhaW50cy52aWRlbyA9IHNjcmVlbkNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLmNvbmZpZ3VyZVNjcmVlbk9wdGlvbnMocHVibGlzaGVyLnN0cmVhbS5vdXRib3VuZE9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBpbml0aWFsaXplZFwiKTtcblxuICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLmVlLmVtaXRFdmVudCgnY2FuLXJlcXVlc3Qtc2NyZWVuJyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHB1Ymxpc2hlcjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIubmFtZSA9PT0gJ0Nocm9tZScpIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nQXV0by5nZXRTY3JlZW5JZCgoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5Db25zdHJhaW50cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IgPT09ICdub3QtaW5zdGFsbGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVELCAnaHR0cHM6Ly9jaHJvbWUuZ29vZ2xlLmNvbS93ZWJzdG9yZS9kZXRhaWwvc2NyZWVuLWNhcHR1cmluZy9hamhpZmRkaW1rYXBnY2lmZ2NvZG1tZmRsa25haGZmaycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgPT09ICdwZXJtaXNzaW9uLWRlbmllZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5vdXRib3VuZE9wdGlvbnMubWVkaWFDb25zdHJhaW50cy52aWRlbyA9IHNjcmVlbkNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLmNvbmZpZ3VyZVNjcmVlbk9wdGlvbnMocHVibGlzaGVyLnN0cmVhbS5vdXRib3VuZE9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0uZWUuZW1pdEV2ZW50KCdjYW4tcmVxdWVzdC1zY3JlZW4nKTtcbiAgICAgICAgICAgICAgICB9LCAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignZ2V0U2NyZWVuSWQgZXJyb3InLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBpbml0aWFsaXplZFwiKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcHVibGlzaGVyO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdTY3JlZW4gc2hhcmluZyBub3Qgc3VwcG9ydGVkIG9uICcgKyBEZXRlY3RSVEMuYnJvd3Nlci5uYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNoZWNrU3lzdGVtUmVxdWlyZW1lbnRzKCk6IG51bWJlciB7XG5cbiAgICAgICAgbGV0IGRlZmF1bHRXZWJSVENTdXBwb3J0OiBib29sZWFuID0gRGV0ZWN0UlRDLmlzV2ViUlRDU3VwcG9ydGVkO1xuICAgICAgICBsZXQgYnJvd3NlciA9IERldGVjdFJUQy5icm93c2VyLm5hbWU7XG4gICAgICAgIGxldCB2ZXJzaW9uID0gRGV0ZWN0UlRDLmJyb3dzZXIudmVyc2lvbjtcblxuICAgICAgICBpZiAoKGJyb3dzZXIgIT09ICdDaHJvbWUnKSAmJiAoYnJvd3NlciAhPT0gJ0ZpcmVmb3gnKSAmJiAoYnJvd3NlciAhPT0gJ09wZXJhJykpIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGRlZmF1bHRXZWJSVENTdXBwb3J0ID8gMSA6IDA7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBnZXREZXZpY2VzKGNhbGxiYWNrKSB7XG4gICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZW51bWVyYXRlRGV2aWNlcygpLnRoZW4oKGRldmljZUluZm9zKSA9PiB7XG4gICAgICAgICAgICBjYWxsYmFjayhudWxsLCBkZXZpY2VJbmZvcyk7XG4gICAgICAgIH0pLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIGdldHRpbmcgZGV2aWNlc1wiLCBlcnJvcik7XG4gICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGVuYWJsZVByb2RNb2RlKCkge1xuICAgICAgICBjb25zb2xlLmxvZyA9IGZ1bmN0aW9uICgpIHsgfTtcbiAgICAgICAgY29uc29sZS5kZWJ1ZyA9IGZ1bmN0aW9uICgpIHsgfTtcbiAgICAgICAgY29uc29sZS5pbmZvID0gZnVuY3Rpb24gKCkgeyB9O1xuICAgICAgICBjb25zb2xlLndhcm4gPSBmdW5jdGlvbiAoKSB7IH07XG4gICAgfVxuXG4gICAgaW5pdExvY2FsUmVjb3JkZXIoc3RyZWFtOiBTdHJlYW0pOiBMb2NhbFJlY29yZGVyIHtcbiAgICAgICAgcmV0dXJuIG5ldyBMb2NhbFJlY29yZGVyKHN0cmVhbSk7XG4gICAgfVxuXG59XG4iLCIvKlxuICogb3B0aW9uczogbmFtZTogWFhYIGRhdGE6IHRydWUgKE1heWJlIHRoaXMgaXMgYmFzZWQgb24gd2VicnRjKSBhdWRpbzogdHJ1ZSxcbiAqIHZpZGVvOiB0cnVlLCB1cmw6IFwiZmlsZTovLy8uLi5cIiA+IFBsYXllciBzY3JlZW46IHRydWUgPiBEZXNrdG9wIChpbXBsaWNpdFxuICogdmlkZW86dHJ1ZSwgYXVkaW86ZmFsc2UpIGF1ZGlvOiB0cnVlLCB2aWRlbzogdHJ1ZSA+IFdlYmNhbVxuICpcbiAqIHN0cmVhbS5oYXNBdWRpbygpOyBzdHJlYW0uaGFzVmlkZW8oKTsgc3RyZWFtLmhhc0RhdGEoKTtcbiAqL1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TdHJlYW0nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5cbmltcG9ydCBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCd3b2xmeTg3LWV2ZW50ZW1pdHRlcicpO1xuXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyIHtcblxuICAgIGVlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gICAgYWNjZXNzQWxsb3dlZCA9IGZhbHNlO1xuICAgIGVsZW1lbnQ6IEVsZW1lbnQ7XG4gICAgaWQ6IHN0cmluZztcbiAgICBzdHJlYW06IFN0cmVhbTtcbiAgICBzZXNzaW9uOiBTZXNzaW9uOyAvL0luaXRpYWxpemVkIGJ5IFNlc3Npb24ucHVibGlzaChQdWJsaXNoZXIpXG4gICAgaXNTY3JlZW5SZXF1ZXN0ZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtLCBwYXJlbnRJZDogc3RyaW5nLCBpc1NjcmVlblJlcXVlc3RlZDogYm9vbGVhbikge1xuICAgICAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTtcbiAgICAgICAgdGhpcy5pc1NjcmVlblJlcXVlc3RlZCA9IGlzU2NyZWVuUmVxdWVzdGVkO1xuXG4gICAgICAgIC8vIExpc3RlbnMgdG8gdGhlIGRlYWN0aXZhdGlvbiBvZiB0aGUgZGVmYXVsdCBiZWhhdmlvdXIgdXBvbiB0aGUgZGVsZXRpb24gb2YgYSBTdHJlYW0gb2JqZWN0XG4gICAgICAgIHRoaXMuZWUuYWRkTGlzdGVuZXIoJ3N0cmVhbS1kZXN0cm95ZWQtZGVmYXVsdCcsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGxldCBzOiBTdHJlYW0gPSBldmVudC5zdHJlYW07XG4gICAgICAgICAgICBzLmFkZE9uY2VFdmVudExpc3RlbmVyKCd2aWRlby1yZW1vdmVkJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnREZXN0cm95ZWQnKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcy5yZW1vdmVWaWRlbygpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocGFyZW50SWQpICE9IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuZWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHBhcmVudElkKSEhO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGlzaEF1ZGlvKHZhbHVlOiBib29sZWFuKSB7XG4gICAgICAgIHRoaXMuc3RyZWFtLmdldFdlYlJ0Y1BlZXIoKS5hdWRpb0VuYWJsZWQgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICBwdWJsaXNoVmlkZW8odmFsdWU6IGJvb2xlYW4pIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0V2ViUnRjUGVlcigpLnZpZGVvRW5hYmxlZCA9IHZhbHVlO1xuICAgIH1cblxuICAgIGRlc3Ryb3koKSB7XG4gICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbikgdGhpcy5zZXNzaW9uLnVucHVibGlzaCh0aGlzKTtcbiAgICAgICAgdGhpcy5zdHJlYW0uZGlzcG9zZSgpO1xuICAgICAgICB0aGlzLnN0cmVhbS5yZW1vdmVWaWRlbyh0aGlzLmVsZW1lbnQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBzdWJzY3JpYmVUb1JlbW90ZSgpIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uc3Vic2NyaWJlVG9NeVJlbW90ZSgpO1xuICAgIH1cblxuICAgIG9uKGV2ZW50TmFtZTogc3RyaW5nLCBjYWxsYmFjaykge1xuICAgICAgICB0aGlzLmVlLmFkZExpc3RlbmVyKGV2ZW50TmFtZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgZXZlbnROYW1lICsgXCInIHRyaWdnZXJlZCBieSAnUHVibGlzaGVyJ1wiLCBldmVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIGV2ZW50TmFtZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1B1Ymxpc2hlcidcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYWxsYmFjayhldmVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoZXZlbnROYW1lID09ICdzdHJlYW1DcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzUHVibGlzaGVyUHVibGlzaGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbeyBzdHJlYW06IHRoaXMuc3RyZWFtIH1dKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uYWRkRXZlbnRMaXN0ZW5lcignc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFt7IHN0cmVhbTogdGhpcy5zdHJlYW0gfV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChldmVudE5hbWUgPT0gJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNWaWRlb0VMZW1lbnRDcmVhdGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudENyZWF0ZWQnLCBbe1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50OiB0aGlzLnN0cmVhbS5nZXRWaWRlb0VsZW1lbnQoKVxuICAgICAgICAgICAgICAgIH1dKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uYWRkRXZlbnRMaXN0ZW5lcigndmlkZW8tZWxlbWVudC1jcmVhdGVkLWJ5LXN0cmVhbScsIChlbGVtZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaWQgPSBlbGVtZW50LmlkO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFt7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50OiBlbGVtZW50LmVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChldmVudE5hbWUgPT0gJ3ZpZGVvUGxheWluZycpIHtcbiAgICAgICAgICAgIHZhciB2aWRlbyA9IHRoaXMuc3RyZWFtLmdldFZpZGVvRWxlbWVudCgpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLnN0cmVhbS5kaXNwbGF5TXlSZW1vdGUoKSAmJiB2aWRlbyAmJlxuICAgICAgICAgICAgICAgIHZpZGVvLmN1cnJlbnRUaW1lID4gMCAmJlxuICAgICAgICAgICAgICAgIHZpZGVvLnBhdXNlZCA9PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHZpZGVvLmVuZGVkID09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdmlkZW8ucmVhZHlTdGF0ZSA9PSA0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvUGxheWluZycsIFt7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQ6IHRoaXMuc3RyZWFtLmdldFZpZGVvRWxlbWVudCgpXG4gICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5hZGRFdmVudExpc3RlbmVyKCd2aWRlby1pcy1wbGF5aW5nJywgKGVsZW1lbnQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvUGxheWluZycsIFt7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50OiBlbGVtZW50LmVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChldmVudE5hbWUgPT0gJ3JlbW90ZVZpZGVvUGxheWluZycpIHtcbiAgICAgICAgICAgIHZhciB2aWRlbyA9IHRoaXMuc3RyZWFtLmdldFZpZGVvRWxlbWVudCgpO1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpICYmIHZpZGVvICYmXG4gICAgICAgICAgICAgICAgdmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdmlkZW8ucGF1c2VkID09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdmlkZW8uZW5kZWQgPT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB2aWRlby5yZWFkeVN0YXRlID09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncmVtb3RlVmlkZW9QbGF5aW5nJywgW3tcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudDogdGhpcy5zdHJlYW0uZ2V0VmlkZW9FbGVtZW50KClcbiAgICAgICAgICAgICAgICB9XSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmFkZEV2ZW50TGlzdGVuZXIoJ3JlbW90ZS12aWRlby1pcy1wbGF5aW5nJywgKGVsZW1lbnQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlbW90ZVZpZGVvUGxheWluZycsIFt7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50OiBlbGVtZW50LmVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChldmVudE5hbWUgPT0gJ2FjY2Vzc0FsbG93ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uYWNjZXNzSXNBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uYWRkRXZlbnRMaXN0ZW5lcignYWNjZXNzLWFsbG93ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnYWNjZXNzQWxsb3dlZCcpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChldmVudE5hbWUgPT0gJ2FjY2Vzc0RlbmllZCcpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5hY2Nlc3NJc0RlbmllZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NEZW5pZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uYWRkRXZlbnRMaXN0ZW5lcignYWNjZXNzLWRlbmllZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NEZW5pZWQnKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn0iLCJpbXBvcnQgeyBTZXNzaW9uSW50ZXJuYWwsIFNlc3Npb25PcHRpb25zLCBTaWduYWxPcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TZXNzaW9uSW50ZXJuYWwnO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TdHJlYW0nO1xuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvT3BlblZpZHVFcnJvcic7XG5cbmltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdSc7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuL1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTdWJzY3JpYmVyIH0gZnJvbSAnLi9TdWJzY3JpYmVyJztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5pbXBvcnQgKiBhcyBEZXRlY3RSVEMgZnJvbSAnLi4vS3VyZW50b1V0aWxzL0RldGVjdFJUQyc7XG5cbmV4cG9ydCBjbGFzcyBTZXNzaW9uIHtcblxuICAgIHNlc3Npb25JZDogU3RyaW5nO1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICBwcml2YXRlIGVlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBzZXNzaW9uOiBTZXNzaW9uSW50ZXJuYWwsIHByaXZhdGUgb3BlblZpZHU6IE9wZW5WaWR1KSB7XG4gICAgICAgIHRoaXMuc2Vzc2lvbklkID0gc2Vzc2lvbi5nZXRTZXNzaW9uSWQoKTtcblxuICAgICAgICAvLyBMaXN0ZW5zIHRvIHRoZSBkZWFjdGl2YXRpb24gb2YgdGhlIGRlZmF1bHQgYmVoYXZpb3VyIHVwb24gdGhlIGRlbGV0aW9uIG9mIGEgU3RyZWFtIG9iamVjdFxuICAgICAgICB0aGlzLnNlc3Npb24uYWRkRXZlbnRMaXN0ZW5lcignc3RyZWFtLWRlc3Ryb3llZC1kZWZhdWx0JywgZXZlbnQgPT4ge1xuICAgICAgICAgICAgZXZlbnQuc3RyZWFtLnJlbW92ZVZpZGVvKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIExpc3RlbnMgdG8gdGhlIGRlYWN0aXZhdGlvbiBvZiB0aGUgZGVmYXVsdCBiZWhhdmlvdXIgdXBvbiB0aGUgZGlzY29ubmVjdGlvbiBvZiBhIFNlc3Npb25cbiAgICAgICAgdGhpcy5zZXNzaW9uLmFkZEV2ZW50TGlzdGVuZXIoJ3Nlc3Npb24tZGlzY29ubmVjdGVkLWRlZmF1bHQnLCAoKSA9PiB7XG4gICAgICAgICAgICBsZXQgczogU3RyZWFtO1xuICAgICAgICAgICAgZm9yIChsZXQgc3RyZWFtSWQgaW4gdGhpcy5zZXNzaW9uLmdldFJlbW90ZVN0cmVhbXMoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5nZXRSZW1vdGVTdHJlYW1zKClbc3RyZWFtSWRdLnJlbW92ZVZpZGVvKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uICYmIChPYmplY3Qua2V5cyh0aGlzLmNvbm5lY3Rpb24uZ2V0U3RyZWFtcygpKS5sZW5ndGggPiAwKSkge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHN0cmVhbUlkIGluIHRoaXMuY29ubmVjdGlvbi5nZXRTdHJlYW1zKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmdldFN0cmVhbXMoKVtzdHJlYW1JZF0ucmVtb3ZlVmlkZW8oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFNldHMgb3IgdXBkYXRlcyB0aGUgdmFsdWUgb2YgJ2Nvbm5lY3Rpb24nIHByb3BlcnR5LiBUcmlnZ2VyZWQgYnkgU2Vzc2lvbkludGVybmFsIHdoZW4gc3VjY2VzZnVsIGNvbm5lY3Rpb25cbiAgICAgICAgdGhpcy5zZXNzaW9uLmFkZEV2ZW50TGlzdGVuZXIoJ3VwZGF0ZS1jb25uZWN0aW9uLW9iamVjdCcsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IGV2ZW50LmNvbm5lY3Rpb247XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGNvbm5lY3QodG9rZW46IHN0cmluZywgY2FsbGJhY2s6IGFueSk7XG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YTogYW55LCBjYWxsYmFjazogYW55KTtcblxuICAgIGNvbm5lY3QocGFyYW0xLCBwYXJhbTIsIHBhcmFtMz8pIHtcbiAgICAgICAgLy8gRWFybHkgY29uZmlndXJhdGlvbiB0byBkZWFjdGl2YXRlIGF1dG9tYXRpYyBzdWJzY3JpcHRpb24gdG8gc3RyZWFtc1xuICAgICAgICBpZiAocGFyYW0zKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5vcGVuVmlkdS5jaGVja1N5c3RlbVJlcXVpcmVtZW50cygpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmNvbmZpZ3VyZSh7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb25JZDogdGhpcy5zZXNzaW9uLmdldFNlc3Npb25JZCgpLFxuICAgICAgICAgICAgICAgICAgICBwYXJ0aWNpcGFudElkOiBwYXJhbTEsXG4gICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiB0aGlzLnNlc3Npb24uc3RyaW5nQ2xpZW50TWV0YWRhdGEocGFyYW0yKSxcbiAgICAgICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9TdHJlYW1zOiBmYWxzZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5jb25uZWN0KHBhcmFtMSwgcGFyYW0zKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcGFyYW0zKG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkJST1dTRVJfTk9UX1NVUFBPUlRFRCwgJ0Jyb3dzZXIgJyArIERldGVjdFJUQy5icm93c2VyLm5hbWUgKyAnICcgKyBEZXRlY3RSVEMuYnJvd3Nlci52ZXJzaW9uICsgJyBpcyBub3Qgc3VwcG9ydGVkIGluIE9wZW5WaWR1JykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHRoaXMub3BlblZpZHUuY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5jb25maWd1cmUoe1xuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uSWQ6IHRoaXMuc2Vzc2lvbi5nZXRTZXNzaW9uSWQoKSxcbiAgICAgICAgICAgICAgICAgICAgcGFydGljaXBhbnRJZDogcGFyYW0xLFxuICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogJycsXG4gICAgICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvU3RyZWFtczogZmFsc2VcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uY29ubmVjdChwYXJhbTEsIHBhcmFtMik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBhcmFtMihuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5CUk9XU0VSX05PVF9TVVBQT1JURUQsICdCcm93c2VyICcgKyBEZXRlY3RSVEMuYnJvd3Nlci5uYW1lICsgJyAnICsgRGV0ZWN0UlRDLmJyb3dzZXIudmVyc2lvbiArICcgaXMgbm90IHN1cHBvcnRlZCBpbiBPcGVuVmlkdScpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGRpc2Nvbm5lY3QoKSB7XG4gICAgICAgIHRoaXMub3BlblZpZHUub3BlblZpZHUuY2xvc2UoZmFsc2UpO1xuICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzZXNzaW9uRGlzY29ubmVjdGVkJywgW3tcbiAgICAgICAgICAgIHByZXZlbnREZWZhdWx0OiAoKSA9PiB7IHRoaXMuc2Vzc2lvbi5yZW1vdmVFdmVudCgnc2Vzc2lvbi1kaXNjb25uZWN0ZWQtZGVmYXVsdCcpOyB9XG4gICAgICAgIH1dKTtcbiAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc2Vzc2lvbi1kaXNjb25uZWN0ZWQtZGVmYXVsdCcsIFt7fV0pO1xuICAgIH1cblxuICAgIHB1Ymxpc2gocHVibGlzaGVyOiBQdWJsaXNoZXIpIHtcbiAgICAgICAgaWYgKCFwdWJsaXNoZXIuc3RyZWFtLmlzUHVibGlzaGVyUHVibGlzaGVkKSB7IC8vICdTZXNzaW9uLnVucHVibGlzaChQdWJsaXNoZXIpJyBoYXMgTk9UIGJlZW4gY2FsbGVkXG4gICAgICAgICAgICBpZiAocHVibGlzaGVyLmlzU2NyZWVuUmVxdWVzdGVkKSB7IC8vIFNjcmVlbiBzaGFyaW5nIFB1Ymxpc2hlclxuICAgICAgICAgICAgICAgIGlmICghcHVibGlzaGVyLnN0cmVhbS5pc1NjcmVlblJlcXVlc3RlZFJlYWR5KSB7IC8vIFNjcmVlbiB2aWRlbyBzdHJlYW0gaXMgbm90IGF2YWlsYWJsZSB5ZXRcbiAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5hZGRPbmNlRXZlbnRMaXN0ZW5lcignc2NyZWVuLXJlYWR5JywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1QdWJsaXNoKHB1Ymxpc2hlcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7IC8vIC8vIFNjcmVlbiB2aWRlbyBzdHJlYW0gaXMgYWxyZWFkeSBhdmFpbGFibGVcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1QdWJsaXNoKHB1Ymxpc2hlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHsgLy8gQXVkaW8tVmlkZW8gUHVibGlzaGVyXG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1QdWJsaXNoKHB1Ymxpc2hlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7IC8vICdTZXNzaW9uLnVucHVibGlzaChQdWJsaXNoZXIpJyBoYXMgYmVlbiBjYWxsZWRcbiAgICAgICAgICAgIHB1Ymxpc2hlciA9IHRoaXMub3BlblZpZHUucmVpbml0UHVibGlzaGVyKHB1Ymxpc2hlcik7XG5cbiAgICAgICAgICAgIGlmIChwdWJsaXNoZXIuaXNTY3JlZW5SZXF1ZXN0ZWQgJiYgIXB1Ymxpc2hlci5zdHJlYW0uaXNTY3JlZW5SZXF1ZXN0ZWRSZWFkeSkgeyAvLyBTY3JlZW4gc2hhcmluZyBQdWJsaXNoZXIgYW5kIHZpZGVvIHN0cmVhbSBub3QgYXZhaWxhYmxlIHlldFxuICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0uYWRkT25jZUV2ZW50TGlzdGVuZXIoJ3NjcmVlbi1yZWFkeScsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1QdWJsaXNoKHB1Ymxpc2hlcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2UgeyAvLyBWaWRlbyBzdHJlYW0gYWxyZWFkeSBhdmFpbGFibGVcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbVB1Ymxpc2gocHVibGlzaGVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc3RyZWFtUHVibGlzaChwdWJsaXNoZXI6IFB1Ymxpc2hlcikge1xuICAgICAgICBwdWJsaXNoZXIuc2Vzc2lvbiA9IHRoaXM7XG4gICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgIHB1Ymxpc2hlci5zdHJlYW0ucHVibGlzaCgpO1xuICAgIH1cblxuICAgIHVucHVibGlzaChwdWJsaXNoZXI6IFB1Ymxpc2hlcikge1xuICAgICAgICB0aGlzLnNlc3Npb24udW5wdWJsaXNoKHB1Ymxpc2hlcik7XG4gICAgfVxuXG4gICAgb24oZXZlbnROYW1lOiBzdHJpbmcsIGNhbGxiYWNrKSB7XG4gICAgICAgIHRoaXMuc2Vzc2lvbi5hZGRFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgZXZlbnROYW1lICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyBldmVudE5hbWUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdTZXNzaW9uJ1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhbGxiYWNrKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgb25jZShldmVudE5hbWU6IHN0cmluZywgY2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5zZXNzaW9uLmFkZE9uY2VFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgY2FsbGJhY2soZXZlbnQpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBvZmYoZXZlbnROYW1lOiBzdHJpbmcsIGV2ZW50SGFuZGxlcikge1xuICAgICAgICB0aGlzLnNlc3Npb24ucmVtb3ZlTGlzdGVuZXIoZXZlbnROYW1lLCBldmVudEhhbmRsZXIpO1xuICAgIH1cblxuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgaHRtbElkOiBzdHJpbmcsIHZpZGVvT3B0aW9uczogYW55KTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIGh0bWxJZDogc3RyaW5nKTogU3Vic2NyaWJlcjtcblxuICAgIHN1YnNjcmliZShwYXJhbTEsIHBhcmFtMiwgcGFyYW0zPyk6IFN1YnNjcmliZXIge1xuICAgICAgICAvLyBTdWJzY3JpcHRpb25cbiAgICAgICAgdGhpcy5zZXNzaW9uLnN1YnNjcmliZShwYXJhbTEpO1xuICAgICAgICBsZXQgc3Vic2NyaWJlciA9IG5ldyBTdWJzY3JpYmVyKHBhcmFtMSwgcGFyYW0yKTtcbiAgICAgICAgcGFyYW0xLnBsYXlPbmx5VmlkZW8ocGFyYW0yLCBudWxsKTtcbiAgICAgICAgcmV0dXJuIHN1YnNjcmliZXI7XG4gICAgfVxuXG4gICAgdW5zdWJzY3JpYmUoc3Vic2NyaWJlcjogU3Vic2NyaWJlcikge1xuICAgICAgICB0aGlzLnNlc3Npb24udW5zdWJzY3JpYmUoc3Vic2NyaWJlci5zdHJlYW0pO1xuICAgICAgICBzdWJzY3JpYmVyLnN0cmVhbS5yZW1vdmVWaWRlbygpO1xuICAgIH1cblxuICAgIHNpZ25hbChzaWduYWw6IFNpZ25hbE9wdGlvbnMsIGNvbXBsZXRpb25IYW5kbGVyPzogRnVuY3Rpb24pIHtcbiAgICAgICAgdmFyIHNpZ25hbE1lc3NhZ2UgPSB7fTtcblxuICAgICAgICBpZiAoc2lnbmFsLnRvICYmIHNpZ25hbC50by5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBsZXQgY29ubmVjdGlvbklkczogc3RyaW5nW10gPSBbXTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2lnbmFsLnRvLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbklkcy5wdXNoKHNpZ25hbC50b1tpXS5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2lnbmFsTWVzc2FnZVsndG8nXSA9IGNvbm5lY3Rpb25JZHM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0byddID0gW107XG4gICAgICAgIH1cblxuICAgICAgICBzaWduYWxNZXNzYWdlWydkYXRhJ10gPSBzaWduYWwuZGF0YSA/IHNpZ25hbC5kYXRhIDogJyc7XG4gICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3R5cGUnXSA9IHNpZ25hbC50eXBlID8gc2lnbmFsLnR5cGUgOiAnJztcblxuICAgICAgICB0aGlzLm9wZW5WaWR1Lm9wZW5WaWR1LnNlbmRNZXNzYWdlKEpTT04uc3RyaW5naWZ5KHNpZ25hbE1lc3NhZ2UpKTtcbiAgICB9XG5cbn1cbiIsImltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvU3RyZWFtJztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cbmV4cG9ydCBjbGFzcyBTdWJzY3JpYmVyIHtcblxuICAgIHByaXZhdGUgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgICBlbGVtZW50OiBFbGVtZW50O1xuICAgIGlkOiBzdHJpbmc7XG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICBjb25zdHJ1Y3RvcihzdHJlYW06IFN0cmVhbSwgcGFyZW50SWQ6IHN0cmluZykge1xuICAgICAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTtcbiAgICAgICAgaWYgKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHBhcmVudElkKSAhPSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLmVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChwYXJlbnRJZCkhITtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIExpc3RlbnMgdG8gZGVsZXRpb24gb2YgdGhlIEhUTUwgdmlkZW8gZWxlbWVudCBvZiB0aGUgU3Vic2NyaWJlclxuICAgICAgICB0aGlzLnN0cmVhbS5hZGRFdmVudExpc3RlbmVyKCd2aWRlby1yZW1vdmVkJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudERlc3Ryb3llZCcpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBvbihldmVudE5hbWU6IHN0cmluZywgY2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5lZS5hZGRMaXN0ZW5lcihldmVudE5hbWUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIGV2ZW50TmFtZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1N1YnNjcmliZXInXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgZXZlbnROYW1lICsgXCInIHRyaWdnZXJlZCBieSAnU3Vic2NyaWJlcidcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYWxsYmFjayhldmVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoZXZlbnROYW1lID09ICd2aWRlb0VsZW1lbnRDcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzVmlkZW9FTGVtZW50Q3JlYXRlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW3tcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudDogdGhpcy5zdHJlYW0uZ2V0VmlkZW9FbGVtZW50KClcbiAgICAgICAgICAgICAgICB9XSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmFkZE9uY2VFdmVudExpc3RlbmVyKCd2aWRlby1lbGVtZW50LWNyZWF0ZWQtYnktc3RyZWFtJywgZWxlbWVudCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaWQgPSBlbGVtZW50LmlkO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFt7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50OiBlbGVtZW50XG4gICAgICAgICAgICAgICAgICAgIH1dKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoZXZlbnROYW1lID09ICd2aWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICB2YXIgdmlkZW8gPSB0aGlzLnN0cmVhbS5nZXRWaWRlb0VsZW1lbnQoKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgJiYgdmlkZW8gJiZcbiAgICAgICAgICAgICAgICB2aWRlby5jdXJyZW50VGltZSA+IDAgJiYgXG4gICAgICAgICAgICAgICAgdmlkZW8ucGF1c2VkID09IGZhbHNlICYmIFxuICAgICAgICAgICAgICAgIHZpZGVvLmVuZGVkID09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdmlkZW8ucmVhZHlTdGF0ZSA9PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudDogdGhpcy5zdHJlYW0uZ2V0VmlkZW9FbGVtZW50KClcbiAgICAgICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5hZGRPbmNlRXZlbnRMaXN0ZW5lcigndmlkZW8taXMtcGxheWluZycsIChlbGVtZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudDogZWxlbWVudC5lbGVtZW50XG4gICAgICAgICAgICAgICAgICAgIH1dKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn0iLCJpbXBvcnQgeyBTdHJlYW0sIFN0cmVhbU9wdGlvbnNTZXJ2ZXIsIEluYm91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgT3BlblZpZHVJbnRlcm5hbCB9IGZyb20gJy4vT3BlblZpZHVJbnRlcm5hbCc7XG5pbXBvcnQgeyBTZXNzaW9uSW50ZXJuYWwgfSBmcm9tICcuL1Nlc3Npb25JbnRlcm5hbCc7XG5cbnR5cGUgT2JqTWFwPFQ+ID0geyBbczogc3RyaW5nXTogVDsgfVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbm5lY3Rpb25PcHRpb25zIHtcbiAgICBpZDogc3RyaW5nO1xuICAgIG1ldGFkYXRhOiBzdHJpbmc7XG4gICAgc3RyZWFtczogU3RyZWFtT3B0aW9uc1NlcnZlcltdO1xufVxuXG5leHBvcnQgY2xhc3MgQ29ubmVjdGlvbiB7XG5cbiAgICBwdWJsaWMgY29ubmVjdGlvbklkOiBzdHJpbmc7XG4gICAgcHVibGljIGRhdGE6IHN0cmluZztcbiAgICBwdWJsaWMgY3JlYXRpb25UaW1lOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBzdHJlYW1zOiBPYmpNYXA8U3RyZWFtPiA9IHt9O1xuICAgIHByaXZhdGUgaW5ib3VuZFN0cmVhbXNPcHRzOiBJbmJvdW5kU3RyZWFtT3B0aW9ucztcblxuICAgIGNvbnN0cnVjdG9yKCBwcml2YXRlIG9wZW5WaWR1OiBPcGVuVmlkdUludGVybmFsLCBwcml2YXRlIGxvY2FsOiBib29sZWFuLCBwcml2YXRlIHJvb206IFNlc3Npb25JbnRlcm5hbCwgcHJpdmF0ZSBvcHRpb25zPzogQ29ubmVjdGlvbk9wdGlvbnMgKSB7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCBcIidDb25uZWN0aW9uJyBjcmVhdGVkIChcIiArICggbG9jYWwgPyBcImxvY2FsXCIgOiBcInJlbW90ZVwiICkgKyBcIilcIiArICggbG9jYWwgPyBcIlwiIDogXCIsIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgKG9wdGlvbnMgPyBvcHRpb25zLmlkIDogJycpICsgXCJdIFwiICkpO1xuXG4gICAgICAgIGlmICggb3B0aW9ucyAmJiAhbG9jYWwgKSB7XG5cbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbklkID0gb3B0aW9ucy5pZDtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLm1ldGFkYXRhKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRhID0gb3B0aW9ucy5tZXRhZGF0YTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvcHRpb25zLnN0cmVhbXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRSZW1vdGVTdHJlYW1zKG9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIFxuICAgIH1cblxuICAgIGFkZFN0cmVhbSggc3RyZWFtOiBTdHJlYW0gKSB7XG4gICAgICAgIHN0cmVhbS5jb25uZWN0aW9uID0gdGhpcztcbiAgICAgICAgdGhpcy5zdHJlYW1zW3N0cmVhbS5zdHJlYW1JZF0gPSBzdHJlYW07XG4gICAgICAgIC8vdGhpcy5yb29tLmdldFN0cmVhbXMoKVtzdHJlYW0uc3RyZWFtSWRdID0gc3RyZWFtO1xuICAgIH1cblxuICAgIHJlbW92ZVN0cmVhbSgga2V5OiBzdHJpbmcgKSB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLnN0cmVhbXNba2V5XTtcbiAgICAgICAgLy9kZWxldGUgdGhpcy5yb29tLmdldFN0cmVhbXMoKVtrZXldO1xuICAgICAgICBkZWxldGUgdGhpcy5pbmJvdW5kU3RyZWFtc09wdHM7XG4gICAgfVxuXG4gICAgc2V0T3B0aW9ucyhvcHRpb25zOiBDb25uZWN0aW9uT3B0aW9ucykge1xuICAgICAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuICAgIH1cblxuICAgIGdldFN0cmVhbXMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0cmVhbXM7XG4gICAgfVxuXG4gICAgZGlzcG9zZSgpIHtcbiAgICAgICAgZm9yICggbGV0IGtleSBpbiB0aGlzLnN0cmVhbXMgKSB7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbXNba2V5XS5kaXNwb3NlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzZW5kSWNlQ2FuZGlkYXRlKCBjYW5kaWRhdGUgKSB7XG5cbiAgICAgICAgY29uc29sZS5kZWJ1ZygoIHRoaXMubG9jYWwgPyBcIkxvY2FsXCIgOiBcIlJlbW90ZVwiICksIFwiY2FuZGlkYXRlIGZvclwiLFxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQsIEpTT04uc3RyaW5naWZ5KCBjYW5kaWRhdGUgKSApO1xuXG4gICAgICAgIHRoaXMub3BlblZpZHUuc2VuZFJlcXVlc3QoIFwib25JY2VDYW5kaWRhdGVcIiwge1xuICAgICAgICAgICAgZW5kcG9pbnROYW1lOiB0aGlzLmNvbm5lY3Rpb25JZCxcbiAgICAgICAgICAgIGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSxcbiAgICAgICAgICAgIHNkcE1pZDogY2FuZGlkYXRlLnNkcE1pZCxcbiAgICAgICAgICAgIHNkcE1MaW5lSW5kZXg6IGNhbmRpZGF0ZS5zZHBNTGluZUluZGV4XG4gICAgICAgIH0sIGZ1bmN0aW9uKCBlcnJvciwgcmVzcG9uc2UgKSB7XG4gICAgICAgICAgICBpZiAoIGVycm9yICkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoIFwiRXJyb3Igc2VuZGluZyBJQ0UgY2FuZGlkYXRlOiBcIlxuICAgICAgICAgICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KCBlcnJvciApICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGluaXRSZW1vdGVTdHJlYW1zKG9wdGlvbnM6IENvbm5lY3Rpb25PcHRpb25zKSB7XG4gICAgICAgIGxldCBvcHRzOiBTdHJlYW1PcHRpb25zU2VydmVyO1xuICAgICAgICBmb3IgKCBvcHRzIG9mIG9wdGlvbnMuc3RyZWFtcyApIHtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbGV0IHN0cmVhbU9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIGlkOiBvcHRzLmlkLFxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb246IHRoaXMsXG4gICAgICAgICAgICAgICAgcmVjdkF1ZGlvOiAoIG9wdHMuYXVkaW9BY3RpdmUgPT0gbnVsbCA/IHRydWUgOiBvcHRzLmF1ZGlvQWN0aXZlICksXG4gICAgICAgICAgICAgICAgcmVjdlZpZGVvOiAoIG9wdHMudmlkZW9BY3RpdmUgPT0gbnVsbCA/IHRydWUgOiBvcHRzLnZpZGVvQWN0aXZlICksXG4gICAgICAgICAgICAgICAgdHlwZU9mVmlkZW86IG9wdHMudHlwZU9mVmlkZW8sXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgc3RyZWFtID0gbmV3IFN0cmVhbSh0aGlzLm9wZW5WaWR1LCBmYWxzZSwgdGhpcy5yb29tLCBzdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgdGhpcy5hZGRTdHJlYW0oc3RyZWFtKTtcbiAgICAgICAgICAgIHRoaXMuaW5ib3VuZFN0cmVhbXNPcHRzID0gc3RyZWFtT3B0aW9ucztcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnQ29ubmVjdGlvbicgd2l0aCAnY29ubmVjdGlvbklkJyBbXCIgKyB0aGlzLmNvbm5lY3Rpb25JZCArIFwiXSBpcyBub3cgY29uZmlndXJlZCBmb3IgcmVjZWl2aW5nIFN0cmVhbXMgd2l0aCBvcHRpb25zOiBcIiwgdGhpcy5pbmJvdW5kU3RyZWFtc09wdHMgKTtcbiAgICB9XG59IiwiaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSBcIi4vU3RyZWFtXCI7XG5cbmRlY2xhcmUgdmFyIE1lZGlhUmVjb3JkZXI6IGFueTtcblxuZXhwb3J0IGNvbnN0IGVudW0gTG9jYWxSZWNvZGVyU3RhdGUge1xuICAgIFJFQURZID0gJ1JFQURZJyxcbiAgICBSRUNPUkRJTkcgPSAnUkVDT1JESU5HJyxcbiAgICBQQVVTRUQgPSAnUEFVU0VEJyxcbiAgICBGSU5JU0hFRCA9ICdGSU5JU0hFRCdcbn1cblxuZXhwb3J0IGNsYXNzIExvY2FsUmVjb3JkZXIge1xuXG4gICAgc3RhdGU6IExvY2FsUmVjb2RlclN0YXRlO1xuXG4gICAgcHJpdmF0ZSBzdHJlYW06IFN0cmVhbTtcbiAgICBwcml2YXRlIGNvbm5lY3Rpb25JZDogc3RyaW5nO1xuXG4gICAgcHJpdmF0ZSBtZWRpYVJlY29yZGVyOiBhbnk7XG4gICAgcHJpdmF0ZSBjaHVua3M6IGFueVtdID0gW107XG4gICAgcHJpdmF0ZSBibG9iOiBCbG9iO1xuICAgIHByaXZhdGUgY291bnQ6IG51bWJlciA9IDA7XG4gICAgcHJpdmF0ZSBpZDogc3RyaW5nO1xuXG4gICAgcHJpdmF0ZSB2aWRlb1ByZXZpZXdTcmM6IHN0cmluZztcbiAgICBwcml2YXRlIGh0bWxQYXJlbnRFbGVtZW50SWQ6IHN0cmluZztcbiAgICBwcml2YXRlIHZpZGVvUHJldmlldzogSFRNTFZpZGVvRWxlbWVudDtcblxuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtKSB7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLmNvbm5lY3Rpb25JZCA9ICghIXRoaXMuc3RyZWFtLmNvbm5lY3Rpb24pID8gdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgOiAnZGVmYXVsdC1jb25uZWN0aW9uJztcbiAgICAgICAgdGhpcy5pZCA9IHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ18nICsgdGhpcy5jb25uZWN0aW9uSWQgKyAnX2xvY2FscmVjb3JkJztcbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb2RlclN0YXRlLlJFQURZO1xuICAgIH1cblxuICAgIHJlY29yZCgpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBNZWRpYVJlY29yZGVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignTWVkaWFSZWNvcmRlciBub3Qgc3VwcG9ydGVkIG9uIHlvdXIgYnJvd3Nlci4gU2VlIGNvbXBhdGliaWxpdHkgaW4gaHR0cHM6Ly9jYW5pdXNlLmNvbS8jc2VhcmNoPU1lZGlhUmVjb3JkZXInKTtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignTWVkaWFSZWNvcmRlciBub3Qgc3VwcG9ydGVkIG9uIHlvdXIgYnJvd3Nlci4gU2VlIGNvbXBhdGliaWxpdHkgaW4gaHR0cHM6Ly9jYW5pdXNlLmNvbS8jc2VhcmNoPU1lZGlhUmVjb3JkZXInKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb2RlclN0YXRlLlJFQURZKSB7XG4gICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnJlY29yZCgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1JFQURZXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuY2xlYW4oKVxcJyBvciBpbml0IGEgbmV3IExvY2FsUmVjb3JkZXIgYmVmb3JlJykpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUubG9nKFwiU3RhcnRpbmcgbG9jYWwgcmVjb3JkaW5nIG9mIHN0cmVhbSAnXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArIFwiJyBvZiBjb25uZWN0aW9uICdcIiArIHRoaXMuY29ubmVjdGlvbklkICsgXCInXCIpO1xuICAgICAgICBpZiAodHlwZW9mIE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkID09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGxldCBvcHRpb25zO1xuICAgICAgICAgICAgaWYgKE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkKCd2aWRlby93ZWJtO2NvZGVjcz12cDknKSkge1xuICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7IG1pbWVUeXBlOiAndmlkZW8vd2VibTtjb2RlY3M9dnA5JyB9O1xuICAgICAgICAgICAgfSBlbHNlIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9aDI2NCcpKSB7XG4gICAgICAgICAgICAgICAgb3B0aW9ucyA9IHsgbWltZVR5cGU6ICd2aWRlby93ZWJtO2NvZGVjcz1oMjY0JyB9O1xuICAgICAgICAgICAgfSBlbHNlIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9dnA4JykpIHtcbiAgICAgICAgICAgICAgICBvcHRpb25zID0geyBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOCcgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdVc2luZyBtaW1lVHlwZSAnICsgb3B0aW9ucy5taW1lVHlwZSk7XG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLCBvcHRpb25zKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignaXNUeXBlU3VwcG9ydGVkIGlzIG5vdCBzdXBwb3J0ZWQsIHVzaW5nIGRlZmF1bHQgY29kZWNzIGZvciBicm93c2VyJyk7XG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5zdGFydCgxMCk7XG5cbiAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZGF0YWF2YWlsYWJsZSA9IChlKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNodW5rcy5wdXNoKGUuZGF0YSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZXJyb3IgPSAoZSkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignTWVkaWFSZWNvcmRlciBlcnJvcjogJywgZSk7XG4gICAgICAgIH07XG5cblxuICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdGFydCA9ICgpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHN0YXJ0ZWQgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyBcIilcIik7XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RvcCA9ICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMub25TdG9wRGVmYXVsdCgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnBhdXNlID0gKCkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgcGF1c2VkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgXCIpXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ucmVzdW1lID0gKCkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgcmVzdW1lZCAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArIFwiKVwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbndhcm5pbmcgPSAoZSkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgd2FybmluZzogJyArIGUpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29kZXJTdGF0ZS5SRUNPUkRJTkc7XG4gICAgfVxuXG4gICAgc3RvcCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvZGVyU3RhdGUuUkVBRFkgfHwgdGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5zdG9wKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVDT1JESU5HXFwnIG9yIFxcJ1BBVVNFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0YXJ0KClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdG9wID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm9uU3RvcERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5zdG9wKCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwYXVzZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb2RlclN0YXRlLlJFQ09SRElORykge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5wYXVzZSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1JFQ09SRElOR1xcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0YXJ0KClcXCcgb3IgXFwnTG9jYWxSZWNvcmRlci5yZXN1bWUoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnBhdXNlKCk7XG4gICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29kZXJTdGF0ZS5QQVVTRUQ7XG4gICAgfVxuXG4gICAgcmVzdW1lKCkge1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnJlc3VtZSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1BBVVNFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnBhdXNlKClcXCcgYmVmb3JlJykpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5yZXN1bWUoKTtcbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb2RlclN0YXRlLlJFQ09SRElORztcbiAgICB9XG5cbiAgICBwcmV2aWV3KHBhcmVudEVsZW1lbnQpOiBIVE1MVmlkZW9FbGVtZW50IHtcblxuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucHJldmlldygpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlldy5pZCA9IHRoaXMuaWQ7XG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LmF1dG9wbGF5ID0gdHJ1ZTtcblxuICAgICAgICBpZiAodHlwZW9mIHBhcmVudEVsZW1lbnQgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIHRoaXMuaHRtbFBhcmVudEVsZW1lbnRJZCA9IHBhcmVudEVsZW1lbnQ7XG5cbiAgICAgICAgICAgIGxldCBwYXJlbnRFbGVtZW50RG9tID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocGFyZW50RWxlbWVudCk7XG4gICAgICAgICAgICBpZiAocGFyZW50RWxlbWVudERvbSkge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gcGFyZW50RWxlbWVudERvbS5hcHBlbmRDaGlsZCh0aGlzLnZpZGVvUHJldmlldyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmh0bWxQYXJlbnRFbGVtZW50SWQgPSBwYXJlbnRFbGVtZW50LmlkO1xuICAgICAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMudmlkZW9QcmV2aWV3KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LnNyYyA9IHRoaXMudmlkZW9QcmV2aWV3U3JjO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnZpZGVvUHJldmlldztcbiAgICB9XG5cbiAgICBjbGVhbigpIHtcbiAgICAgICAgbGV0IGYgPSAoKSA9PiB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5ibG9iO1xuICAgICAgICAgICAgdGhpcy5jaHVua3MgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuY291bnQgPSAwO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMubWVkaWFSZWNvcmRlcjtcbiAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29kZXJTdGF0ZS5SRUFEWTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvZGVyU3RhdGUuUkVDT1JESU5HIHx8IHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb2RlclN0YXRlLlBBVVNFRCkge1xuICAgICAgICAgICAgdGhpcy5zdG9wKCkudGhlbigoKSA9PiBmKCkpLmNhdGNoKCgpID0+IGYoKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBkb3dubG9hZCgpIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb2RlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLmRvd25sb2FkKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbGV0IGE6IEhUTUxBbmNob3JFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImFcIik7XG4gICAgICAgICAgICBhLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGEpO1xuXG4gICAgICAgICAgICBsZXQgdXJsID0gd2luZG93LlVSTC5jcmVhdGVPYmplY3RVUkwodGhpcy5ibG9iKTtcbiAgICAgICAgICAgIGEuaHJlZiA9IHVybDtcbiAgICAgICAgICAgIGEuZG93bmxvYWQgPSB0aGlzLmlkICsgJy53ZWJtJztcbiAgICAgICAgICAgIGEuY2xpY2soKTtcbiAgICAgICAgICAgIHdpbmRvdy5VUkwucmV2b2tlT2JqZWN0VVJMKHVybCk7XG5cbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoYSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBnZXRCbG9iKCk6IEJsb2Ige1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignQ2FsbCBcXCdMb2NhbFJlY29yZC5zdG9wKClcXCcgYmVmb3JlIGdldHRpbmcgQmxvYiBmaWxlJykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYmxvYjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHVwbG9hZEFzQmluYXJ5KGVuZHBvaW50OiBzdHJpbmcsIGhlYWRlcnM/OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb2RlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKCdcXCdMb2NhbFJlY29yZC51cGxvYWRBc0JpbmFyeSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbGV0IGh0dHAgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgICAgICBodHRwLm9wZW4oXCJQT1NUXCIsIGVuZHBvaW50LCB0cnVlKTtcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGhlYWRlcnMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhoZWFkZXJzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaHR0cC5zZXRSZXF1ZXN0SGVhZGVyKGtleSwgaGVhZGVyc1trZXldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGh0dHAub25yZWFkeXN0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5zdGF0dXMudG9TdHJpbmcoKS5jaGFyQXQoMCkgPT09ICcyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN1Y2Nlc3MgcmVzcG9uc2UgZnJvbSBzZXJ2ZXIgKEhUVFAgc3RhdHVzIHN0YW5kYXJkOiAyWFggaXMgc3VjY2VzcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGh0dHAucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKFwiVXBsb2FkIGVycm9yOiBcIiArIGh0dHAuc3RhdHVzKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaHR0cC5zZW5kKHRoaXMuYmxvYik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHVwbG9hZEFzTXVsdGlwYXJ0ZmlsZShlbmRwb2ludDogc3RyaW5nLCBoZWFkZXJzPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29kZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQudXBsb2FkQXNNdWx0aXBhcnRmaWxlKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBsZXQgaHR0cCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgIGh0dHAub3BlbihcIlBPU1RcIiwgZW5kcG9pbnQsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBoZWFkZXJzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMoaGVhZGVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcihrZXksIGhlYWRlcnNba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBsZXQgc2VuZGFibGUgPSBuZXcgRm9ybURhdGEoKTtcbiAgICAgICAgICAgICAgICBzZW5kYWJsZS5hcHBlbmQoXCJmaWxlXCIsIHRoaXMuYmxvYiwgdGhpcy5pZCArIFwiLndlYm1cIik7XG5cbiAgICAgICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAuc3RhdHVzLnRvU3RyaW5nKCkuY2hhckF0KDApID09PSAnMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzIHJlc3BvbnNlIGZyb20gc2VydmVyIChIVFRQIHN0YXR1cyBzdGFuZGFyZDogMlhYIGlzIHN1Y2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcihcIlVwbG9hZCBlcnJvcjogXCIgKyBodHRwLnN0YXR1cykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaHR0cC5zZW5kKHNlbmRhYmxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvblN0b3BEZWZhdWx0KCkge1xuICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciBzdG9wcGVkICAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArIFwiKVwiKTtcblxuICAgICAgICB0aGlzLmJsb2IgPSBuZXcgQmxvYih0aGlzLmNodW5rcywgeyB0eXBlOiBcInZpZGVvL3dlYm1cIiB9KTtcbiAgICAgICAgdGhpcy5jaHVua3MgPSBbXTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlld1NyYyA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG5cbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb2RlclN0YXRlLkZJTklTSEVEO1xuICAgIH1cblxufVxuIiwiZXhwb3J0IGNvbnN0IGVudW0gT3BlblZpZHVFcnJvck5hbWUge1xuICAgIEJST1dTRVJfTk9UX1NVUFBPUlRFRCA9ICdCUk9XU0VSX05PVF9TVVBQT1JURUQnLFxuICAgIENBTUVSQV9BQ0NFU1NfREVOSUVEID0gJ0NBTUVSQV9BQ0NFU1NfREVOSUVEJyxcbiAgICBNSUNST1BIT05FX0FDQ0VTU19ERU5JRUQgPSAnTUlDUk9QSE9ORV9BQ0NFU1NfREVOSUVEJyxcbiAgICBTQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgPSAnU0NSRUVOX0NBUFRVUkVfREVOSUVEJyxcbiAgICBOT19WSURFT19ERVZJQ0UgPSAnTk9fVklERU9fREVWSUNFJyxcbiAgICBOT19JTlBVVF9ERVZJQ0UgPSAnTk9fSU5QVVRfREVWSUNFJyxcbiAgICBTQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVEID0gJ1NDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQnLFxuICAgIFNDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCA9ICdTQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQnLFxuICAgIEdFTkVSSUNfRVJST1IgPSAnR0VORVJJQ19FUlJPUidcbn1cblxuZXhwb3J0IGNsYXNzIE9wZW5WaWR1RXJyb3Ige1xuXG4gICAgbmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG4gICAgbWVzc2FnZTogc3RyaW5nO1xuXG4gICAgY29uc3RydWN0b3IobmFtZTogT3BlblZpZHVFcnJvck5hbWUsIG1lc3NhZ2U6IHN0cmluZykge1xuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTcgT3BlblZpZHUgKGh0dHA6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cbmltcG9ydCB7IFNlc3Npb25JbnRlcm5hbCwgU2Vzc2lvbk9wdGlvbnMgfSBmcm9tICcuL1Nlc3Npb25JbnRlcm5hbCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi9Db25uZWN0aW9uJztcbmltcG9ydCB7IE9wZW5WaWR1RXJyb3IsIE9wZW5WaWR1RXJyb3JOYW1lIH0gZnJvbSAnLi9PcGVuVmlkdUVycm9yJztcbmltcG9ydCB7IFN0cmVhbSwgT3V0Ym91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0ICogYXMgUnBjQnVpbGRlciBmcm9tICcuLi9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjJztcblxuZXhwb3J0IHR5cGUgQ2FsbGJhY2s8VD4gPSAoZXJyb3I/OiBhbnksIG9wZW5WaWR1PzogVCkgPT4gdm9pZDtcblxuZXhwb3J0IGNsYXNzIE9wZW5WaWR1SW50ZXJuYWwge1xuXG4gICAgcHJpdmF0ZSB3c1VyaTtcbiAgICBwcml2YXRlIHNlc3Npb246IFNlc3Npb25JbnRlcm5hbDtcbiAgICBwcml2YXRlIGpzb25ScGNDbGllbnQ6IGFueTtcbiAgICBwcml2YXRlIHJwY1BhcmFtczogYW55O1xuICAgIHByaXZhdGUgY2FsbGJhY2s6IENhbGxiYWNrPE9wZW5WaWR1SW50ZXJuYWw+O1xuICAgIHByaXZhdGUgbG9jYWxTdHJlYW06IFN0cmVhbTtcbiAgICBwcml2YXRlIHNlY3JldDogc3RyaW5nO1xuICAgIHByaXZhdGUgcmVjb3JkZXI6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIC8qIE5FVyBNRVRIT0RTICovXG4gICAgaW5pdFNlc3Npb24oc2Vzc2lvbklkKSB7XG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIidTZXNzaW9uJyBpbml0aWFsaXplZCB3aXRoICdzZXNzaW9uSWQnIFtcIiArIHNlc3Npb25JZCArIFwiXVwiKTtcbiAgICAgICAgdGhpcy5zZXNzaW9uID0gbmV3IFNlc3Npb25JbnRlcm5hbCh0aGlzLCBzZXNzaW9uSWQpO1xuICAgICAgICByZXR1cm4gdGhpcy5zZXNzaW9uO1xuICAgIH1cblxuICAgIGluaXRQdWJsaXNoZXJUYWdnZWQocGFyZW50SWQ6IHN0cmluZywgY2FtZXJhT3B0aW9uczogT3V0Ym91bmRTdHJlYW1PcHRpb25zLCBuZXdTdHJlYW06IGJvb2xlYW4sIGNhbGxiYWNrPzogRnVuY3Rpb24pOiBTdHJlYW0ge1xuXG4gICAgICAgIGlmIChuZXdTdHJlYW0pIHtcbiAgICAgICAgICAgIGlmIChjYW1lcmFPcHRpb25zID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBjYW1lcmFPcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICBzZW5kQXVkaW86IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIHNlbmRWaWRlbzogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgYWN0aXZlQXVkaW86IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIGFjdGl2ZVZpZGVvOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBkYXRhQ2hhbm5lbDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czoge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXVkaW86IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICB2aWRlbzogeyB3aWR0aDogeyBpZGVhbDogMTI4MCB9IH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMubG9jYWxTdHJlYW0gPSBuZXcgU3RyZWFtKHRoaXMsIHRydWUsIHRoaXMuc2Vzc2lvbiwgY2FtZXJhT3B0aW9ucyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmxvY2FsU3RyZWFtLnJlcXVlc3RDYW1lcmFBY2Nlc3MoKGVycm9yLCBsb2NhbFN0cmVhbSkgPT4ge1xuICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgLy8gTmVpdGhlciBsb2NhbFN0cmVhbSBvciBtaWNyb3Bob25lIGRldmljZSBpcyBhbGxvd2VkL2FibGUgdG8gY2FwdHVyZSBtZWRpYVxuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayhlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubG9jYWxTdHJlYW0uZWUuZW1pdEV2ZW50KCdhY2Nlc3MtZGVuaWVkLWJ5LXB1Ymxpc2hlcicpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsU3RyZWFtLnNldFZpZGVvRWxlbWVudCh0aGlzLmNhbWVyYVJlYWR5KGxvY2FsU3RyZWFtISwgcGFyZW50SWQpKTtcbiAgICAgICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2sodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpcy5sb2NhbFN0cmVhbTtcbiAgICB9XG5cbiAgICBpbml0UHVibGlzaGVyU2NyZWVuKHBhcmVudElkOiBzdHJpbmcsIG5ld1N0cmVhbTogYm9vbGVhbiwgY2FsbGJhY2s/KTogU3RyZWFtIHtcblxuICAgICAgICBpZiAobmV3U3RyZWFtKSB7XG4gICAgICAgICAgICB0aGlzLmxvY2FsU3RyZWFtID0gbmV3IFN0cmVhbSh0aGlzLCB0cnVlLCB0aGlzLnNlc3Npb24sICdzY3JlZW4tb3B0aW9ucycpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5sb2NhbFN0cmVhbS5hZGRPbmNlRXZlbnRMaXN0ZW5lcignY2FuLXJlcXVlc3Qtc2NyZWVuJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5sb2NhbFN0cmVhbS5yZXF1ZXN0Q2FtZXJhQWNjZXNzKChlcnJvciwgbG9jYWxTdHJlYW0pID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2NhbFN0cmVhbS5lZS5lbWl0RXZlbnQoJ2FjY2Vzcy1kZW5pZWQtYnktcHVibGlzaGVyJyk7XG4gICAgICAgICAgICAgICAgICAgIGxldCBlcnJvck5hbWU6IE9wZW5WaWR1RXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVEO1xuICAgICAgICAgICAgICAgICAgICBsZXQgZXJyb3JNZXNzYWdlID0gJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCc7XG4gICAgICAgICAgICAgICAgICAgIGxldCBlID0gbmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvY2FsU3RyZWFtLnNldFZpZGVvRWxlbWVudCh0aGlzLmNhbWVyYVJlYWR5KGxvY2FsU3RyZWFtISwgcGFyZW50SWQpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMubG9jYWxTdHJlYW0uZ2V0U2VuZEF1ZGlvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSB1c2VyIHdhbnRzIHRvIHNlbmQgYXVkaW8gd2l0aCB0aGUgc2NyZWVuIGNhcHR1cmluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoeyBhdWRpbzogdHJ1ZSwgdmlkZW86IGZhbHNlIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4odXNlclN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9jYWxTdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5hZGRUcmFjayh1c2VyU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE11dGUgYXVkaW8gaWYgJ2FjdGl2ZUF1ZGlvJyBwcm9wZXJ0eSBpcyBmYWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodXNlclN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZXJTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXS5lbmFibGVkID0gdGhpcy5sb2NhbFN0cmVhbS5vdXRib3VuZE9wdGlvbnMuYWN0aXZlQXVkaW87XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvY2FsU3RyZWFtLmlzU2NyZWVuUmVxdWVzdGVkUmVhZHkgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvY2FsU3RyZWFtLmVlLmVtaXRFdmVudCgnc2NyZWVuLXJlYWR5Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2sodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2NhbFN0cmVhbS5lZS5lbWl0RXZlbnQoJ2FjY2Vzcy1kZW5pZWQtYnktcHVibGlzaGVyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBhY2Nlc3NpbmcgdGhlIG1pY3JvcGhvbmVcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlcnJvck5hbWU6IE9wZW5WaWR1RXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuTUlDUk9QSE9ORV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvY2FsU3RyZWFtLmlzU2NyZWVuUmVxdWVzdGVkUmVhZHkgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2NhbFN0cmVhbS5lZS5lbWl0RXZlbnQoJ3NjcmVlbi1yZWFkeScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2sodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxTdHJlYW07XG4gICAgfVxuXG4gICAgY2FtZXJhUmVhZHkobG9jYWxTdHJlYW06IFN0cmVhbSwgcGFyZW50SWQ6IHN0cmluZykge1xuICAgICAgICB0aGlzLmxvY2FsU3RyZWFtID0gbG9jYWxTdHJlYW07XG4gICAgICAgIGxldCB2aWRlb0VsZW1lbnQgPSB0aGlzLmxvY2FsU3RyZWFtLnBsYXlPbmx5VmlkZW8ocGFyZW50SWQsIG51bGwpO1xuICAgICAgICB0aGlzLmxvY2FsU3RyZWFtLmVtaXRTdHJlYW1SZWFkeUV2ZW50KCk7XG4gICAgICAgIHJldHVybiB2aWRlb0VsZW1lbnQ7XG4gICAgfVxuXG4gICAgZ2V0TG9jYWxTdHJlYW0oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxvY2FsU3RyZWFtO1xuICAgIH1cblxuICAgIC8qIE5FVyBNRVRIT0RTICovXG5cbiAgICBnZXRXc1VyaSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud3NVcmk7XG4gICAgfVxuXG4gICAgc2V0V3NVcmkod3NVcmk6IHN0cmluZykge1xuICAgICAgICB0aGlzLndzVXJpID0gd3NVcmk7XG4gICAgfVxuXG4gICAgZ2V0U2VjcmV0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zZWNyZXQ7XG4gICAgfVxuXG4gICAgc2V0U2VjcmV0KHNlY3JldDogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc2VjcmV0ID0gc2VjcmV0O1xuICAgIH1cblxuICAgIGdldFJlY29yZGVyKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yZWNvcmRlcjtcbiAgICB9XG5cbiAgICBzZXRSZWNvcmRlcihyZWNvcmRlcjogYm9vbGVhbikge1xuICAgICAgICB0aGlzLnJlY29yZGVyID0gcmVjb3JkZXI7XG4gICAgfVxuXG4gICAgZ2V0T3BlblZpZHVTZXJ2ZXJVUkwoKSB7XG4gICAgICAgIHJldHVybiAnaHR0cHM6Ly8nICsgdGhpcy53c1VyaS5zcGxpdChcIndzczovL1wiKVsxXS5zcGxpdChcIi9yb29tXCIpWzBdO1xuICAgIH1cblxuICAgIGdldFJvb20oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNlc3Npb247XG4gICAgfVxuXG4gICAgY29ubmVjdChjYWxsYmFjazogQ2FsbGJhY2s8T3BlblZpZHVJbnRlcm5hbD4pOiB2b2lkIHtcblxuICAgICAgICB0aGlzLmNhbGxiYWNrID0gY2FsbGJhY2s7XG5cbiAgICAgICAgdGhpcy5pbml0SnNvblJwY0NsaWVudCh0aGlzLndzVXJpKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRKc29uUnBjQ2xpZW50KHdzVXJpOiBzdHJpbmcpOiB2b2lkIHtcblxuICAgICAgICBsZXQgY29uZmlnID0ge1xuICAgICAgICAgICAgaGVhcnRiZWF0OiAzMDAwLFxuICAgICAgICAgICAgc2VuZENsb3NlTWVzc2FnZTogZmFsc2UsXG4gICAgICAgICAgICB3czoge1xuICAgICAgICAgICAgICAgIHVyaTogd3NVcmksXG4gICAgICAgICAgICAgICAgdXNlU29ja0pTOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBvbmNvbm5lY3RlZDogdGhpcy5jb25uZWN0Q2FsbGJhY2suYmluZCh0aGlzKSxcbiAgICAgICAgICAgICAgICBvbmRpc2Nvbm5lY3Q6IHRoaXMuZGlzY29ubmVjdENhbGxiYWNrLmJpbmQodGhpcyksXG4gICAgICAgICAgICAgICAgb25yZWNvbm5lY3Rpbmc6IHRoaXMucmVjb25uZWN0aW5nQ2FsbGJhY2suYmluZCh0aGlzKSxcbiAgICAgICAgICAgICAgICBvbnJlY29ubmVjdGVkOiB0aGlzLnJlY29ubmVjdGVkQ2FsbGJhY2suYmluZCh0aGlzKVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJwYzoge1xuICAgICAgICAgICAgICAgIHJlcXVlc3RUaW1lb3V0OiAxNTAwMCxcbiAgICAgICAgICAgICAgICAvL25vdGlmaWNhdGlvbnNcbiAgICAgICAgICAgICAgICBwYXJ0aWNpcGFudEpvaW5lZDogdGhpcy5vblBhcnRpY2lwYW50Sm9pbmVkLmJpbmQodGhpcyksXG4gICAgICAgICAgICAgICAgcGFydGljaXBhbnRQdWJsaXNoZWQ6IHRoaXMub25QYXJ0aWNpcGFudFB1Ymxpc2hlZC5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgICAgIHBhcnRpY2lwYW50VW5wdWJsaXNoZWQ6IHRoaXMub25QYXJ0aWNpcGFudFVucHVibGlzaGVkLmJpbmQodGhpcyksXG4gICAgICAgICAgICAgICAgcGFydGljaXBhbnRMZWZ0OiB0aGlzLm9uUGFydGljaXBhbnRMZWZ0LmJpbmQodGhpcyksXG4gICAgICAgICAgICAgICAgcGFydGljaXBhbnRFdmljdGVkOiB0aGlzLm9uUGFydGljaXBhbnRFdmljdGVkLmJpbmQodGhpcyksXG4gICAgICAgICAgICAgICAgc2VuZE1lc3NhZ2U6IHRoaXMub25OZXdNZXNzYWdlLmJpbmQodGhpcyksXG4gICAgICAgICAgICAgICAgaWNlQ2FuZGlkYXRlOiB0aGlzLmljZUNhbmRpZGF0ZUV2ZW50LmJpbmQodGhpcyksXG4gICAgICAgICAgICAgICAgbWVkaWFFcnJvcjogdGhpcy5vbk1lZGlhRXJyb3IuYmluZCh0aGlzKSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLmpzb25ScGNDbGllbnQgPSBuZXcgUnBjQnVpbGRlci5jbGllbnRzLkpzb25ScGNDbGllbnQoY29uZmlnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNvbm5lY3RDYWxsYmFjayhlcnJvcikge1xuICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgIHRoaXMuY2FsbGJhY2soZXJyb3IpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5jYWxsYmFjayhudWxsKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgaXNSb29tQXZhaWxhYmxlKCkge1xuICAgICAgICBpZiAodGhpcy5zZXNzaW9uICE9PSB1bmRlZmluZWQgJiYgdGhpcy5zZXNzaW9uIGluc3RhbmNlb2YgU2Vzc2lvbkludGVybmFsKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignU2Vzc2lvbiBpbnN0YW5jZSBub3QgZm91bmQnKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZGlzY29ubmVjdENhbGxiYWNrKCkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QnKTtcbiAgICAgICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vbkxvc3RDb25uZWN0aW9uKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhbGVydCgnQ29ubmVjdGlvbiBlcnJvci4gUGxlYXNlIHJlbG9hZCBwYWdlLicpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZWNvbm5lY3RpbmdDYWxsYmFjaygpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgY29ubmVjdGlvbiBsb3N0IChyZWNvbm5lY3RpbmcpJyk7XG4gICAgICAgIGlmICh0aGlzLmlzUm9vbUF2YWlsYWJsZSgpKSB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24ub25Mb3N0Q29ubmVjdGlvbigpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgcmVjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgcmVjb25uZWN0ZWQnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uUGFydGljaXBhbnRKb2luZWQocGFyYW1zKSB7XG4gICAgICAgIGlmICh0aGlzLmlzUm9vbUF2YWlsYWJsZSgpKSB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudEpvaW5lZChwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvblBhcnRpY2lwYW50UHVibGlzaGVkKHBhcmFtcykge1xuICAgICAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRQdWJsaXNoZWQocGFyYW1zKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgb25QYXJ0aWNpcGFudFVucHVibGlzaGVkKHBhcmFtcykge1xuICAgICAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRVbnB1Ymxpc2hlZChwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvblBhcnRpY2lwYW50TGVmdChwYXJhbXMpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50TGVmdChwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvblBhcnRpY2lwYW50RXZpY3RlZChwYXJhbXMpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50RXZpY3RlZChwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvbk5ld01lc3NhZ2UocGFyYW1zKSB7XG4gICAgICAgIGlmICh0aGlzLmlzUm9vbUF2YWlsYWJsZSgpKSB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24ub25OZXdNZXNzYWdlKHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGljZUNhbmRpZGF0ZUV2ZW50KHBhcmFtcykge1xuICAgICAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLnJlY3ZJY2VDYW5kaWRhdGUocGFyYW1zKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgb25Sb29tQ2xvc2VkKHBhcmFtcykge1xuICAgICAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9uUm9vbUNsb3NlZChwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvbk1lZGlhRXJyb3IocGFyYW1zKSB7XG4gICAgICAgIGlmICh0aGlzLmlzUm9vbUF2YWlsYWJsZSgpKSB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24ub25NZWRpYUVycm9yKHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIHNldFJwY1BhcmFtcyhwYXJhbXM6IGFueSkge1xuICAgICAgICB0aGlzLnJwY1BhcmFtcyA9IHBhcmFtcztcbiAgICB9XG5cbiAgICBzZW5kUmVxdWVzdChtZXRob2QsIHBhcmFtcywgY2FsbGJhY2s/KSB7XG5cbiAgICAgICAgaWYgKHBhcmFtcyAmJiBwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgICAgICAgY2FsbGJhY2sgPSBwYXJhbXM7XG4gICAgICAgICAgICBwYXJhbXMgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG5cbiAgICAgICAgaWYgKHRoaXMucnBjUGFyYW1zICYmIHRoaXMucnBjUGFyYW1zICE9PSBudWxsICYmIHRoaXMucnBjUGFyYW1zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGZvciAobGV0IGluZGV4IGluIHRoaXMucnBjUGFyYW1zKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucnBjUGFyYW1zLmhhc093blByb3BlcnR5KGluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJhbXNbaW5kZXhdID0gdGhpcy5ycGNQYXJhbXNbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdSUEMgcGFyYW0gYWRkZWQgdG8gcmVxdWVzdCB7JyArIGluZGV4ICsgJzogJyArIHRoaXMucnBjUGFyYW1zW2luZGV4XSArICd9Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyByZXF1ZXN0OiB7bWV0aG9kOlwiJyArIG1ldGhvZCArICdcIiwgcGFyYW1zOiAnICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSArICd9Jyk7XG5cbiAgICAgICAgdGhpcy5qc29uUnBjQ2xpZW50LnNlbmQobWV0aG9kLCBwYXJhbXMsIGNhbGxiYWNrKTtcbiAgICB9XG5cbiAgICBjbG9zZShmb3JjZWQpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5sZWF2ZShmb3JjZWQsIHRoaXMuanNvblJwY0NsaWVudCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgZGlzY29ubmVjdFBhcnRpY2lwYW50KHN0cmVhbSkge1xuICAgICAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmRpc2Nvbm5lY3Qoc3RyZWFtKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vQ0hBVFxuICAgIHNlbmRNZXNzYWdlKG1lc3NhZ2UpIHtcbiAgICAgICAgdGhpcy5zZW5kUmVxdWVzdCgnc2VuZE1lc3NhZ2UnLCB7XG4gICAgICAgICAgICBtZXNzYWdlOiBtZXNzYWdlXG4gICAgICAgIH0sIGZ1bmN0aW9uIChlcnJvciwgcmVzcG9uc2UpIHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKGNhbWVyYU9wdGlvbnM6IGFueSkge1xuICAgICAgICBsZXQgbWVkaWFDb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgIGF1ZGlvOiBjYW1lcmFPcHRpb25zLmF1ZGlvLFxuICAgICAgICAgICAgdmlkZW86IHt9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFjYW1lcmFPcHRpb25zLnZpZGVvKSB7XG4gICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvID0gZmFsc2VcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxldCB3LCBoO1xuICAgICAgICAgICAgc3dpdGNoIChjYW1lcmFPcHRpb25zLnF1YWxpdHkpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdMT1cnOlxuICAgICAgICAgICAgICAgICAgICB3ID0gMzIwO1xuICAgICAgICAgICAgICAgICAgICBoID0gMjQwO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdNRURJVU0nOlxuICAgICAgICAgICAgICAgICAgICB3ID0gNjQwO1xuICAgICAgICAgICAgICAgICAgICBoID0gNDgwO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdISUdIJzpcbiAgICAgICAgICAgICAgICAgICAgdyA9IDEyODA7XG4gICAgICAgICAgICAgICAgICAgIGggPSA3MjA7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHcgPSA2NDA7XG4gICAgICAgICAgICAgICAgICAgIGggPSA0ODA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvWyd3aWR0aCddID0geyBleGFjdDogdyB9O1xuICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50cy52aWRlb1snaGVpZ2h0J10gPSB7IGV4YWN0OiBoIH07XG4gICAgICAgICAgICAvL21lZGlhQ29uc3RyYWludHMudmlkZW9bJ2ZyYW1lUmF0ZSddID0geyBpZGVhbDogTnVtYmVyKCg8SFRNTElucHV0RWxlbWVudD5kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZnJhbWVSYXRlJykpLnZhbHVlKSB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtZWRpYUNvbnN0cmFpbnRzO1xuICAgIH1cblxufVxuIiwiaW1wb3J0IHsgU3RyZWFtLCBTdHJlYW1PcHRpb25zU2VydmVyIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgT3BlblZpZHVJbnRlcm5hbCB9IGZyb20gJy4vT3BlblZpZHVJbnRlcm5hbCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uLCBDb25uZWN0aW9uT3B0aW9ucyB9IGZyb20gJy4vQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdS9QdWJsaXNoZXInO1xuXG5pbXBvcnQgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnd29sZnk4Ny1ldmVudGVtaXR0ZXInKTtcblxudHlwZSBPYmpNYXA8VD4gPSB7IFtzOiBzdHJpbmddOiBUOyB9XG5cbmNvbnN0IFNFQ1JFVF9QQVJBTSA9ICc/c2VjcmV0PSc7XG5jb25zdCBSRUNPUkRFUl9QQVJBTSA9ICcmcmVjb3JkZXI9JztcblxuZXhwb3J0IGludGVyZmFjZSBTZXNzaW9uT3B0aW9ucyB7XG4gICAgc2Vzc2lvbklkOiBzdHJpbmc7XG4gICAgcGFydGljaXBhbnRJZDogc3RyaW5nO1xuICAgIG1ldGFkYXRhOiBzdHJpbmc7XG4gICAgc3Vic2NyaWJlVG9TdHJlYW1zPzogYm9vbGVhbjtcbiAgICB1cGRhdGVTcGVha2VySW50ZXJ2YWw/OiBudW1iZXI7XG4gICAgdGhyZXNob2xkU3BlYWtlcj86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTaWduYWxPcHRpb25zIHtcbiAgICB0eXBlPzogc3RyaW5nO1xuICAgIHRvPzogQ29ubmVjdGlvbltdO1xuICAgIGRhdGE/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjbGFzcyBTZXNzaW9uSW50ZXJuYWwge1xuXG4gICAgcHJpdmF0ZSBpZDogc3RyaW5nO1xuICAgIHByaXZhdGUgc2Vzc2lvbklkOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICBwcml2YXRlIHJlbW90ZVN0cmVhbXM6IE9iak1hcDxTdHJlYW0+ID0ge307XG4gICAgcHJpdmF0ZSBwYXJ0aWNpcGFudHMgPSB7fTtcbiAgICBwcml2YXRlIHB1Ymxpc2hlcnNTcGVha2luZzogQ29ubmVjdGlvbltdID0gW107XG4gICAgcHJpdmF0ZSBjb25uZWN0ZWQgPSBmYWxzZTtcbiAgICBwdWJsaWMgbG9jYWxQYXJ0aWNpcGFudDogQ29ubmVjdGlvbjtcbiAgICBwcml2YXRlIHN1YnNjcmliZVRvU3RyZWFtczogYm9vbGVhbjtcbiAgICBwcml2YXRlIHVwZGF0ZVNwZWFrZXJJbnRlcnZhbDogbnVtYmVyO1xuICAgIHB1YmxpYyB0aHJlc2hvbGRTcGVha2VyOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBvcHRpb25zOiBTZXNzaW9uT3B0aW9ucztcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgb3BlblZpZHU6IE9wZW5WaWR1SW50ZXJuYWwsIHNlc3Npb25JZDogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc2Vzc2lvbklkID0gdGhpcy5nZXRVcmxXaXRob3V0U2VjcmV0KHNlc3Npb25JZCk7XG4gICAgICAgIHRoaXMubG9jYWxQYXJ0aWNpcGFudCA9IG5ldyBDb25uZWN0aW9uKHRoaXMub3BlblZpZHUsIHRydWUsIHRoaXMpO1xuICAgICAgICBpZiAoIXRoaXMub3BlblZpZHUuZ2V0V3NVcmkoKSAmJiAhIXNlc3Npb25JZCkge1xuICAgICAgICAgICAgdGhpcy5wcm9jZXNzT3BlblZpZHVVcmwoc2Vzc2lvbklkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgcHJvY2Vzc09wZW5WaWR1VXJsKHVybDogc3RyaW5nKSB7XG4gICAgICAgIGxldCBzZWNyZXQgPSB0aGlzLmdldFNlY3JldEZyb21VcmwodXJsKTtcbiAgICAgICAgbGV0IHJlY29yZGVyID0gdGhpcy5nZXRSZWNvcmRlckZyb21VcmwodXJsKTtcbiAgICAgICAgaWYgKCEoc2VjcmV0ID09IG51bGwpKSB7XG4gICAgICAgICAgICB0aGlzLm9wZW5WaWR1LnNldFNlY3JldChzZWNyZXQpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghKHJlY29yZGVyID09IG51bGwpKSB7XG4gICAgICAgICAgICB0aGlzLm9wZW5WaWR1LnNldFJlY29yZGVyKHJlY29yZGVyKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9wZW5WaWR1LnNldFdzVXJpKHRoaXMuZ2V0RmluYWxVcmwodXJsKSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRTZWNyZXRGcm9tVXJsKHVybDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgbGV0IHNlY3JldCA9ICcnO1xuICAgICAgICBpZiAodXJsLmluZGV4T2YoU0VDUkVUX1BBUkFNKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIGxldCBlbmRPZlNlY3JldCA9IHVybC5sYXN0SW5kZXhPZihSRUNPUkRFUl9QQVJBTSk7XG4gICAgICAgICAgICBpZiAoZW5kT2ZTZWNyZXQgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgc2VjcmV0ID0gdXJsLnN1YnN0cmluZyh1cmwubGFzdEluZGV4T2YoU0VDUkVUX1BBUkFNKSArIFNFQ1JFVF9QQVJBTS5sZW5ndGgsIGVuZE9mU2VjcmV0KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VjcmV0ID0gdXJsLnN1YnN0cmluZyh1cmwubGFzdEluZGV4T2YoU0VDUkVUX1BBUkFNKSArIFNFQ1JFVF9QQVJBTS5sZW5ndGgsIHVybC5sZW5ndGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzZWNyZXQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSZWNvcmRlckZyb21VcmwodXJsOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAgICAgbGV0IHJlY29yZGVyID0gJyc7XG4gICAgICAgIGlmICh1cmwuaW5kZXhPZihSRUNPUkRFUl9QQVJBTSkgIT09IC0xKSB7XG4gICAgICAgICAgICByZWNvcmRlciA9IHVybC5zdWJzdHJpbmcodXJsLmxhc3RJbmRleE9mKFJFQ09SREVSX1BBUkFNKSArIFJFQ09SREVSX1BBUkFNLmxlbmd0aCwgdXJsLmxlbmd0aCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBCb29sZWFuKHJlY29yZGVyKS52YWx1ZU9mKCk7O1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0VXJsV2l0aG91dFNlY3JldCh1cmw6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIGlmICghdXJsKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdzZXNzaW9uSWQgaXMgbm90IGRlZmluZWQnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodXJsLmluZGV4T2YoU0VDUkVUX1BBUkFNKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHVybCA9IHVybC5zdWJzdHJpbmcoMCwgdXJsLmxhc3RJbmRleE9mKFNFQ1JFVF9QQVJBTSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1cmw7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRGaW5hbFVybCh1cmw6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIHVybCA9IHRoaXMuZ2V0VXJsV2l0aG91dFNlY3JldCh1cmwpLnN1YnN0cmluZygwLCB1cmwubGFzdEluZGV4T2YoJy8nKSkgKyAnL3Jvb20nO1xuICAgICAgICBpZiAodXJsLmluZGV4T2YoXCIubmdyb2suaW9cIikgIT09IC0xKSB7XG4gICAgICAgICAgICAvLyBPcGVuVmlkdSBzZXJ2ZXIgVVJMIHJlZmVyZXMgdG8gYSBuZ3JvayBJUDogc2VjdXJlIHdzcyBwcm90b2NvbCBhbmQgZGVsZXRlIHBvcnQgb2YgVVJMXG4gICAgICAgICAgICB1cmwgPSB1cmwucmVwbGFjZShcIndzOi8vXCIsIFwid3NzOi8vXCIpO1xuICAgICAgICAgICAgbGV0IHJlZ2V4ID0gL1xcLm5ncm9rXFwuaW86XFxkKy87XG4gICAgICAgICAgICB1cmwgPSB1cmwucmVwbGFjZShyZWdleCwgXCIubmdyb2suaW9cIik7XG4gICAgICAgIH0gZWxzZSBpZiAoKHVybC5pbmRleE9mKFwibG9jYWxob3N0XCIpICE9PSAtMSkgfHwgKHVybC5pbmRleE9mKFwiMTI3LjAuMC4xXCIpICE9IC0xKSkge1xuICAgICAgICAgICAgLy8gT3BlblZpZHUgc2VydmVyIFVSTCByZWZlcmVzIHRvIGxvY2FsaG9zdCBJUFxuXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVybDtcbiAgICB9XG5cblxuXG4gICAgLyogTkVXIE1FVEhPRFMgKi9cbiAgICBjb25uZWN0KHRva2VuLCBjYWxsYmFjaykge1xuXG4gICAgICAgIHRoaXMub3BlblZpZHUuY29ubmVjdCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCdFUlJPUiBDT05ORUNUSU5HIFRPIE9QRU5WSURVJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcblxuICAgICAgICAgICAgICAgIGlmICghdG9rZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgdG9rZW4gPSB0aGlzLnJhbmRvbVRva2VuKCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbGV0IGpvaW5QYXJhbXMgPSB7XG4gICAgICAgICAgICAgICAgICAgIHRva2VuOiB0b2tlbixcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbjogdGhpcy5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiB0aGlzLm9wdGlvbnMubWV0YWRhdGEsXG4gICAgICAgICAgICAgICAgICAgIHNlY3JldDogdGhpcy5vcGVuVmlkdS5nZXRTZWNyZXQoKSxcbiAgICAgICAgICAgICAgICAgICAgcmVjb3JkZXI6IHRoaXMub3BlblZpZHUuZ2V0UmVjb3JkZXIoKSxcbiAgICAgICAgICAgICAgICAgICAgZGF0YUNoYW5uZWxzOiBmYWxzZVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmxvY2FsUGFydGljaXBhbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5rZXlzKHRoaXMubG9jYWxQYXJ0aWNpcGFudC5nZXRTdHJlYW1zKCkpLnNvbWUoc3RyZWFtSWQgPT5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc1tzdHJlYW1JZF0uaXNEYXRhQ2hhbm5lbEVuYWJsZWQoKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGpvaW5QYXJhbXMuZGF0YUNoYW5uZWxzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMub3BlblZpZHUuc2VuZFJlcXVlc3QoJ2pvaW5Sb29tJywgam9pblBhcmFtcywgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3RlZCA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBleFBhcnRpY2lwYW50czogQ29ubmVjdGlvbk9wdGlvbnNbXSA9IHJlc3BvbnNlLnZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJTVBPUlRBTlQ6IFVwZGF0ZSBjb25uZWN0aW9uSWQgd2l0aCB2YWx1ZSBzZW5kIGJ5IHNlcnZlclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2NhbFBhcnRpY2lwYW50LmNvbm5lY3Rpb25JZCA9IHJlc3BvbnNlLmlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYXJ0aWNpcGFudHNbcmVzcG9uc2UuaWRdID0gdGhpcy5sb2NhbFBhcnRpY2lwYW50O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgcm9vbUV2ZW50ID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcnRpY2lwYW50czogbmV3IEFycmF5PENvbm5lY3Rpb24+KCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtczogbmV3IEFycmF5PFN0cmVhbT4oKVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgbGVuZ3RoID0gZXhQYXJ0aWNpcGFudHMubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLm9wZW5WaWR1LCBmYWxzZSwgdGhpcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhQYXJ0aWNpcGFudHNbaV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24uY3JlYXRpb25UaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBhcnRpY2lwYW50c1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF0gPSBjb25uZWN0aW9uO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vbUV2ZW50LnBhcnRpY2lwYW50cy5wdXNoKGNvbm5lY3Rpb24pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHN0cmVhbXMgPSBjb25uZWN0aW9uLmdldFN0cmVhbXMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBrZXkgaW4gc3RyZWFtcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb29tRXZlbnQuc3RyZWFtcy5wdXNoKHN0cmVhbXNba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN1YnNjcmliZVRvU3RyZWFtcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtc1trZXldLnN1YnNjcmliZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBVcGRhdGUgbG9jYWwgQ29ubmVjdGlvbiBvYmplY3QgcHJvcGVydGllcyB3aXRoIHZhbHVlcyByZXR1cm5lZCBieSBzZXJ2ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9jYWxQYXJ0aWNpcGFudC5kYXRhID0gcmVzcG9uc2UubWV0YWRhdGE7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvY2FsUGFydGljaXBhbnQuY3JlYXRpb25UaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVwZGF0ZXMgdGhlIHZhbHVlIG9mIHByb3BlcnR5ICdjb25uZWN0aW9uJyBpbiBTZXNzaW9uIG9iamVjdFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3VwZGF0ZS1jb25uZWN0aW9uLW9iamVjdCcsIFt7IGNvbm5lY3Rpb246IHRoaXMubG9jYWxQYXJ0aWNpcGFudCB9XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBPd24gY29ubmVjdGlvbiBjcmVhdGVkIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkNyZWF0ZWQnLCBbeyBjb25uZWN0aW9uOiB0aGlzLmxvY2FsUGFydGljaXBhbnQgfV0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmUgY29ubmVjdGlvbiBjcmVhdGVkIGV2ZW50IGZvciBlYWNoIGV4aXN0aW5nIGNvbm5lY3Rpb24gaW4gdGhlIHNlc3Npb25cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IHBhcnQgb2Ygcm9vbUV2ZW50LnBhcnRpY2lwYW50cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFt7IGNvbm5lY3Rpb246IHBhcnQgfV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAvL2lmICh0aGlzLnN1YnNjcmliZVRvU3RyZWFtcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgc3RyZWFtIG9mIHJvb21FdmVudC5zdHJlYW1zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbeyBzdHJlYW0gfV0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3RvcmUgdGhlIHJlbW90ZSBzdHJlYW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVN0cmVhbXNbc3RyZWFtLnN0cmVhbUlkXSA9IHN0cmVhbTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2sodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyogTkVXIE1FVEhPRFMgKi9cblxuXG5cblxuXG4gICAgY29uZmlndXJlKG9wdGlvbnM6IFNlc3Npb25PcHRpb25zKSB7XG4gICAgICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgICAgIHRoaXMuaWQgPSBvcHRpb25zLnNlc3Npb25JZDtcbiAgICAgICAgdGhpcy5zdWJzY3JpYmVUb1N0cmVhbXMgPSBvcHRpb25zLnN1YnNjcmliZVRvU3RyZWFtcyA9PSBudWxsID8gdHJ1ZSA6IG9wdGlvbnMuc3Vic2NyaWJlVG9TdHJlYW1zO1xuICAgICAgICB0aGlzLnVwZGF0ZVNwZWFrZXJJbnRlcnZhbCA9IG9wdGlvbnMudXBkYXRlU3BlYWtlckludGVydmFsIHx8IDE1MDA7XG4gICAgICAgIHRoaXMudGhyZXNob2xkU3BlYWtlciA9IG9wdGlvbnMudGhyZXNob2xkU3BlYWtlciB8fCAtNTA7XG4gICAgICAgIHRoaXMuYWN0aXZhdGVVcGRhdGVNYWluU3BlYWtlcigpO1xuXG4gICAgICAgIGlmICghdGhpcy5vcGVuVmlkdS5nZXRXc1VyaSgpKSB7XG4gICAgICAgICAgICB0aGlzLnByb2Nlc3NPcGVuVmlkdVVybChvcHRpb25zLnNlc3Npb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBnZXRJZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaWQ7XG4gICAgfVxuXG4gICAgZ2V0U2Vzc2lvbklkKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zZXNzaW9uSWQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhY3RpdmF0ZVVwZGF0ZU1haW5TcGVha2VyKCkge1xuXG4gICAgICAgIC8qc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucHVibGlzaGVyc1NwZWFraW5nLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFt7XG4gICAgICAgICAgICAgICAgICAgIHBhcnRpY2lwYW50SWQ6IHRoaXMucHVibGlzaGVyc1NwZWFraW5nW3RoaXMucHVibGlzaGVyc1NwZWFraW5nLmxlbmd0aCAtIDFdXG4gICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB0aGlzLnVwZGF0ZVNwZWFrZXJJbnRlcnZhbCk7Ki9cbiAgICB9XG5cbiAgICBnZXRMb2NhbFBhcnRpY2lwYW50KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sb2NhbFBhcnRpY2lwYW50O1xuICAgIH1cblxuICAgIGFkZEV2ZW50TGlzdGVuZXIoZXZlbnROYW1lLCBsaXN0ZW5lcikge1xuICAgICAgICB0aGlzLmVlLm9uKGV2ZW50TmFtZSwgbGlzdGVuZXIpO1xuICAgIH1cblxuICAgIGFkZE9uY2VFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgbGlzdGVuZXIpIHtcbiAgICAgICAgdGhpcy5lZS5vbmNlKGV2ZW50TmFtZSwgbGlzdGVuZXIpO1xuICAgIH1cblxuICAgIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSwgbGlzdGVuZXIpIHtcbiAgICAgICAgdGhpcy5lZS5vZmYoZXZlbnROYW1lLCBsaXN0ZW5lcik7XG4gICAgfVxuXG4gICAgcmVtb3ZlRXZlbnQoZXZlbnROYW1lKSB7XG4gICAgICAgIHRoaXMuZWUucmVtb3ZlRXZlbnQoZXZlbnROYW1lKTtcbiAgICB9XG5cbiAgICBlbWl0RXZlbnQoZXZlbnROYW1lLCBldmVudHNBcnJheSkge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudChldmVudE5hbWUsIGV2ZW50c0FycmF5KTtcbiAgICB9XG5cblxuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSkge1xuICAgICAgICBzdHJlYW0uc3Vic2NyaWJlKCk7XG4gICAgfVxuXG4gICAgdW5zdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0pIHtcbiAgICAgICAgY29uc29sZS5pbmZvKFwiVW5zdWJzY3JpYmluZyBmcm9tIFwiICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgdGhpcy5vcGVuVmlkdS5zZW5kUmVxdWVzdCgndW5zdWJzY3JpYmVGcm9tVmlkZW8nLCB7XG4gICAgICAgICAgICBzZW5kZXI6IHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZFxuICAgICAgICB9LFxuICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3IgdW5zdWJzY3JpYmluZyBmcm9tIFN1YnNjcmliZXJcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIlVuc3Vic2NyaWJlZCBjb3JyZWN0bHkgZnJvbSBcIiArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN0cmVhbS5kaXNwb3NlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBvblBhcnRpY2lwYW50UHVibGlzaGVkKHJlc3BvbnNlOiBDb25uZWN0aW9uT3B0aW9ucykge1xuXG4gICAgICAgIC8vIEdldCB0aGUgZXhpc3RpbmcgQ29ubmVjdGlvbiBjcmVhdGVkIG9uICdvblBhcnRpY2lwYW50Sm9pbmVkJyBmb3JcbiAgICAgICAgLy8gZXhpc3RpbmcgcGFydGljaXBhbnRzIG9yIGNyZWF0ZSBhIG5ldyBvbmUgZm9yIG5ldyBwYXJ0aWNpcGFudHNcbiAgICAgICAgbGV0IGNvbm5lY3Rpb246IENvbm5lY3Rpb24gPSB0aGlzLnBhcnRpY2lwYW50c1tyZXNwb25zZS5pZF07XG4gICAgICAgIGlmIChjb25uZWN0aW9uICE9IG51bGwpIHtcbiAgICAgICAgICAgIC8vIFVwZGF0ZSBleGlzdGluZyBDb25uZWN0aW9uXG4gICAgICAgICAgICByZXNwb25zZS5tZXRhZGF0YSA9IGNvbm5lY3Rpb24uZGF0YTtcbiAgICAgICAgICAgIGNvbm5lY3Rpb24uc2V0T3B0aW9ucyhyZXNwb25zZSk7XG4gICAgICAgICAgICBjb25uZWN0aW9uLmluaXRSZW1vdGVTdHJlYW1zKHJlc3BvbnNlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIENyZWF0ZSBuZXcgQ29ubmVjdGlvblxuICAgICAgICAgICAgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMub3BlblZpZHUsIGZhbHNlLCB0aGlzLCByZXNwb25zZSk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcGlkID0gY29ubmVjdGlvbi5jb25uZWN0aW9uSWQ7XG4gICAgICAgIGlmICghKHBpZCBpbiB0aGlzLnBhcnRpY2lwYW50cykpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoXCJSZW1vdGUgQ29ubmVjdGlvbiBub3QgZm91bmQgaW4gY29ubmVjdGlvbnMgbGlzdCBieSBpdHMgaWQgW1wiICsgcGlkICsgXCJdXCIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZyhcIlJlbW90ZSBDb25uZWN0aW9uIGZvdW5kIGluIGNvbm5lY3Rpb25zIGxpc3QgYnkgaXRzIGlkIFtcIiArIHBpZCArIFwiXVwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucGFydGljaXBhbnRzW3BpZF0gPSBjb25uZWN0aW9uO1xuXG4gICAgICAgIGxldCBzdHJlYW1zID0gY29ubmVjdGlvbi5nZXRTdHJlYW1zKCk7XG4gICAgICAgIGZvciAobGV0IGtleSBpbiBzdHJlYW1zKSB7XG4gICAgICAgICAgICBsZXQgc3RyZWFtID0gc3RyZWFtc1trZXldO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMucmVtb3RlU3RyZWFtc1tzdHJlYW0uc3RyZWFtSWRdKSB7XG4gICAgICAgICAgICAgICAgLy8gQXZvaWQgcmFjZSBjb25kaXRpb24gYmV0d2VlbiBzdHJlYW0uc3Vic2NyaWJlKCkgaW4gXCJvblBhcnRpY2lwYW50UHVibGlzaGVkXCIgYW5kIGluIFwiam9pblJvb21cIiBycGMgY2FsbGJhY2tcbiAgICAgICAgICAgICAgICAvLyBUaGlzIGNvbmRpdGlvbiBpcyBmYWxzZSBpZiBvcGVudmlkdS1zZXJ2ZXIgc2VuZHMgXCJwYXJ0aWNpcGFudFB1Ymxpc2hlZFwiIGV2ZW50IHRvIGEgc3Vic2NyaWJlciBwYXJ0aWNpcGFudCB0aGF0IGhhc1xuICAgICAgICAgICAgICAgIC8vIGFscmVhZHkgc3Vic2NyaWJlZCB0byBjZXJ0YWluIHN0cmVhbSBpbiB0aGUgY2FsbGJhY2sgb2YgXCJqb2luUm9vbVwiIG1ldGhvZFxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3Vic2NyaWJlVG9TdHJlYW1zKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbS5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbeyBzdHJlYW0gfV0pO1xuXG4gICAgICAgICAgICAgICAgLy8gU3RvcmUgdGhlIHJlbW90ZSBzdHJlYW1cbiAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVN0cmVhbXNbc3RyZWFtLnN0cmVhbUlkXSA9IHN0cmVhbTtcblxuICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvblBhcnRpY2lwYW50VW5wdWJsaXNoZWQobXNnKSB7XG4gICAgICAgIGxldCBjb25uZWN0aW9uOiBDb25uZWN0aW9uID0gdGhpcy5wYXJ0aWNpcGFudHNbbXNnLm5hbWVdO1xuXG4gICAgICAgIGlmIChjb25uZWN0aW9uICE9PSB1bmRlZmluZWQpIHtcblxuICAgICAgICAgICAgbGV0IHN0cmVhbXMgPSBjb25uZWN0aW9uLmdldFN0cmVhbXMoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGtleSBpbiBzdHJlYW1zKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFt7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbTogc3RyZWFtc1trZXldLFxuICAgICAgICAgICAgICAgICAgICBwcmV2ZW50RGVmYXVsdDogKCkgPT4geyB0aGlzLmVlLnJlbW92ZUV2ZW50KCdzdHJlYW0tZGVzdHJveWVkLWRlZmF1bHQnKTsgfVxuICAgICAgICAgICAgICAgIH1dKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtLWRlc3Ryb3llZC1kZWZhdWx0JywgW3tcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtOiBzdHJlYW1zW2tleV1cbiAgICAgICAgICAgICAgICB9XSk7XG5cbiAgICAgICAgICAgICAgICAvLyBEZWxldGluZyB0aGUgcmVtb3RlIHN0cmVhbVxuICAgICAgICAgICAgICAgIGxldCBzdHJlYW1JZDogc3RyaW5nID0gc3RyZWFtc1trZXldLnN0cmVhbUlkO1xuICAgICAgICAgICAgICAgIGxldCBzdHJlYW06IFN0cmVhbSA9IHRoaXMucmVtb3RlU3RyZWFtc1tzdHJlYW1JZF07XG5cbiAgICAgICAgICAgICAgICBzdHJlYW0uZGlzcG9zZSgpO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnJlbW90ZVN0cmVhbXNbc3RyZWFtLnN0cmVhbUlkXTtcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLnJlbW92ZVN0cmVhbShzdHJlYW0uc3RyZWFtSWQpO1xuXG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJQYXJ0aWNpcGFudCBcIiArIG1zZy5uYW1lXG4gICAgICAgICAgICAgICAgKyBcIiB1bmtub3duLiBQYXJ0aWNpcGFudHM6IFwiXG4gICAgICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeSh0aGlzLnBhcnRpY2lwYW50cykpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgb25QYXJ0aWNpcGFudEpvaW5lZChyZXNwb25zZTogQ29ubmVjdGlvbk9wdGlvbnMpIHtcblxuICAgICAgICBsZXQgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMub3BlblZpZHUsIGZhbHNlLCB0aGlzLCByZXNwb25zZSk7XG4gICAgICAgIGNvbm5lY3Rpb24uY3JlYXRpb25UaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgICAgICAgbGV0IHBpZCA9IGNvbm5lY3Rpb24uY29ubmVjdGlvbklkO1xuICAgICAgICBpZiAoIShwaWQgaW4gdGhpcy5wYXJ0aWNpcGFudHMpKSB7XG4gICAgICAgICAgICB0aGlzLnBhcnRpY2lwYW50c1twaWRdID0gY29ubmVjdGlvbjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vdXNlIGV4aXN0aW5nIHNvIHRoYXQgd2UgZG9uJ3QgbG9zZSBzdHJlYW1zIGluZm9cbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkNvbm5lY3Rpb24gYWxyZWFkeSBleGlzdHMgaW4gY29ubmVjdGlvbnMgbGlzdCB3aXRoIFwiICtcbiAgICAgICAgICAgICAgICBcInRoZSBzYW1lIGNvbm5lY3Rpb25JZCwgb2xkOlwiLCB0aGlzLnBhcnRpY2lwYW50c1twaWRdLCBcIiwgam9pbmVkIG5vdzpcIiwgY29ubmVjdGlvbik7XG4gICAgICAgICAgICBjb25uZWN0aW9uID0gdGhpcy5wYXJ0aWNpcGFudHNbcGlkXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdwYXJ0aWNpcGFudC1qb2luZWQnLCBbe1xuICAgICAgICAgICAgY29ubmVjdGlvbjogY29ubmVjdGlvblxuICAgICAgICB9XSk7XG5cbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25DcmVhdGVkJywgW3tcbiAgICAgICAgICAgIGNvbm5lY3Rpb246IGNvbm5lY3Rpb25cbiAgICAgICAgfV0pO1xuXG4gICAgfVxuXG4gICAgb25QYXJ0aWNpcGFudExlZnQobXNnKSB7XG5cbiAgICAgICAgbGV0IGNvbm5lY3Rpb246IENvbm5lY3Rpb24gPSB0aGlzLnBhcnRpY2lwYW50c1ttc2cubmFtZV07XG5cbiAgICAgICAgaWYgKGNvbm5lY3Rpb24gIT09IHVuZGVmaW5lZCkge1xuXG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncGFydGljaXBhbnQtbGVmdCcsIFt7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbjogY29ubmVjdGlvblxuICAgICAgICAgICAgfV0pO1xuXG4gICAgICAgICAgICBsZXQgc3RyZWFtcyA9IGNvbm5lY3Rpb24uZ2V0U3RyZWFtcygpO1xuICAgICAgICAgICAgZm9yIChsZXQga2V5IGluIHN0cmVhbXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3tcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtOiBzdHJlYW1zW2tleV0sXG4gICAgICAgICAgICAgICAgICAgIHByZXZlbnREZWZhdWx0OiAoKSA9PiB7IHRoaXMuZWUucmVtb3ZlRXZlbnQoJ3N0cmVhbS1kZXN0cm95ZWQtZGVmYXVsdCcpOyB9XG4gICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW0tZGVzdHJveWVkLWRlZmF1bHQnLCBbe1xuICAgICAgICAgICAgICAgICAgICBzdHJlYW06IHN0cmVhbXNba2V5XVxuICAgICAgICAgICAgICAgIH1dKTtcblxuICAgICAgICAgICAgICAgIC8vIERlbGV0aW5nIHRoZSByZW1vdGUgc3RyZWFtXG4gICAgICAgICAgICAgICAgbGV0IHN0cmVhbUlkOiBzdHJpbmcgPSBzdHJlYW1zW2tleV0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc1tzdHJlYW1JZF07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbm5lY3Rpb24uZGlzcG9zZSgpO1xuXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5wYXJ0aWNpcGFudHNbbXNnLm5hbWVdO1xuXG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkRlc3Ryb3llZCcsIFt7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbjogY29ubmVjdGlvblxuICAgICAgICAgICAgfV0pO1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJQYXJ0aWNpcGFudCBcIiArIG1zZy5uYW1lXG4gICAgICAgICAgICAgICAgKyBcIiB1bmtub3duLiBQYXJ0aWNpcGFudHM6IFwiXG4gICAgICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeSh0aGlzLnBhcnRpY2lwYW50cykpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIG9uUGFydGljaXBhbnRFdmljdGVkKG1zZykge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncGFydGljaXBhbnQtZXZpY3RlZCcsIFt7XG4gICAgICAgICAgICBsb2NhbFBhcnRpY2lwYW50OiB0aGlzLmxvY2FsUGFydGljaXBhbnRcbiAgICAgICAgfV0pO1xuICAgIH07XG5cbiAgICBvbk5ld01lc3NhZ2UobXNnKSB7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKFwiTmV3IHNpZ25hbDogXCIgKyBKU09OLnN0cmluZ2lmeShtc2cpKTtcblxuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2lnbmFsJywgW3tcbiAgICAgICAgICAgIGRhdGE6IG1zZy5kYXRhLFxuICAgICAgICAgICAgZnJvbTogdGhpcy5wYXJ0aWNpcGFudHNbbXNnLmZyb21dLFxuICAgICAgICAgICAgdHlwZTogbXNnLnR5cGVcbiAgICAgICAgfV0pO1xuXG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzaWduYWw6JyArIG1zZy50eXBlLCBbe1xuICAgICAgICAgICAgZGF0YTogbXNnLmRhdGEsXG4gICAgICAgICAgICBmcm9tOiB0aGlzLnBhcnRpY2lwYW50c1ttc2cuZnJvbV0sXG4gICAgICAgICAgICB0eXBlOiBtc2cudHlwZVxuICAgICAgICB9XSk7XG5cbiAgICB9XG5cbiAgICByZWN2SWNlQ2FuZGlkYXRlKG1zZykge1xuXG4gICAgICAgIGxldCBjYW5kaWRhdGUgPSB7XG4gICAgICAgICAgICBjYW5kaWRhdGU6IG1zZy5jYW5kaWRhdGUsXG4gICAgICAgICAgICBzZHBNaWQ6IG1zZy5zZHBNaWQsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBtc2cuc2RwTUxpbmVJbmRleFxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGNvbm5lY3Rpb24gPSB0aGlzLnBhcnRpY2lwYW50c1ttc2cuZW5kcG9pbnROYW1lXTtcbiAgICAgICAgaWYgKCFjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiUGFydGljaXBhbnQgbm90IGZvdW5kIGZvciBlbmRwb2ludCBcIiArXG4gICAgICAgICAgICAgICAgbXNnLmVuZHBvaW50TmFtZSArIFwiLiBJY2UgY2FuZGlkYXRlIHdpbGwgYmUgaWdub3JlZC5cIixcbiAgICAgICAgICAgICAgICBjYW5kaWRhdGUpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHN0cmVhbXMgPSBjb25uZWN0aW9uLmdldFN0cmVhbXMoKTtcbiAgICAgICAgZm9yIChsZXQga2V5IGluIHN0cmVhbXMpIHtcbiAgICAgICAgICAgIGxldCBzdHJlYW0gPSBzdHJlYW1zW2tleV07XG4gICAgICAgICAgICBzdHJlYW0uZ2V0V2ViUnRjUGVlcigpLmFkZEljZUNhbmRpZGF0ZShjYW5kaWRhdGUsIGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3IgYWRkaW5nIGNhbmRpZGF0ZSBmb3IgXCIgKyBrZXlcbiAgICAgICAgICAgICAgICAgICAgICAgICsgXCIgc3RyZWFtIG9mIGVuZHBvaW50IFwiICsgbXNnLmVuZHBvaW50TmFtZVxuICAgICAgICAgICAgICAgICAgICAgICAgKyBcIjogXCIgKyBlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvblJvb21DbG9zZWQobXNnKSB7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKFwiU2Vzc2lvbiBjbG9zZWQ6IFwiICsgSlNPTi5zdHJpbmdpZnkobXNnKSk7XG4gICAgICAgIGxldCByb29tID0gbXNnLnJvb207XG4gICAgICAgIGlmIChyb29tICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyb29tLWNsb3NlZCcsIFt7XG4gICAgICAgICAgICAgICAgcm9vbTogcm9vbVxuICAgICAgICAgICAgfV0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiU2Vzc2lvbiB1bmRlZmluZWQgb24gc2Vzc2lvbiBjbG9zZWRcIiwgbXNnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG9uTG9zdENvbm5lY3Rpb24oKSB7XG5cbiAgICAgICAgaWYgKCF0aGlzLmNvbm5lY3RlZCkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdOb3QgY29ubmVjdGVkIHRvIHNlc3Npb246IGlmIHlvdSBhcmUgbm90IGRlYnVnZ2luZywgdGhpcyBpcyBwcm9iYWJseSBhIGNlcnRpZmljYXRlIGVycm9yJyk7XG4gICAgICAgICAgICBpZiAod2luZG93LmNvbmZpcm0oJ0lmIHlvdSBhcmUgbm90IGRlYnVnZ2luZywgdGhpcyBpcyBwcm9iYWJseSBhIGNlcnRpZmljYXRlIGVycm9yIGF0IFxcXCInICsgdGhpcy5vcGVuVmlkdS5nZXRPcGVuVmlkdVNlcnZlclVSTCgpICsgJ1xcXCJcXG5cXG5DbGljayBPSyB0byBuYXZpZ2F0ZSBhbmQgYWNjZXB0IGl0JykpIHtcbiAgICAgICAgICAgICAgICBsb2NhdGlvbi5hc3NpZ24odGhpcy5vcGVuVmlkdS5nZXRPcGVuVmlkdVNlcnZlclVSTCgpICsgJy9hY2NlcHQtY2VydGlmaWNhdGUnKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlLndhcm4oJ0xvc3QgY29ubmVjdGlvbiBpbiBTZXNzaW9uICcgKyB0aGlzLmlkKTtcbiAgICAgICAgbGV0IHJvb20gPSB0aGlzLmlkO1xuICAgICAgICBpZiAocm9vbSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnbG9zdC1jb25uZWN0aW9uJywgW3sgcm9vbSB9XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1Nlc3Npb24gdW5kZWZpbmVkIHdoZW4gbG9zdCBjb25uZWN0aW9uJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvbk1lZGlhRXJyb3IocGFyYW1zKSB7XG5cbiAgICAgICAgY29uc29sZS5lcnJvcihcIk1lZGlhIGVycm9yOiBcIiArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykpO1xuICAgICAgICBsZXQgZXJyb3IgPSBwYXJhbXMuZXJyb3I7XG4gICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Vycm9yLW1lZGlhJywgW3tcbiAgICAgICAgICAgICAgICBlcnJvcjogZXJyb3JcbiAgICAgICAgICAgIH1dKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIlJlY2VpdmVkIHVuZGVmaW5lZCBtZWRpYSBlcnJvci4gUGFyYW1zOlwiLCBwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBmb3JjZWQgbWVhbnMgdGhlIHVzZXIgd2FzIGV2aWN0ZWQsIG5vIG5lZWQgdG8gc2VuZCB0aGUgJ2xlYXZlUm9vbScgcmVxdWVzdFxuICAgICAqL1xuICAgIGxlYXZlKGZvcmNlZCwganNvblJwY0NsaWVudCkge1xuXG4gICAgICAgIGZvcmNlZCA9ICEhZm9yY2VkO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIkxlYXZpbmcgU2Vzc2lvbiAoZm9yY2VkPVwiICsgZm9yY2VkICsgXCIpXCIpO1xuXG4gICAgICAgIGlmICh0aGlzLmNvbm5lY3RlZCAmJiAhZm9yY2VkKSB7XG4gICAgICAgICAgICB0aGlzLm9wZW5WaWR1LnNlbmRSZXF1ZXN0KCdsZWF2ZVJvb20nLCBmdW5jdGlvbiAoZXJyb3IsIHJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBqc29uUnBjQ2xpZW50LmNsb3NlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGpzb25ScGNDbGllbnQuY2xvc2UoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgICAgICBpZiAodGhpcy5wYXJ0aWNpcGFudHMpIHtcbiAgICAgICAgICAgIGZvciAobGV0IHBpZCBpbiB0aGlzLnBhcnRpY2lwYW50cykge1xuICAgICAgICAgICAgICAgIHRoaXMucGFydGljaXBhbnRzW3BpZF0uZGlzcG9zZSgpO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnBhcnRpY2lwYW50c1twaWRdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZGlzY29ubmVjdChzdHJlYW06IFN0cmVhbSkge1xuXG4gICAgICAgIGxldCBjb25uZWN0aW9uID0gc3RyZWFtLmdldFBhcnRpY2lwYW50KCk7XG4gICAgICAgIGlmICghY29ubmVjdGlvbikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIlN0cmVhbSB0byBkaXNjb25uZWN0IGhhcyBubyBwYXJ0aWNpcGFudFwiLCBzdHJlYW0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZGVsZXRlIHRoaXMucGFydGljaXBhbnRzW2Nvbm5lY3Rpb24uY29ubmVjdGlvbklkXTtcbiAgICAgICAgY29ubmVjdGlvbi5kaXNwb3NlKCk7XG5cbiAgICAgICAgaWYgKGNvbm5lY3Rpb24gPT09IHRoaXMubG9jYWxQYXJ0aWNpcGFudCkge1xuXG4gICAgICAgICAgICBjb25zb2xlLmluZm8oXCJVbnB1Ymxpc2hpbmcgbXkgbWVkaWEgKEknbSBcIiArIGNvbm5lY3Rpb24uY29ubmVjdGlvbklkICsgXCIpXCIpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMubG9jYWxQYXJ0aWNpcGFudDtcbiAgICAgICAgICAgIHRoaXMub3BlblZpZHUuc2VuZFJlcXVlc3QoJ3VucHVibGlzaFZpZGVvJywgZnVuY3Rpb24gKGVycm9yLCByZXNwb25zZSkge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJNZWRpYSB1bnB1Ymxpc2hlZCBjb3JyZWN0bHlcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMudW5zdWJzY3JpYmUoc3RyZWFtKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHVucHVibGlzaChwdWJsaXNoZXI6IFB1Ymxpc2hlcikge1xuXG4gICAgICAgIGxldCBzdHJlYW0gPSBwdWJsaXNoZXIuc3RyZWFtO1xuXG4gICAgICAgIGlmICghc3RyZWFtLmNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBudWxsXCIsIHN0cmVhbSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSBpZiAoc3RyZWFtLmNvbm5lY3Rpb24gIT09IHRoaXMubG9jYWxQYXJ0aWNpcGFudCkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIlRoZSBhc3NvY2lhdGVkIENvbm5lY3Rpb24gb2JqZWN0IG9mIHRoaXMgUHVibGlzaGVyIGlzIG5vdCB5b3VyIGxvY2FsIENvbm5lY3Rpb24uXCIgK1xuICAgICAgICAgICAgICAgIFwiT25seSBtb2RlcmF0b3JzIGNhbiBmb3JjZSB1bnB1Ymxpc2ggb24gcmVtb3RlIFN0cmVhbXMgdmlhICdmb3JjZVVucHVibGlzaCcgbWV0aG9kXCIsIHN0cmVhbSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdHJlYW0uZGlzcG9zZSgpO1xuXG4gICAgICAgICAgICBjb25zb2xlLmluZm8oXCJVbnB1Ymxpc2hpbmcgbG9jYWwgbWVkaWEgKFwiICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkICsgXCIpXCIpO1xuXG4gICAgICAgICAgICB0aGlzLm9wZW5WaWR1LnNlbmRSZXF1ZXN0KCd1bnB1Ymxpc2hWaWRlbycsIGZ1bmN0aW9uIChlcnJvciwgcmVzcG9uc2UpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiTWVkaWEgdW5wdWJsaXNoZWQgY29ycmVjdGx5XCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBzdHJlYW0uaXNSZWFkeVRvUHVibGlzaCA9IGZhbHNlO1xuICAgICAgICAgICAgc3RyZWFtLmlzU2NyZWVuUmVxdWVzdGVkUmVhZHkgPSBmYWxzZTtcblxuICAgICAgICAgICAgZGVsZXRlIHN0cmVhbS5jb25uZWN0aW9uLmdldFN0cmVhbXMoKVtzdHJlYW0uc3RyZWFtSWRdO1xuXG4gICAgICAgICAgICBwdWJsaXNoZXIuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbe1xuICAgICAgICAgICAgICAgIHN0cmVhbTogcHVibGlzaGVyLnN0cmVhbSxcbiAgICAgICAgICAgICAgICBwcmV2ZW50RGVmYXVsdDogKCkgPT4geyB0aGlzLmVlLnJlbW92ZUV2ZW50KCdzdHJlYW0tZGVzdHJveWVkLWRlZmF1bHQnKTsgfVxuICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgcHVibGlzaGVyLmVlLmVtaXRFdmVudCgnc3RyZWFtLWRlc3Ryb3llZC1kZWZhdWx0JywgW3tcbiAgICAgICAgICAgICAgICBzdHJlYW06IHB1Ymxpc2hlci5zdHJlYW1cbiAgICAgICAgICAgIH1dKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGdldFJlbW90ZVN0cmVhbXMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJlbW90ZVN0cmVhbXM7XG4gICAgfVxuXG4gICAgYWRkUGFydGljaXBhbnRTcGVha2luZyhwYXJ0aWNpcGFudElkKSB7XG4gICAgICAgIHRoaXMucHVibGlzaGVyc1NwZWFraW5nLnB1c2gocGFydGljaXBhbnRJZCk7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgW3tcbiAgICAgICAgICAgIHBhcnRpY2lwYW50SWQ6IHBhcnRpY2lwYW50SWRcbiAgICAgICAgfV0pO1xuICAgIH1cblxuICAgIHJlbW92ZVBhcnRpY2lwYW50U3BlYWtpbmcocGFydGljaXBhbnRJZCkge1xuICAgICAgICBsZXQgcG9zID0gLTE7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5wdWJsaXNoZXJzU3BlYWtpbmcubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnB1Ymxpc2hlcnNTcGVha2luZ1tpXSA9PSBwYXJ0aWNpcGFudElkKSB7XG4gICAgICAgICAgICAgICAgcG9zID0gaTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAocG9zICE9IC0xKSB7XG4gICAgICAgICAgICB0aGlzLnB1Ymxpc2hlcnNTcGVha2luZy5zcGxpY2UocG9zLCAxKTtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCBbe1xuICAgICAgICAgICAgICAgIHBhcnRpY2lwYW50SWQ6IHBhcnRpY2lwYW50SWRcbiAgICAgICAgICAgIH1dKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHN0cmluZ0NsaWVudE1ldGFkYXRhKG1ldGFkYXRhKTogc3RyaW5nIHtcbiAgICAgICAgaWYgKCEodHlwZW9mIG1ldGFkYXRhID09PSAnc3RyaW5nJykpIHtcbiAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShtZXRhZGF0YSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbWV0YWRhdGE7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHJhbmRvbVRva2VuKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiBNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zbGljZSgyKSArIE1hdGgucmFuZG9tKCkudG9TdHJpbmcoMzYpLnNsaWNlKDIpO1xuICAgIH1cblxufVxuIiwiLypcbiAqIG9wdGlvbnM6IG5hbWU6IFhYWCBkYXRhOiB0cnVlIChNYXliZSB0aGlzIGlzIGJhc2VkIG9uIHdlYnJ0YykgYXVkaW86IHRydWUsXG4gKiB2aWRlbzogdHJ1ZSwgdXJsOiBcImZpbGU6Ly8vLi4uXCIgPiBQbGF5ZXIgc2NyZWVuOiB0cnVlID4gRGVza3RvcCAoaW1wbGljaXRcbiAqIHZpZGVvOnRydWUsIGF1ZGlvOmZhbHNlKSBhdWRpbzogdHJ1ZSwgdmlkZW86IHRydWUgPiBXZWJjYW1cbiAqXG4gKiBzdHJlYW0uaGFzQXVkaW8oKTsgc3RyZWFtLmhhc1ZpZGVvKCk7IHN0cmVhbS5oYXNEYXRhKCk7XG4gKi9cbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuL0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbkludGVybmFsIH0gZnJvbSAnLi9TZXNzaW9uSW50ZXJuYWwnO1xuaW1wb3J0IHsgT3BlblZpZHVJbnRlcm5hbCwgQ2FsbGJhY2sgfSBmcm9tICcuL09wZW5WaWR1SW50ZXJuYWwnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgV2ViUnRjU3RhdHMgfSBmcm9tICcuL1dlYlJ0Y1N0YXRzJztcbmltcG9ydCBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCd3b2xmeTg3LWV2ZW50ZW1pdHRlcicpO1xuaW1wb3J0ICogYXMga3VyZW50b1V0aWxzIGZyb20gJy4uL0t1cmVudG9VdGlscy9rdXJlbnRvLXV0aWxzLWpzJztcblxuaW1wb3J0ICogYXMgYWRhcHRlciBmcm9tICd3ZWJydGMtYWRhcHRlcic7XG5cbmRlY2xhcmUgdmFyIG5hdmlnYXRvcjogYW55O1xuZGVjbGFyZSB2YXIgUlRDU2Vzc2lvbkRlc2NyaXB0aW9uOiBhbnk7XG5cbmlmICh3aW5kb3cpIHtcbiAgICB3aW5kb3dbXCJhZGFwdGVyXCJdID0gYWRhcHRlcjtcbn1cblxuZnVuY3Rpb24ganEoaWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGlkLnJlcGxhY2UoLyhAfDp8XFwufFxcW3xcXF18LCkvZywgXCJcXFxcJDFcIik7XG59XG5cbmZ1bmN0aW9uIHNob3coaWQ6IHN0cmluZykge1xuICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGpxKGlkKSkhLnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xufVxuXG5mdW5jdGlvbiBoaWRlKGlkOiBzdHJpbmcpIHtcbiAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChqcShpZCkpIS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFN0cmVhbU9wdGlvbnNTZXJ2ZXIge1xuICAgIGlkOiBzdHJpbmc7XG4gICAgYXVkaW9BY3RpdmU6IGJvb2xlYW47XG4gICAgdmlkZW9BY3RpdmU6IGJvb2xlYW47XG4gICAgdHlwZU9mVmlkZW86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJbmJvdW5kU3RyZWFtT3B0aW9ucyB7XG4gICAgaWQ6IHN0cmluZztcbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuICAgIHJlY3ZBdWRpbzogYm9vbGVhbjtcbiAgICByZWN2VmlkZW86IGJvb2xlYW47XG4gICAgdHlwZU9mVmlkZW86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPdXRib3VuZFN0cmVhbU9wdGlvbnMge1xuICAgIGFjdGl2ZUF1ZGlvOiBib29sZWFuO1xuICAgIGFjdGl2ZVZpZGVvOiBib29sZWFuO1xuICAgIGRhdGFDaGFubmVsOiBib29sZWFuO1xuICAgIG1lZGlhQ29uc3RyYWludHM6IGFueTtcbiAgICBzZW5kQXVkaW86IGJvb2xlYW47XG4gICAgc2VuZFZpZGVvOiBib29sZWFuO1xufVxuXG5leHBvcnQgY2xhc3MgU3RyZWFtIHtcblxuICAgIHB1YmxpYyBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuICAgIHB1YmxpYyBzdHJlYW1JZDogc3RyaW5nO1xuICAgIHB1YmxpYyBoYXNWaWRlbzogYm9vbGVhbjtcbiAgICBwdWJsaWMgaGFzQXVkaW86IGJvb2xlYW47XG4gICAgcHVibGljIHR5cGVPZlZpZGVvOiBzdHJpbmc7IC8vICdDQU1FUkEnIG9yICdTQ1JFRU4nXG5cbiAgICBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICBwcml2YXRlIG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbTtcbiAgICBwcml2YXRlIHdwOiBhbnk7XG4gICAgcHJpdmF0ZSB2aWRlbzogSFRNTFZpZGVvRWxlbWVudDtcbiAgICBwcml2YXRlIHNwZWVjaEV2ZW50OiBhbnk7XG4gICAgcHJpdmF0ZSBzaG93TXlSZW1vdGUgPSBmYWxzZTtcbiAgICBwcml2YXRlIGxvY2FsTWlycm9yZWQgPSBmYWxzZTtcbiAgICBwcml2YXRlIGNoYW5JZCA9IDA7XG4gICAgcHJpdmF0ZSBkYXRhQ2hhbm5lbE9wZW5lZCA9IGZhbHNlO1xuXG4gICAgaW5ib3VuZE9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zO1xuICAgIG91dGJvdW5kT3B0aW9uczogT3V0Ym91bmRTdHJlYW1PcHRpb25zO1xuXG4gICAgcHJpdmF0ZSBwYXJlbnRJZDogc3RyaW5nO1xuICAgIHB1YmxpYyBpc1JlYWR5VG9QdWJsaXNoOiBib29sZWFuID0gZmFsc2U7XG4gICAgcHVibGljIGlzUHVibGlzaGVyUHVibGlzaGVkOiBib29sZWFuID0gZmFsc2U7XG4gICAgcHVibGljIGlzVmlkZW9FTGVtZW50Q3JlYXRlZDogYm9vbGVhbiA9IGZhbHNlO1xuICAgIHB1YmxpYyBhY2Nlc3NJc0FsbG93ZWQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBwdWJsaWMgYWNjZXNzSXNEZW5pZWQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBwdWJsaWMgaXNTY3JlZW5SZXF1ZXN0ZWRSZWFkeTogYm9vbGVhbiA9IGZhbHNlO1xuICAgIHByaXZhdGUgaXNTY3JlZW5SZXF1ZXN0ZWQgPSBmYWxzZTtcblxuICAgIHByaXZhdGUgd2ViUnRjU3RhdHM6IFdlYlJ0Y1N0YXRzO1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBvcGVuVmlkdTogT3BlblZpZHVJbnRlcm5hbCwgcHJpdmF0ZSBsb2NhbDogYm9vbGVhbiwgcHJpdmF0ZSByb29tOiBTZXNzaW9uSW50ZXJuYWwsIG9wdGlvbnM6IGFueSkge1xuICAgICAgICBpZiAob3B0aW9ucyAhPT0gJ3NjcmVlbi1vcHRpb25zJykge1xuICAgICAgICAgICAgLy8gT3V0Ym91bmQgc3RyZWFtIChub3Qgc2NyZWVuIHNoYXJlKSBvciBJbmJvdW5kIHN0cmVhbVxuICAgICAgICAgICAgaWYgKCdpZCcgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5ib3VuZE9wdGlvbnMgPSBvcHRpb25zO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLm91dGJvdW5kT3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnN0cmVhbUlkID0gKG9wdGlvbnMuaWQgIT0gbnVsbCkgPyBvcHRpb25zLmlkIDogKChvcHRpb25zLnNlbmRWaWRlbykgPyBcIkNBTUVSQVwiIDogXCJNSUNST1wiKTtcbiAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSAob3B0aW9ucy50eXBlT2ZWaWRlbyAhPSBudWxsKSA/IG9wdGlvbnMudHlwZU9mVmlkZW8gOiAnJztcblxuICAgICAgICAgICAgaWYgKCdyZWN2QXVkaW8nIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICAvLyBTZXQgQ29ubmVjdGlvbiBmb3IgYW4gSW5ib3VuZCBzdHJlYW0gKGZvciBPdXRib3VuZCBzdHJlYW1zIHdpbGwgYmUgc2V0IG9uIFNlc3Npb24uUHVibGlzaChQdWJsaXNoZXIpKVxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IG9wdGlvbnMuY29ubmVjdGlvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE91dGJvdW5kIHN0cmVhbSBmb3Igc2NyZWVuIHNoYXJlXG4gICAgICAgICAgICB0aGlzLmlzU2NyZWVuUmVxdWVzdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSAnU0NSRUVOJztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ21lZGlhc3RyZWFtLXVwZGF0ZWQnLCAoKSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy52aWRlbykgdGhpcy52aWRlby5zcmNPYmplY3QgPSB0aGlzLm1lZGlhU3RyZWFtO1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZyhcIlZpZGVvIHNyY09iamVjdCBbXCIgKyB0aGlzLm1lZGlhU3RyZWFtICsgXCJdIGFkZGVkIHRvIHN0cmVhbSBbXCIgKyB0aGlzLnN0cmVhbUlkICsgXCJdXCIpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBlbWl0U3RyZWFtUmVhZHlFdmVudCgpIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbS1yZWFkeScpO1xuICAgIH1cblxuICAgIHJlbW92ZVZpZGVvKHBhcmVudEVsZW1lbnQ6IHN0cmluZyk7XG4gICAgcmVtb3ZlVmlkZW8ocGFyZW50RWxlbWVudDogRWxlbWVudCk7XG4gICAgcmVtb3ZlVmlkZW8oKTtcblxuICAgIHJlbW92ZVZpZGVvKHBhcmVudEVsZW1lbnQ/KSB7XG4gICAgICAgIGlmICh0aGlzLnZpZGVvKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHBhcmVudEVsZW1lbnQgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChwYXJlbnRFbGVtZW50KSEucmVtb3ZlQ2hpbGQodGhpcy52aWRlbyk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvLXJlbW92ZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocGFyZW50RWxlbWVudCBpbnN0YW5jZW9mIEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICBwYXJlbnRFbGVtZW50LnJlbW92ZUNoaWxkKHRoaXMudmlkZW8pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlby1yZW1vdmVkJyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCFwYXJlbnRFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgaWYgKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMucGFyZW50SWQpKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMucGFyZW50SWQpIS5yZW1vdmVDaGlsZCh0aGlzLnZpZGVvKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvLXJlbW92ZWQnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWxldGUgdGhpcy52aWRlbztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGdldFZpZGVvRWxlbWVudCgpOiBIVE1MVmlkZW9FbGVtZW50IHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmlkZW87XG4gICAgfVxuXG4gICAgc2V0VmlkZW9FbGVtZW50KHZpZGVvKSB7XG4gICAgICAgIGlmICghIXZpZGVvKSB0aGlzLnZpZGVvID0gdmlkZW87XG4gICAgfVxuXG4gICAgZ2V0UGFyZW50SWQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBhcmVudElkO1xuICAgIH1cblxuICAgIGdldFJlY3ZWaWRlbygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaW5ib3VuZE9wdGlvbnMucmVjdlZpZGVvO1xuICAgIH1cblxuICAgIGdldFJlY3ZBdWRpbygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaW5ib3VuZE9wdGlvbnMucmVjdkF1ZGlvO1xuICAgIH1cblxuICAgIGdldFNlbmRWaWRlbygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3V0Ym91bmRPcHRpb25zLnNlbmRWaWRlbztcbiAgICB9XG5cbiAgICBnZXRTZW5kQXVkaW8oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm91dGJvdW5kT3B0aW9ucy5zZW5kQXVkaW87XG4gICAgfVxuXG5cbiAgICBzdWJzY3JpYmVUb015UmVtb3RlKCkge1xuICAgICAgICB0aGlzLnNob3dNeVJlbW90ZSA9IHRydWU7XG4gICAgfVxuXG4gICAgZGlzcGxheU15UmVtb3RlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zaG93TXlSZW1vdGU7XG4gICAgfVxuXG4gICAgbWlycm9yTG9jYWxTdHJlYW0od3IpIHtcbiAgICAgICAgdGhpcy5zaG93TXlSZW1vdGUgPSB0cnVlO1xuICAgICAgICB0aGlzLmxvY2FsTWlycm9yZWQgPSB0cnVlO1xuICAgICAgICBpZiAod3IpIHtcbiAgICAgICAgICAgIHRoaXMubWVkaWFTdHJlYW0gPSB3cjtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdtZWRpYXN0cmVhbS11cGRhdGVkJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpc0xvY2FsTWlycm9yZWQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxvY2FsTWlycm9yZWQ7XG4gICAgfVxuXG4gICAgZ2V0Q2hhbm5lbE5hbWUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0cmVhbUlkICsgJ18nICsgdGhpcy5jaGFuSWQrKztcbiAgICB9XG5cblxuICAgIGlzRGF0YUNoYW5uZWxFbmFibGVkKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5vdXRib3VuZE9wdGlvbnMuZGF0YUNoYW5uZWw7XG4gICAgfVxuXG5cbiAgICBpc0RhdGFDaGFubmVsT3BlbmVkKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kYXRhQ2hhbm5lbE9wZW5lZDtcbiAgICB9XG5cbiAgICBvbkRhdGFDaGFubmVsT3BlbihldmVudCkge1xuICAgICAgICBjb25zb2xlLmRlYnVnKCdEYXRhIGNoYW5uZWwgaXMgb3BlbmVkJyk7XG4gICAgICAgIHRoaXMuZGF0YUNoYW5uZWxPcGVuZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIG9uRGF0YUNoYW5uZWxDbG9zZWQoZXZlbnQpIHtcbiAgICAgICAgY29uc29sZS5kZWJ1ZygnRGF0YSBjaGFubmVsIGlzIGNsb3NlZCcpO1xuICAgICAgICB0aGlzLmRhdGFDaGFubmVsT3BlbmVkID0gZmFsc2U7XG4gICAgfVxuXG4gICAgc2VuZERhdGEoZGF0YSkge1xuICAgICAgICBpZiAodGhpcy53cCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1dlYlJUQyBwZWVyIGhhcyBub3QgYmVlbiBjcmVhdGVkIHlldCcpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5kYXRhQ2hhbm5lbE9wZW5lZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdEYXRhIGNoYW5uZWwgaXMgbm90IG9wZW5lZCcpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIlNlbmRpbmcgdGhyb3VnaCBkYXRhIGNoYW5uZWw6IFwiICsgZGF0YSk7XG4gICAgICAgIHRoaXMud3Auc2VuZChkYXRhKTtcbiAgICB9XG5cbiAgICBnZXRNZWRpYVN0cmVhbSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgZ2V0V2ViUnRjUGVlcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud3A7XG4gICAgfVxuXG4gICAgZ2V0UlRDUGVlckNvbm5lY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndwLnBlZXJDb25uZWN0aW9uO1xuICAgIH1cblxuICAgIGFkZEV2ZW50TGlzdGVuZXIoZXZlbnROYW1lOiBzdHJpbmcsIGxpc3RlbmVyOiBhbnkpIHtcbiAgICAgICAgdGhpcy5lZS5hZGRMaXN0ZW5lcihldmVudE5hbWUsIGxpc3RlbmVyKTtcbiAgICB9XG5cbiAgICBhZGRPbmNlRXZlbnRMaXN0ZW5lcihldmVudE5hbWU6IHN0cmluZywgbGlzdGVuZXI6IGFueSkge1xuICAgICAgICB0aGlzLmVlLmFkZE9uY2VMaXN0ZW5lcihldmVudE5hbWUsIGxpc3RlbmVyKTtcbiAgICB9XG5cbiAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpIHtcbiAgICAgICAgdGhpcy5lZS5yZW1vdmVBbGxMaXN0ZW5lcnMoZXZlbnROYW1lKTtcbiAgICB9XG5cbiAgICBzaG93U3Bpbm5lcihzcGlubmVyUGFyZW50SWQ6IHN0cmluZykge1xuICAgICAgICBsZXQgcHJvZ3Jlc3MgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgcHJvZ3Jlc3MuaWQgPSAncHJvZ3Jlc3MtJyArIHRoaXMuc3RyZWFtSWQ7XG4gICAgICAgIHByb2dyZXNzLnN0eWxlLmJhY2tncm91bmQgPSBcImNlbnRlciB0cmFuc3BhcmVudCB1cmwoJ2ltZy9zcGlubmVyLmdpZicpIG5vLXJlcGVhdFwiO1xuICAgICAgICBsZXQgc3Bpbm5lclBhcmVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHNwaW5uZXJQYXJlbnRJZCk7XG4gICAgICAgIGlmIChzcGlubmVyUGFyZW50KSB7XG4gICAgICAgICAgICBzcGlubmVyUGFyZW50LmFwcGVuZENoaWxkKHByb2dyZXNzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGhpZGVTcGlubmVyKHNwaW5uZXJJZD86IHN0cmluZykge1xuICAgICAgICBzcGlubmVySWQgPSAoc3Bpbm5lcklkID09PSB1bmRlZmluZWQpID8gdGhpcy5zdHJlYW1JZCA6IHNwaW5uZXJJZDtcbiAgICAgICAgaGlkZSgncHJvZ3Jlc3MtJyArIHNwaW5uZXJJZCk7XG4gICAgfVxuXG4gICAgcGxheU9ubHlWaWRlbyhwYXJlbnRFbGVtZW50LCB0aHVtYm5haWxJZCkge1xuICAgICAgICBpZiAoISFwYXJlbnRFbGVtZW50KSB7XG5cbiAgICAgICAgICAgIHRoaXMudmlkZW8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuXG4gICAgICAgICAgICB0aGlzLnZpZGVvLmlkID0gKHRoaXMubG9jYWwgPyAnbG9jYWwtJyA6ICdyZW1vdGUtJykgKyAndmlkZW8tJyArIHRoaXMuc3RyZWFtSWQ7XG4gICAgICAgICAgICB0aGlzLnZpZGVvLmF1dG9wbGF5ID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMudmlkZW8uY29udHJvbHMgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdtZWRpYXN0cmVhbS11cGRhdGVkJyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmxvY2FsICYmICF0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlby5tdXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlby5vbmNhbnBsYXkgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkxvY2FsICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW1JZCArIFwiXSB2aWRlbyBpcyBub3cgcGxheWluZ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvLWlzLXBsYXlpbmcnLCBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudDogdGhpcy52aWRlb1xuICAgICAgICAgICAgICAgICAgICB9XSk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlby50aXRsZSA9IHRoaXMuc3RyZWFtSWQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgcGFyZW50RWxlbWVudCA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgIHRoaXMucGFyZW50SWQgPSBwYXJlbnRFbGVtZW50O1xuXG4gICAgICAgICAgICAgICAgbGV0IHBhcmVudEVsZW1lbnREb20gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChwYXJlbnRFbGVtZW50KTtcbiAgICAgICAgICAgICAgICBpZiAocGFyZW50RWxlbWVudERvbSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnZpZGVvID0gcGFyZW50RWxlbWVudERvbS5hcHBlbmRDaGlsZCh0aGlzLnZpZGVvKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvLWVsZW1lbnQtY3JlYXRlZC1ieS1zdHJlYW0nLCBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudDogdGhpcy52aWRlb1xuICAgICAgICAgICAgICAgICAgICB9XSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaXNWaWRlb0VMZW1lbnRDcmVhdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMucGFyZW50SWQgPSBwYXJlbnRFbGVtZW50LmlkO1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW8gPSBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMudmlkZW8pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmlzUmVhZHlUb1B1Ymxpc2ggPSB0cnVlO1xuXG4gICAgICAgICAgICByZXR1cm4gdGhpcy52aWRlbztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHBsYXlUaHVtYm5haWwodGh1bWJuYWlsSWQpIHtcblxuICAgICAgICBsZXQgY29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIGNvbnRhaW5lci5jbGFzc05hbWUgPSBcInBhcnRpY2lwYW50XCI7XG4gICAgICAgIGNvbnRhaW5lci5pZCA9IHRoaXMuc3RyZWFtSWQ7XG4gICAgICAgIGxldCB0aHVtYm5haWwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aHVtYm5haWxJZCk7XG4gICAgICAgIGlmICh0aHVtYm5haWwpIHtcbiAgICAgICAgICAgIHRodW1ibmFpbC5hcHBlbmRDaGlsZChjb250YWluZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IG5hbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgY29udGFpbmVyLmFwcGVuZENoaWxkKG5hbWUpO1xuICAgICAgICBsZXQgdXNlck5hbWUgPSB0aGlzLnN0cmVhbUlkLnJlcGxhY2UoJ193ZWJjYW0nLCAnJyk7XG4gICAgICAgIGlmICh1c2VyTmFtZS5sZW5ndGggPj0gMTYpIHtcbiAgICAgICAgICAgIHVzZXJOYW1lID0gdXNlck5hbWUuc3Vic3RyaW5nKDAsIDE2KSArIFwiLi4uXCI7XG4gICAgICAgIH1cbiAgICAgICAgbmFtZS5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSh1c2VyTmFtZSkpO1xuICAgICAgICBuYW1lLmlkID0gXCJuYW1lLVwiICsgdGhpcy5zdHJlYW1JZDtcbiAgICAgICAgbmFtZS5jbGFzc05hbWUgPSBcIm5hbWVcIjtcbiAgICAgICAgbmFtZS50aXRsZSA9IHRoaXMuc3RyZWFtSWQ7XG5cbiAgICAgICAgdGhpcy5zaG93U3Bpbm5lcih0aHVtYm5haWxJZCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMucGxheU9ubHlWaWRlbyhjb250YWluZXIsIHRodW1ibmFpbElkKTtcbiAgICB9XG5cbiAgICBnZXRQYXJ0aWNpcGFudCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29ubmVjdGlvbjtcbiAgICB9XG5cbiAgICByZXF1ZXN0Q2FtZXJhQWNjZXNzKGNhbGxiYWNrOiBDYWxsYmFjazxTdHJlYW0+KSB7XG5cbiAgICAgICAgbGV0IGNvbnN0cmFpbnRzID0gdGhpcy5vdXRib3VuZE9wdGlvbnMubWVkaWFDb25zdHJhaW50cztcblxuICAgICAgICAvKmxldCBjb25zdHJhaW50czIgPSB7XG4gICAgICAgICAgICBhdWRpbzogdHJ1ZSxcbiAgICAgICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICAgICAgd2lkdGg6IHtcbiAgICAgICAgICAgICAgICAgICAgaWRlYWw6IDEyODBcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGZyYW1lUmF0ZToge1xuICAgICAgICAgICAgICAgICAgICBpZGVhbDogMTVcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07Ki9cblxuICAgICAgICB0aGlzLnVzZXJNZWRpYUhhc1ZpZGVvKChoYXNWaWRlbykgPT4ge1xuICAgICAgICAgICAgaWYgKCFoYXNWaWRlbykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLm91dGJvdW5kT3B0aW9ucy5zZW5kVmlkZW8pIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuTk9fVklERU9fREVWSUNFLCAnWW91IGhhdmUgcmVxdWVzdGVkIGNhbWVyYSBhY2Nlc3MgYnV0IHRoZXJlIGlzIG5vIHZpZGVvIGlucHV0IGRldmljZSBhdmFpbGFibGUuIFRyeWluZyB0byBjb25uZWN0IHdpdGggYW4gYXVkaW8gaW5wdXQgZGV2aWNlIG9ubHknKSwgdGhpcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5vdXRib3VuZE9wdGlvbnMuc2VuZEF1ZGlvKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk5PX0lOUFVUX0RFVklDRSwgJ1lvdSBtdXN0IGluaXQgUHVibGlzaGVyIG9iamVjdCB3aXRoIGF1ZGlvIG9yIHZpZGVvIHN0cmVhbXMgZW5hYmxlZCcpLCB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzLnZpZGVvID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub3V0Ym91bmRPcHRpb25zLnNlbmRWaWRlbyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlcXVlc3RDYW1lcmFBY2Nlc0F1eChjb25zdHJhaW50cywgY2FsbGJhY2spO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXF1ZXN0Q2FtZXJhQWNjZXNBdXgoY29uc3RyYWludHMsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZXF1ZXN0Q2FtZXJhQWNjZXNBdXgoY29uc3RyYWludHMsIGNhbGxiYWNrKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGNvbnN0cmFpbnRzKTtcbiAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoY29uc3RyYWludHMpXG4gICAgICAgICAgICAudGhlbih1c2VyU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbWVyYUFjY2Vzc1N1Y2Nlc3ModXNlclN0cmVhbSwgY2FsbGJhY2spO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NJc0RlbmllZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NJc0FsbG93ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBsZXQgZXJyb3JOYW1lOiBPcGVuVmlkdUVycm9yTmFtZTtcbiAgICAgICAgICAgICAgICBsZXQgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTs7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmlzU2NyZWVuUmVxdWVzdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IHRoaXMub3V0Ym91bmRPcHRpb25zLnNlbmRWaWRlbyA/IE9wZW5WaWR1RXJyb3JOYW1lLkNBTUVSQV9BQ0NFU1NfREVOSUVEIDogT3BlblZpZHVFcnJvck5hbWUuTUlDUk9QSE9ORV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRDsgLy8gVGhpcyBjb2RlIGlzIG9ubHkgcmVhY2hhYmxlIGZvciBGaXJlZm94XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSwgdW5kZWZpbmVkKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgY2FtZXJhQWNjZXNzU3VjY2Vzcyh1c2VyU3RyZWFtOiBNZWRpYVN0cmVhbSwgY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gICAgICAgIHRoaXMuYWNjZXNzSXNBbGxvd2VkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5hY2Nlc3NJc0RlbmllZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnYWNjZXNzLWFsbG93ZWQtYnktcHVibGlzaGVyJyk7XG5cbiAgICAgICAgaWYgKHVzZXJTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSAhPSBudWxsKSB7XG4gICAgICAgICAgICB1c2VyU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0uZW5hYmxlZCA9IHRoaXMub3V0Ym91bmRPcHRpb25zLmFjdGl2ZUF1ZGlvO1xuICAgICAgICB9XG4gICAgICAgIGlmICh1c2VyU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0gIT0gbnVsbCkge1xuICAgICAgICAgICAgdXNlclN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdLmVuYWJsZWQgPSB0aGlzLm91dGJvdW5kT3B0aW9ucy5hY3RpdmVWaWRlbztcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMubWVkaWFTdHJlYW0gPSB1c2VyU3RyZWFtO1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnbWVkaWFzdHJlYW0tdXBkYXRlZCcpO1xuXG4gICAgICAgIGNhbGxiYWNrKHVuZGVmaW5lZCwgdGhpcyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSB1c2VyTWVkaWFIYXNWaWRlbyhjYWxsYmFjaykge1xuICAgICAgICAvLyBJZiB0aGUgdXNlciBpcyBnb2luZyB0byBwdWJsaXNoIGl0cyBzY3JlZW4gdGhlcmUncyBhIHZpZGVvIHNvdXJjZVxuICAgICAgICBpZiAodGhpcy5pc1NjcmVlblJlcXVlc3RlZCkge1xuICAgICAgICAgICAgY2FsbGJhY2sodHJ1ZSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBMaXN0IGFsbCBpbnB1dCBkZXZpY2VzIGFuZCBzZXJhY2ggZm9yIGEgdmlkZW8ga2luZFxuICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKCkudGhlbihmdW5jdGlvbiAobWVkaWFEZXZpY2VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHZpZGVvSW5wdXQgPSBtZWRpYURldmljZXMuZmlsdGVyKGZ1bmN0aW9uIChkZXZpY2VJbmZvKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkZXZpY2VJbmZvLmtpbmQgPT09ICd2aWRlb2lucHV0JztcbiAgICAgICAgICAgICAgICB9KVswXTtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayh2aWRlb0lucHV0ICE9IG51bGwpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaXNoVmlkZW9DYWxsYmFjayhlcnJvciwgc2RwT2ZmZXJQYXJhbSwgd3ApIHtcblxuICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBjb25zb2xlLmVycm9yKFwiKHB1Ymxpc2gpIFNEUCBvZmZlciBlcnJvcjogXCJcbiAgICAgICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlLmRlYnVnKFwiU2VuZGluZyBTRFAgb2ZmZXIgdG8gcHVibGlzaCBhcyBcIlxuICAgICAgICAgICAgKyB0aGlzLnN0cmVhbUlkLCBzZHBPZmZlclBhcmFtKTtcblxuICAgICAgICB0aGlzLm9wZW5WaWR1LnNlbmRSZXF1ZXN0KFwicHVibGlzaFZpZGVvXCIsIHtcbiAgICAgICAgICAgIHNkcE9mZmVyOiBzZHBPZmZlclBhcmFtLFxuICAgICAgICAgICAgZG9Mb29wYmFjazogdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSB8fCBmYWxzZSxcbiAgICAgICAgICAgIGF1ZGlvQWN0aXZlOiB0aGlzLm91dGJvdW5kT3B0aW9ucy5zZW5kQXVkaW8sXG4gICAgICAgICAgICB2aWRlb0FjdGl2ZTogdGhpcy5vdXRib3VuZE9wdGlvbnMuc2VuZFZpZGVvLFxuICAgICAgICAgICAgdHlwZU9mVmlkZW86ICgodGhpcy5vdXRib3VuZE9wdGlvbnMuc2VuZFZpZGVvKSA/ICgodGhpcy5pc1NjcmVlblJlcXVlc3RlZCkgPyAnU0NSRUVOJyA6ICdDQU1FUkEnKSA6ICcnKVxuICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3Igb24gcHVibGlzaFZpZGVvOiBcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMucHJvY2Vzc1NkcEFuc3dlcihyZXNwb25zZS5zZHBBbnN3ZXIpO1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIHN1Y2Nlc2Z1bGx5IHB1Ymxpc2hlZCB0byBzZXNzaW9uXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBzdGFydFZpZGVvQ2FsbGJhY2soZXJyb3IsIHNkcE9mZmVyUGFyYW0sIHdwKSB7XG4gICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIGNvbnNvbGUuZXJyb3IoXCIoc3Vic2NyaWJlKSBTRFAgb2ZmZXIgZXJyb3I6IFwiXG4gICAgICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuZGVidWcoXCJTZW5kaW5nIFNEUCBvZmZlciB0byBzdWJzY3JpYmUgdG8gXCJcbiAgICAgICAgICAgICsgdGhpcy5zdHJlYW1JZCwgc2RwT2ZmZXJQYXJhbSk7XG4gICAgICAgIHRoaXMub3BlblZpZHUuc2VuZFJlcXVlc3QoXCJyZWNlaXZlVmlkZW9Gcm9tXCIsIHtcbiAgICAgICAgICAgIHNlbmRlcjogdGhpcy5zdHJlYW1JZCxcbiAgICAgICAgICAgIHNkcE9mZmVyOiBzZHBPZmZlclBhcmFtXG4gICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBvbiByZWN2VmlkZW9Gcm9tOiBcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMucHJvY2Vzc1NkcEFuc3dlcihyZXNwb25zZS5zZHBBbnN3ZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRXZWJSdGNQZWVyKHNkcE9mZmVyQ2FsbGJhY2spIHtcbiAgICAgICAgaWYgKHRoaXMubG9jYWwpIHtcblxuICAgICAgICAgICAgbGV0IHVzZXJNZWRpYUNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLm91dGJvdW5kT3B0aW9ucy5zZW5kQXVkaW8sXG4gICAgICAgICAgICAgICAgdmlkZW86IHRoaXMub3V0Ym91bmRPcHRpb25zLnNlbmRWaWRlb1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgb3B0aW9uczogYW55ID0ge1xuICAgICAgICAgICAgICAgIHZpZGVvU3RyZWFtOiB0aGlzLm1lZGlhU3RyZWFtLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IHVzZXJNZWRpYUNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgIG9uaWNlY2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLm91dGJvdW5kT3B0aW9ucy5kYXRhQ2hhbm5lbCkge1xuICAgICAgICAgICAgICAgIG9wdGlvbnMuZGF0YUNoYW5uZWxDb25maWcgPSB7XG4gICAgICAgICAgICAgICAgICAgIGlkOiB0aGlzLmdldENoYW5uZWxOYW1lKCksXG4gICAgICAgICAgICAgICAgICAgIG9ub3BlbjogdGhpcy5vbkRhdGFDaGFubmVsT3BlbixcbiAgICAgICAgICAgICAgICAgICAgb25jbG9zZTogdGhpcy5vbkRhdGFDaGFubmVsQ2xvc2VkXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBvcHRpb25zLmRhdGFDaGFubmVscyA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53cCA9IGt1cmVudG9VdGlscy5XZWJSdGNQZWVyLldlYlJ0Y1BlZXJTZW5kcmVjdihvcHRpb25zLCBlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud3AuZ2VuZXJhdGVPZmZlcihzZHBPZmZlckNhbGxiYWNrLmJpbmQodGhpcykpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLndwID0ga3VyZW50b1V0aWxzLldlYlJ0Y1BlZXIuV2ViUnRjUGVlclNlbmRvbmx5KG9wdGlvbnMsIGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy53cC5nZW5lcmF0ZU9mZmVyKHNkcE9mZmVyQ2FsbGJhY2suYmluZCh0aGlzKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmlzUHVibGlzaGVyUHVibGlzaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxldCBvZmZlckNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmluYm91bmRPcHRpb25zLnJlY3ZBdWRpbyxcbiAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5pbmJvdW5kT3B0aW9ucy5yZWN2VmlkZW9cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKFwiJ1Nlc3Npb24uc3Vic2NyaWJlKFN0cmVhbSknIGNhbGxlZC4gQ29uc3RyYWludHMgb2YgZ2VuZXJhdGUgU0RQIG9mZmVyXCIsXG4gICAgICAgICAgICAgICAgb2ZmZXJDb25zdHJhaW50cyk7XG4gICAgICAgICAgICBsZXQgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBvbmljZWNhbmRpZGF0ZTogdGhpcy5jb25uZWN0aW9uLnNlbmRJY2VDYW5kaWRhdGUuYmluZCh0aGlzLmNvbm5lY3Rpb24pLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IG9mZmVyQ29uc3RyYWludHNcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMud3AgPSBrdXJlbnRvVXRpbHMuV2ViUnRjUGVlci5XZWJSdGNQZWVyUmVjdm9ubHkob3B0aW9ucywgZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMud3AuZ2VuZXJhdGVPZmZlcihzZHBPZmZlckNhbGxiYWNrLmJpbmQodGhpcykpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS5kZWJ1ZyhcIldhaXRpbmcgZm9yIFNEUCBvZmZlciB0byBiZSBnZW5lcmF0ZWQgKFwiXG4gICAgICAgICAgICArICh0aGlzLmxvY2FsID8gXCJsb2NhbFwiIDogXCJyZW1vdGVcIikgKyBcIiAnU3RyZWFtJzogXCIgKyB0aGlzLnN0cmVhbUlkICsgXCIpXCIpO1xuICAgIH1cblxuICAgIHB1Ymxpc2goKSB7XG5cbiAgICAgICAgLy8gRklYTUU6IFRocm93IGVycm9yIHdoZW4gc3RyZWFtIGlzIG5vdCBsb2NhbFxuICAgICAgICBpZiAodGhpcy5pc1JlYWR5VG9QdWJsaXNoKSB7XG4gICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNQZWVyKHRoaXMucHVibGlzaFZpZGVvQ2FsbGJhY2spO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lZS5vbmNlKCdzdHJlYW0tcmVhZHknLCBzdHJlYW1FdmVudCA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5wdWJsaXNoKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEZJWE1FOiBOb3cgd2UgaGF2ZSBjb3VwbGVkIGNvbm5lY3RpbmcgdG8gYSByb29tIGFuZCBhZGRpbmcgYVxuICAgICAgICAvLyBzdHJlYW0gdG8gdGhpcyByb29tLiBCdXQgaW4gdGhlIG5ldyBBUEksIHRoZXJlIGFyZSB0d28gc3RlcHMuXG4gICAgICAgIC8vIFRoaXMgaXMgdGhlIHNlY29uZCBzdGVwLiBGb3Igbm93LCBpdCBkbyBub3RoaW5nLlxuXG4gICAgfVxuXG4gICAgc3Vic2NyaWJlKCkge1xuXG4gICAgICAgIC8vIEZJWE1FOiBJbiB0aGUgY3VycmVudCBpbXBsZW1lbnRhdGlvbiBhbGwgcGFydGljaXBhbnRzIGFyZSBzdWJzY3JpYmVkXG4gICAgICAgIC8vIGF1dG9tYXRpY2FsbHkgdG8gYWxsIG90aGVyIHBhcnRpY2lwYW50cy4gV2UgdXNlIHRoaXMgbWV0aG9kIG9ubHkgdG9cbiAgICAgICAgLy8gbmVnb3RpYXRlIFNEUFxuXG4gICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1BlZXIodGhpcy5zdGFydFZpZGVvQ2FsbGJhY2spO1xuICAgIH1cblxuICAgIHByb2Nlc3NTZHBBbnN3ZXIoc2RwQW5zd2VyKSB7XG5cbiAgICAgICAgbGV0IGFuc3dlciA9IG5ldyBSVENTZXNzaW9uRGVzY3JpcHRpb24oe1xuICAgICAgICAgICAgdHlwZTogJ2Fuc3dlcicsXG4gICAgICAgICAgICBzZHA6IHNkcEFuc3dlcixcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnNvbGUuZGVidWcodGhpcy5zdHJlYW1JZCArIFwiOiBzZXQgcGVlciBjb25uZWN0aW9uIHdpdGggcmVjdmQgU0RQIGFuc3dlclwiLFxuICAgICAgICAgICAgc2RwQW5zd2VyKTtcbiAgICAgICAgbGV0IHBhcnRpY2lwYW50SWQgPSB0aGlzLnN0cmVhbUlkO1xuICAgICAgICBsZXQgcGMgPSB0aGlzLndwLnBlZXJDb25uZWN0aW9uO1xuICAgICAgICBwYy5zZXRSZW1vdGVEZXNjcmlwdGlvbihhbnN3ZXIsICgpID0+IHtcbiAgICAgICAgICAgIC8vIEF2b2lkcyB0byBzdWJzY3JpYmUgdG8geW91ciBvd24gc3RyZWFtIHJlbW90ZWx5IFxuICAgICAgICAgICAgLy8gZXhjZXB0IHdoZW4gc2hvd015UmVtb3RlIGlzIHRydWVcbiAgICAgICAgICAgIGlmICghdGhpcy5sb2NhbCB8fCB0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbSA9IHBjLmdldFJlbW90ZVN0cmVhbXMoKVswXTtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKFwiUGVlciByZW1vdGUgc3RyZWFtXCIsIHRoaXMubWVkaWFTdHJlYW0pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubWVkaWFTdHJlYW0gIT0gdW5kZWZpbmVkKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ21lZGlhc3RyZWFtLXVwZGF0ZWQnKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdICE9IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudCA9IGt1cmVudG9VdGlscy5XZWJSdGNQZWVyLmhhcmsodGhpcy5tZWRpYVN0cmVhbSwgeyB0aHJlc2hvbGQ6IHRoaXMucm9vbS50aHJlc2hvbGRTcGVha2VyIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzcGVha2luZycsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL3RoaXMucm9vbS5hZGRQYXJ0aWNpcGFudFNwZWFraW5nKHBhcnRpY2lwYW50SWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucm9vbS5lbWl0RXZlbnQoJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uOiB0aGlzLmNvbm5lY3Rpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbUlkOiB0aGlzLnN0cmVhbUlkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3N0b3BwZWRfc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy90aGlzLnJvb20ucmVtb3ZlUGFydGljaXBhbnRTcGVha2luZyhwYXJ0aWNpcGFudElkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJvb20uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uOiB0aGlzLmNvbm5lY3Rpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbUlkOiB0aGlzLnN0cmVhbUlkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghIXRoaXMudmlkZW8pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gbGV0IHRodW1ibmFpbElkID0gdGhpcy52aWRlby50aHVtYjtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy52aWRlby5vbmNhbnBsYXkgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5sb2NhbCAmJiB0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiWW91ciBvd24gcmVtb3RlICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW1JZCArIFwiXSB2aWRlbyBpcyBub3cgcGxheWluZ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncmVtb3RlLXZpZGVvLWlzLXBsYXlpbmcnLCBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50OiB0aGlzLnZpZGVvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghdGhpcy5sb2NhbCAmJiAhdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyBcIl0gdmlkZW8gaXMgbm93IHBsYXlpbmdcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvLWlzLXBsYXlpbmcnLCBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50OiB0aGlzLnZpZGVvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy9zaG93KHRodW1ibmFpbElkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vdGhpcy5oaWRlU3Bpbm5lcih0aGlzLnN0cmVhbUlkKTtcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5yb29tLmVtaXRFdmVudCgnc3RyZWFtLXN1YnNjcmliZWQnLCBbe1xuICAgICAgICAgICAgICAgICAgICBzdHJlYW06IHRoaXNcbiAgICAgICAgICAgICAgICB9XSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG5cbiAgICAgICAgfSwgZXJyb3IgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcih0aGlzLnN0cmVhbUlkICsgXCI6IEVycm9yIHNldHRpbmcgU0RQIHRvIHRoZSBwZWVyIGNvbm5lY3Rpb246IFwiXG4gICAgICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB1bnB1Ymxpc2goKSB7XG4gICAgICAgIGlmICh0aGlzLndwKSB7XG4gICAgICAgICAgICB0aGlzLndwLmRpc3Bvc2UoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICh0aGlzLm1lZGlhU3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goZnVuY3Rpb24gKHRyYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AgJiYgdHJhY2suc3RvcCgpXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaChmdW5jdGlvbiAodHJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgdHJhY2suc3RvcCAmJiB0cmFjay5zdG9wKClcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuc3BlZWNoRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQuc3RvcCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZS5pbmZvKHRoaXMuc3RyZWFtSWQgKyBcIjogU3RyZWFtICdcIiArIHRoaXMuc3RyZWFtSWQgKyBcIicgdW5wdWJsaXNoZWRcIik7XG4gICAgfVxuXG4gICAgZGlzcG9zZSgpIHtcblxuICAgICAgICBmdW5jdGlvbiBkaXNwb3NlRWxlbWVudChlbGVtZW50KSB7XG4gICAgICAgICAgICBpZiAoZWxlbWVudCAmJiBlbGVtZW50LnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICBlbGVtZW50LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZWxlbWVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBkaXNwb3NlRWxlbWVudChcInByb2dyZXNzLVwiICsgdGhpcy5zdHJlYW1JZCk7XG5cbiAgICAgICAgaWYgKHRoaXMud3ApIHtcbiAgICAgICAgICAgIHRoaXMud3AuZGlzcG9zZSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHRoaXMubWVkaWFTdHJlYW0pIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKCkuZm9yRWFjaChmdW5jdGlvbiAodHJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgdHJhY2suc3RvcCAmJiB0cmFjay5zdG9wKClcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKGZ1bmN0aW9uICh0cmFjaykge1xuICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wICYmIHRyYWNrLnN0b3AoKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnN0b3BXZWJSdGNTdGF0cygpO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbygodGhpcy5sb2NhbCA/IFwiTG9jYWwgXCIgOiBcIlJlbW90ZSBcIikgKyBcIidTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW1JZCArIFwiXScgaGFzIGJlZW4gc3VjY2VzZnVsbHkgZGlzcG9zZWRcIik7XG4gICAgfVxuXG4gICAgY29uZmlndXJlU2NyZWVuT3B0aW9ucyhvcHRpb25zOiBPdXRib3VuZFN0cmVhbU9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5vdXRib3VuZE9wdGlvbnMgPSBvcHRpb25zO1xuICAgICAgICB0aGlzLnN0cmVhbUlkID0gXCJTQ1JFRU5cIjtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRXZWJSdGNTdGF0cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy53ZWJSdGNTdGF0cyA9IG5ldyBXZWJSdGNTdGF0cyh0aGlzKTtcbiAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5pbml0V2ViUnRjU3RhdHMoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0b3BXZWJSdGNTdGF0cygpIHtcbiAgICAgICAgaWYgKHRoaXMud2ViUnRjU3RhdHMgIT0gbnVsbCAmJiB0aGlzLndlYlJ0Y1N0YXRzLmlzRW5hYmxlZCgpKSB7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzLnN0b3BXZWJSdGNTdGF0cygpO1xuICAgICAgICB9XG4gICAgfVxuXG59XG4iLCJpbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgKiBhcyBhZGFwdGVyIGZyb20gJ3dlYnJ0Yy1hZGFwdGVyJztcbmltcG9ydCAqIGFzIERldGVjdFJUQyBmcm9tICcuLi9LdXJlbnRvVXRpbHMvRGV0ZWN0UlRDJztcblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1N0YXRzIHtcblxuICAgIHByaXZhdGUgd2ViUnRjU3RhdHNFbmFibGVkOiBib29sZWFuID0gZmFsc2U7XG4gICAgcHJpdmF0ZSB3ZWJSdGNTdGF0c0ludGVydmFsSWQ6IG51bWJlcjtcbiAgICBwcml2YXRlIHN0YXRzSW50ZXJ2YWw6IG51bWJlciA9IDE7XG4gICAgcHJpdmF0ZSBzdGF0czogYW55ID0ge1xuICAgICAgICBcImluYm91bmRcIjoge1xuICAgICAgICAgICAgXCJhdWRpb1wiOiB7XG4gICAgICAgICAgICAgICAgXCJieXRlc1JlY2VpdmVkXCI6IDAsXG4gICAgICAgICAgICAgICAgXCJwYWNrZXRzUmVjZWl2ZWRcIjogMCxcbiAgICAgICAgICAgICAgICBcInBhY2tldHNMb3N0XCI6IDBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBcInZpZGVvXCI6IHtcbiAgICAgICAgICAgICAgICBcImJ5dGVzUmVjZWl2ZWRcIjogMCxcbiAgICAgICAgICAgICAgICBcInBhY2tldHNSZWNlaXZlZFwiOiAwLFxuICAgICAgICAgICAgICAgIFwicGFja2V0c0xvc3RcIjogMCxcbiAgICAgICAgICAgICAgICBcImZyYW1lc0RlY29kZWRcIjogMCxcbiAgICAgICAgICAgICAgICBcIm5hY2tDb3VudFwiOiAwXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwib3V0Ym91bmRcIjoge1xuICAgICAgICAgICAgXCJhdWRpb1wiOiB7XG4gICAgICAgICAgICAgICAgXCJieXRlc1NlbnRcIjogMCxcbiAgICAgICAgICAgICAgICBcInBhY2tldHNTZW50XCI6IDAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCJ2aWRlb1wiOiB7XG4gICAgICAgICAgICAgICAgXCJieXRlc1NlbnRcIjogMCxcbiAgICAgICAgICAgICAgICBcInBhY2tldHNTZW50XCI6IDAsXG4gICAgICAgICAgICAgICAgXCJmcmFtZXNFbmNvZGVkXCI6IDAsXG4gICAgICAgICAgICAgICAgXCJuYWNrQ291bnRcIjogMFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBzdHJlYW06IFN0cmVhbSkgeyB9XG5cbiAgICBwdWJsaWMgaXNFbmFibGVkKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNTdGF0c0VuYWJsZWQ7XG4gICAgfVxuXG4gICAgcHVibGljIGluaXRXZWJSdGNTdGF0cygpOiB2b2lkIHtcblxuICAgICAgICBsZXQgZWxhc3Rlc3RJbnN0cnVtZW50YXRpb24gPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnZWxhc3Rlc3QtaW5zdHJ1bWVudGF0aW9uJyk7XG5cbiAgICAgICAgaWYgKGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uKSB7XG4gICAgICAgICAgICAvLyBFbGFzVGVzdCBpbnN0cnVtZW50YXRpb24gb2JqZWN0IGZvdW5kIGluIGxvY2FsIHN0b3JhZ2VcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiV2ViUnRjIHN0YXRzIGVuYWJsZWQgZm9yIHN0cmVhbSBcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgXCIgb2YgY29ubmVjdGlvbiBcIiArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0VuYWJsZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBsZXQgaW5zdHJ1bWVudGF0aW9uID0gSlNPTi5wYXJzZShlbGFzdGVzdEluc3RydW1lbnRhdGlvbik7XG4gICAgICAgICAgICB0aGlzLnN0YXRzSW50ZXJ2YWwgPSBpbnN0cnVtZW50YXRpb24ud2VicnRjLmludGVydmFsOyAgLy8gSW50ZXJ2YWwgaW4gc2Vjb25kc1xuXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJsb2NhbFN0b3JhZ2UgaXRlbTogXCIgKyBKU09OLnN0cmluZ2lmeShpbnN0cnVtZW50YXRpb24pKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0ludGVydmFsSWQgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kU3RhdHNUb0h0dHBFbmRwb2ludChpbnN0cnVtZW50YXRpb24pO1xuICAgICAgICAgICAgfSwgdGhpcy5zdGF0c0ludGVydmFsICogMTAwMCk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGUuZGVidWcoXCJXZWJSdGMgc3RhdHMgbm90IGVuYWJsZWRcIik7XG4gICAgfVxuXG4gICAgcHVibGljIHN0b3BXZWJSdGNTdGF0cygpIHtcbiAgICAgICAgaWYgKHRoaXMud2ViUnRjU3RhdHNFbmFibGVkKSB7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHRoaXMud2ViUnRjU3RhdHNJbnRlcnZhbElkKTtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIldlYlJ0YyBzdGF0cyBzdG9wcGVkIGZvciBkaXNwb3NlZCBzdHJlYW0gXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArIFwiIG9mIGNvbm5lY3Rpb24gXCIgKyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHNlbmRTdGF0c1RvSHR0cEVuZHBvaW50KGluc3RydW1lbnRhdGlvbik6IHZvaWQge1xuXG4gICAgICAgIGxldCBzZW5kUG9zdCA9IChqc29uKSA9PiB7XG4gICAgICAgICAgICBsZXQgaHR0cDogWE1MSHR0cFJlcXVlc3QgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgIGxldCB1cmw6IHN0cmluZyA9IGluc3RydW1lbnRhdGlvbi53ZWJydGMuaHR0cEVuZHBvaW50O1xuICAgICAgICAgICAgaHR0cC5vcGVuKFwiUE9TVFwiLCB1cmwsIHRydWUpO1xuXG4gICAgICAgICAgICBodHRwLnNldFJlcXVlc3RIZWFkZXIoXCJDb250ZW50LXR5cGVcIiwgXCJhcHBsaWNhdGlvbi9qc29uXCIpO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHsgLy8gQ2FsbCBhIGZ1bmN0aW9uIHdoZW4gdGhlIHN0YXRlIGNoYW5nZXMuXG4gICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PSA0ICYmIGh0dHAuc3RhdHVzID09IDIwMCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIldlYlJ0YyBzdGF0cyBzdWNjZXNmdWxseSBzZW50IHRvIFwiICsgdXJsICsgXCIgZm9yIHN0cmVhbSBcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgXCIgb2YgY29ubmVjdGlvbiBcIiArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBodHRwLnNlbmQoanNvbik7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgZiA9IChzdGF0cykgPT4ge1xuXG4gICAgICAgICAgICBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIubmFtZSA9PT0gJ0ZpcmVmb3gnKSB7XG4gICAgICAgICAgICAgICAgc3RhdHMuZm9yRWFjaCgoc3RhdCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGxldCBqc29uID0ge307XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKChzdGF0LnR5cGUgPT09ICdpbmJvdW5kLXJ0cCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXZvaWQgZmlyZWZveCBlbXB0eSBvdXRib3VuZC1ydHAgc3RhdGlzdGljc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQubmFja0NvdW50ICE9IG51bGwgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlzUmVtb3RlID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaWQuc3RhcnRzV2l0aCgnaW5ib3VuZCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5yZW1vdGVJZC5zdGFydHNXaXRoKCdpbmJvdW5kJylcbiAgICAgICAgICAgICAgICAgICAgICAgICkpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG1ldHJpY0lkID0gJ3dlYnJ0Y19pbmJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBqaXR0ZXIgPSBzdGF0LmppdHRlciAqIDEwMDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiYnl0ZXNSZWNlaXZlZFwiOiAoc3RhdC5ieXRlc1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImppdHRlclwiOiBqaXR0ZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJwYWNrZXRzUmVjZWl2ZWRcIjogKHN0YXQucGFja2V0c1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwicGFja2V0c0xvc3RcIjogKHN0YXQucGFja2V0c0xvc3QgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB1bml0cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImJ5dGVzUmVjZWl2ZWRcIjogXCJieXRlc1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiaml0dGVyXCI6IFwibXNcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInBhY2tldHNSZWNlaXZlZFwiOiBcInBhY2tldHNcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInBhY2tldHNMb3N0XCI6IFwicGFja2V0c1wiXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snZnJhbWVzRGVjb2RlZCddID0gKHN0YXQuZnJhbWVzRGVjb2RlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5mcmFtZXNEZWNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWyduYWNrQ291bnQnXSA9IChzdGF0Lm5hY2tDb3VudCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWydmcmFtZXNEZWNvZGVkJ10gPSBcImZyYW1lc1wiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWyduYWNrQ291bnQnXSA9IFwicGFja2V0c1wiO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQgPSBzdGF0LmZyYW1lc0RlY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCA9IHN0YXQubmFja0NvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQgPSBzdGF0LmJ5dGVzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCA9IHN0YXQucGFja2V0c1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzTG9zdCA9IHN0YXQucGFja2V0c0xvc3Q7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJAdGltZXN0YW1wXCI6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZXhlY1wiOiBpbnN0cnVtZW50YXRpb24uZXhlYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImNvbXBvbmVudFwiOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwic3RyZWFtXCI6IFwid2ViUnRjXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJ0eXBlXCI6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwic3RyZWFtX3R5cGVcIjogXCJjb21wb3NlZF9tZXRyaWNzXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJ1bml0c1wiOiB1bml0c1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAganNvblttZXRyaWNJZF0gPSBtZXRyaWNzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgoc3RhdC50eXBlID09PSAnb3V0Ym91bmQtcnRwJykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBdm9pZCBmaXJlZm94IGVtcHR5IGluYm91bmQtcnRwIHN0YXRpc3RpY3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlzUmVtb3RlID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaWQudG9Mb3dlckNhc2UoKS5pbmNsdWRlcygnb3V0Ym91bmQnKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgbWV0cmljSWQgPSAnd2VicnRjX291dGJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcblxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG1ldHJpY3MgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJieXRlc1NlbnRcIjogKHN0YXQuYnl0ZXNTZW50IC0gdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInBhY2tldHNTZW50XCI6IChzdGF0LnBhY2tldHNTZW50IC0gdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiYnl0ZXNTZW50XCI6IFwiYnl0ZXNcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInBhY2tldHNTZW50XCI6IFwicGFja2V0c1wiXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snZnJhbWVzRW5jb2RlZCddID0gKHN0YXQuZnJhbWVzRW5jb2RlZCAtIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0VuY29kZWQnXSA9IFwiZnJhbWVzXCI7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kLnZpZGVvLmZyYW1lc0VuY29kZWQgPSBzdGF0LmZyYW1lc0VuY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCA9IHN0YXQuYnl0ZXNTZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1NlbnQgPSBzdGF0LnBhY2tldHNTZW50O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiQHRpbWVzdGFtcFwiOiBuZXcgRGF0ZShzdGF0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImV4ZWNcIjogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJjb21wb25lbnRcIjogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInN0cmVhbVwiOiBcIndlYlJ0Y1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwidHlwZVwiOiBtZXRyaWNJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInN0cmVhbV90eXBlXCI6IFwiY29tcG9zZWRfbWV0cmljc1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwidW5pdHNcIjogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgc2VuZFBvc3QoSlNPTi5zdHJpbmdpZnkoanNvbikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKERldGVjdFJUQy5icm93c2VyLm5hbWUgPT09ICdDaHJvbWUnKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHN0YXRzKSkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgc3RhdCA9IHN0YXRzW2tleV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGF0LnR5cGUgPT09ICdzc3JjJykge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQganNvbiA9IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJ2J5dGVzUmVjZWl2ZWQnIGluIHN0YXQgJiYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ2F1ZGlvJyAmJiAnYXVkaW9PdXRwdXRMZXZlbCcgaW4gc3RhdCkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycgJiYgJ3FwU3VtJyBpbiBzdGF0KVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluYm91bmQtcnRwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG1ldHJpY0lkID0gJ3dlYnJ0Y19pbmJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImJ5dGVzUmVjZWl2ZWRcIjogKHN0YXQuYnl0ZXNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiaml0dGVyXCI6IHN0YXQuZ29vZ0ppdHRlckJ1ZmZlck1zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInBhY2tldHNSZWNlaXZlZFwiOiAoc3RhdC5wYWNrZXRzUmVjZWl2ZWQgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwicGFja2V0c0xvc3RcIjogKHN0YXQucGFja2V0c0xvc3QgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImJ5dGVzUmVjZWl2ZWRcIjogXCJieXRlc1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImppdHRlclwiOiBcIm1zXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwicGFja2V0c1JlY2VpdmVkXCI6IFwicGFja2V0c1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInBhY2tldHNMb3N0XCI6IFwicGFja2V0c1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snZnJhbWVzRGVjb2RlZCddID0gKHN0YXQuZnJhbWVzRGVjb2RlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5mcmFtZXNEZWNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snbmFja0NvdW50J10gPSAoc3RhdC5nb29nTmFja3NTZW50IC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWydmcmFtZXNEZWNvZGVkJ10gPSBcImZyYW1lc1wiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snbmFja0NvdW50J10gPSBcInBhY2tldHNcIjtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCA9IHN0YXQuZnJhbWVzRGVjb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCA9IHN0YXQuZ29vZ05hY2tzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQgPSBzdGF0LmJ5dGVzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQgPSBzdGF0LnBhY2tldHNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0ID0gc3RhdC5wYWNrZXRzTG9zdDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiQHRpbWVzdGFtcFwiOiBuZXcgRGF0ZShzdGF0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJleGVjXCI6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImNvbXBvbmVudFwiOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInN0cmVhbVwiOiBcIndlYlJ0Y1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInR5cGVcIjogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwic3RyZWFtX3R5cGVcIjogXCJjb21wb3NlZF9tZXRyaWNzXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwidW5pdHNcIjogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAganNvblttZXRyaWNJZF0gPSBtZXRyaWNzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VuZFBvc3QoSlNPTi5zdHJpbmdpZnkoanNvbikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgnYnl0ZXNTZW50JyBpbiBzdGF0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb3V0Ym91bmQtcnRwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG1ldHJpY0lkID0gJ3dlYnJ0Y19vdXRib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJieXRlc1NlbnRcIjogKHN0YXQuYnl0ZXNTZW50IC0gdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJwYWNrZXRzU2VudFwiOiAoc3RhdC5wYWNrZXRzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImJ5dGVzU2VudFwiOiBcImJ5dGVzXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwicGFja2V0c1NlbnRcIjogXCJwYWNrZXRzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNFbmNvZGVkJ10gPSAoc3RhdC5mcmFtZXNFbmNvZGVkIC0gdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0VuY29kZWQnXSA9IFwiZnJhbWVzXCI7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkID0gc3RhdC5mcmFtZXNFbmNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCA9IHN0YXQuYnl0ZXNTZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50ID0gc3RhdC5wYWNrZXRzU2VudDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiQHRpbWVzdGFtcFwiOiBuZXcgRGF0ZShzdGF0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJleGVjXCI6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImNvbXBvbmVudFwiOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInN0cmVhbVwiOiBcIndlYlJ0Y1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInR5cGVcIjogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwic3RyZWFtX3R5cGVcIjogXCJjb21wb3NlZF9tZXRyaWNzXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwidW5pdHNcIjogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAganNvblttZXRyaWNJZF0gPSBtZXRyaWNzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VuZFBvc3QoSlNPTi5zdHJpbmdpZnkoanNvbikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMuZ2V0U3RhdHNBZ25vc3RpYyh0aGlzLnN0cmVhbS5nZXRSVENQZWVyQ29ubmVjdGlvbigpLCBudWxsLCBmLCAoZXJyb3IpID0+IHsgY29uc29sZS5sb2coZXJyb3IpIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhbmRhcmRpemVSZXBvcnQocmVzcG9uc2UpIHtcbiAgICAgICAgaWYgKERldGVjdFJUQy5icm93c2VyLm5hbWUgPT09ICdGaXJlZm94Jykge1xuICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHN0YW5kYXJkUmVwb3J0ID0ge307XG4gICAgICAgIHJlc3BvbnNlLnJlc3VsdCgpLmZvckVhY2goZnVuY3Rpb24gKHJlcG9ydCkge1xuICAgICAgICAgICAgdmFyIHN0YW5kYXJkU3RhdHMgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IHJlcG9ydC5pZCxcbiAgICAgICAgICAgICAgICB0aW1lc3RhbXA6IHJlcG9ydC50aW1lc3RhbXAsXG4gICAgICAgICAgICAgICAgdHlwZTogcmVwb3J0LnR5cGVcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXBvcnQubmFtZXMoKS5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgICAgICAgICAgc3RhbmRhcmRTdGF0c1tuYW1lXSA9IHJlcG9ydC5zdGF0KG5hbWUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzdGFuZGFyZFJlcG9ydFtzdGFuZGFyZFN0YXRzLmlkXSA9IHN0YW5kYXJkU3RhdHM7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBzdGFuZGFyZFJlcG9ydDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFN0YXRzQWdub3N0aWMocGMsIHNlbGVjdG9yLCBzdWNjZXNzQ2IsIGZhaWx1cmVDYikge1xuICAgICAgICBpZiAoRGV0ZWN0UlRDLmJyb3dzZXIubmFtZSA9PT0gJ0ZpcmVmb3gnKSB7XG4gICAgICAgICAgICAvLyBnZXRTdGF0cyB0YWtlcyBhcmdzIGluIGRpZmZlcmVudCBvcmRlciBpbiBDaHJvbWUgYW5kIEZpcmVmb3hcbiAgICAgICAgICAgIHJldHVybiBwYy5nZXRTdGF0cyhzZWxlY3RvciwgKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgdmFyIHJlcG9ydCA9IHRoaXMuc3RhbmRhcmRpemVSZXBvcnQocmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYihyZXBvcnQpO1xuICAgICAgICAgICAgfSwgZmFpbHVyZUNiKTtcbiAgICAgICAgfSBlbHNlIGlmIChEZXRlY3RSVEMuYnJvd3Nlci5uYW1lID09PSAnQ2hyb21lJykge1xuICAgICAgICAgICAgLy8gSW4gQ2hyb21lLCB0aGUgZmlyc3QgdHdvIGFyZ3VtZW50cyBhcmUgcmV2ZXJzZWRcbiAgICAgICAgICAgIHJldHVybiBwYy5nZXRTdGF0cygocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICB2YXIgcmVwb3J0ID0gdGhpcy5zdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NiKHJlcG9ydCk7XG4gICAgICAgICAgICB9LCBzZWxlY3RvciwgZmFpbHVyZUNiKTtcbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8vIExhc3QgdGltZSB1cGRhdGVkIGF0IEZlYiAxNiwgMjAxNywgMDg6MzI6MjNcblxuLy8gTGF0ZXN0IGZpbGUgY2FuIGJlIGZvdW5kIGhlcmU6IGh0dHBzOi8vY2RuLndlYnJ0Yy1leHBlcmltZW50LmNvbS9nZXRTY3JlZW5JZC5qc1xuXG4vLyBNdWF6IEtoYW4gICAgICAgICAtIHd3dy5NdWF6S2hhbi5jb21cbi8vIE1JVCBMaWNlbnNlICAgICAgIC0gd3d3LldlYlJUQy1FeHBlcmltZW50LmNvbS9saWNlbmNlXG4vLyBEb2N1bWVudGF0aW9uICAgICAtIGh0dHBzOi8vZ2l0aHViLmNvbS9tdWF6LWtoYW4vZ2V0U2NyZWVuSWQuXG5cbi8vIF9fX19fX19fX19fX19fXG4vLyBnZXRTY3JlZW5JZC5qc1xuXG4vKlxuZ2V0U2NyZWVuSWQoZnVuY3Rpb24gKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuX2NvbnN0cmFpbnRzKSB7XG4gICAgLy8gZXJyb3IgICAgPT0gbnVsbCB8fCAncGVybWlzc2lvbi1kZW5pZWQnIHx8ICdub3QtaW5zdGFsbGVkJyB8fCAnaW5zdGFsbGVkLWRpc2FibGVkJyB8fCAnbm90LWNocm9tZSdcbiAgICAvLyBzb3VyY2VJZCA9PSBudWxsIHx8ICdzdHJpbmcnIHx8ICdmaXJlZm94J1xuICAgIFxuICAgIGlmKHNvdXJjZUlkID09ICdmaXJlZm94Jykge1xuICAgICAgICBuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKHNjcmVlbl9jb25zdHJhaW50cywgb25TdWNjZXNzLCBvbkZhaWx1cmUpO1xuICAgIH1cbiAgICBlbHNlIG5hdmlnYXRvci53ZWJraXRHZXRVc2VyTWVkaWEoc2NyZWVuX2NvbnN0cmFpbnRzLCBvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG59KTtcbiovXG5cbndpbmRvdy5nZXRTY3JlZW5JZCA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIC8vIGZvciBGaXJlZm94OlxuICAgIC8vIHNvdXJjZUlkID09ICdmaXJlZm94J1xuICAgIC8vIHNjcmVlbl9jb25zdHJhaW50cyA9IHsuLi59XG4gICAgaWYgKCEhbmF2aWdhdG9yLm1vekdldFVzZXJNZWRpYSkge1xuICAgICAgICBjYWxsYmFjayhudWxsLCAnZmlyZWZveCcsIHtcbiAgICAgICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICAgICAgbW96TWVkaWFTb3VyY2U6ICd3aW5kb3cnLFxuICAgICAgICAgICAgICAgIG1lZGlhU291cmNlOiAnd2luZG93J1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG5cbiAgICBmdW5jdGlvbiBvbklGcmFtZUNhbGxiYWNrKGV2ZW50KSB7XG4gICAgICAgIGlmICghZXZlbnQuZGF0YSkgcmV0dXJuO1xuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQpIHtcbiAgICAgICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQgPT09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soJ3Blcm1pc3Npb24tZGVuaWVkJyk7XG4gICAgICAgICAgICB9IGVsc2UgY2FsbGJhY2sobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBnZXRTY3JlZW5Db25zdHJhaW50cyhudWxsLCBldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykge1xuICAgICAgICAgICAgY2FsbGJhY2soZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMsIG51bGwsIGdldFNjcmVlbkNvbnN0cmFpbnRzKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0aGlzIGV2ZW50IGxpc3RlbmVyIGlzIG5vIG1vcmUgbmVlZGVkXG4gICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgfVxuXG4gICAgc2V0VGltZW91dChwb3N0R2V0U291cmNlSWRNZXNzYWdlLCAxMDApO1xufTtcblxuZnVuY3Rpb24gZ2V0U2NyZWVuQ29uc3RyYWludHMoZXJyb3IsIHNvdXJjZUlkKSB7XG4gICAgdmFyIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgYXVkaW86IGZhbHNlLFxuICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgbWFuZGF0b3J5OiB7XG4gICAgICAgICAgICAgICAgY2hyb21lTWVkaWFTb3VyY2U6IGVycm9yID8gJ3NjcmVlbicgOiAnZGVza3RvcCcsXG4gICAgICAgICAgICAgICAgbWF4V2lkdGg6IHdpbmRvdy5zY3JlZW4ud2lkdGggPiAxOTIwID8gd2luZG93LnNjcmVlbi53aWR0aCA6IDE5MjAsXG4gICAgICAgICAgICAgICAgbWF4SGVpZ2h0OiB3aW5kb3cuc2NyZWVuLmhlaWdodCA+IDEwODAgPyB3aW5kb3cuc2NyZWVuLmhlaWdodCA6IDEwODBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcHRpb25hbDogW11cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBpZiAoc291cmNlSWQpIHtcbiAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNjcmVlbl9jb25zdHJhaW50cztcbn1cblxuZnVuY3Rpb24gcG9zdEdldFNvdXJjZUlkTWVzc2FnZSgpIHtcbiAgICBpZiAoIWlmcmFtZSkge1xuICAgICAgICBsb2FkSUZyYW1lKHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFpZnJhbWUuaXNMb2FkZWQpIHtcbiAgICAgICAgc2V0VGltZW91dChwb3N0R2V0U291cmNlSWRNZXNzYWdlLCAxMDApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICBjYXB0dXJlU291cmNlSWQ6IHRydWVcbiAgICB9LCAnKicpO1xufVxuXG52YXIgaWZyYW1lO1xuXG4vLyB0aGlzIGZ1bmN0aW9uIGlzIHVzZWQgaW4gUlRDTXVsdGlDb25uZWN0aW9uIHYzXG53aW5kb3cuZ2V0U2NyZWVuQ29uc3RyYWludHMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBsb2FkSUZyYW1lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZ2V0U2NyZWVuSWQoZnVuY3Rpb24gKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuX2NvbnN0cmFpbnRzKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBsb2FkSUZyYW1lKGxvYWRDYWxsYmFjaykge1xuICAgIGlmIChpZnJhbWUpIHtcbiAgICAgICAgbG9hZENhbGxiYWNrKCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpZnJhbWUnKTtcbiAgICBpZnJhbWUub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZnJhbWUuaXNMb2FkZWQgPSB0cnVlO1xuXG4gICAgICAgIGxvYWRDYWxsYmFjaygpO1xuICAgIH07XG4gICAgaWZyYW1lLnNyYyA9ICdodHRwczovL3d3dy53ZWJydGMtZXhwZXJpbWVudC5jb20vZ2V0U291cmNlSWQvJzsgLy8gaHR0cHM6Ly93d3d3LnlvdXJkb21haW4uY29tL2dldFNjcmVlbklkLmh0bWxcbiAgICBpZnJhbWUuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAoZG9jdW1lbnQuYm9keSB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLmFwcGVuZENoaWxkKGlmcmFtZSk7XG59XG5cbndpbmRvdy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAvLyBmb3IgRmlyZWZveDpcbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZW5hYmxlZCcpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0aGlzIGV2ZW50IGxpc3RlbmVyIGlzIG5vIG1vcmUgbmVlZGVkXG4gICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgfVxuXG4gICAgc2V0VGltZW91dChwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSwgMTAwKTtcbn07XG5cbmZ1bmN0aW9uIHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlKCkge1xuICAgIGlmICghaWZyYW1lKSB7XG4gICAgICAgIGxvYWRJRnJhbWUocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFpZnJhbWUuaXNMb2FkZWQpIHtcbiAgICAgICAgc2V0VGltZW91dChwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSwgMTAwKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzOiB0cnVlXG4gICAgfSwgJyonKTtcbn1cblxuZXhwb3J0cy5nZXRTY3JlZW5JZCA9IGdldFNjcmVlbklkO1xuZXhwb3J0cy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXM7XG4iXX0= diff --git a/openvidu-recording-node/public/style.css b/openvidu-recording-node/public/style.css new file mode 100644 index 00000000..9a832e9f --- /dev/null +++ b/openvidu-recording-node/public/style.css @@ -0,0 +1,399 @@ +html { + position: relative; + min-height: 100%; +} + +body { + 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; + height: 100%; + margin-top: -70px; +} + +.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; + margin-top: 100px; +} + +#session-header { + margin-bottom: 20px; + height: 8%; + margin-top: 70px; +} + +#session-header form { + display: inline; +} + +#session-title { + display: inline-block; +} + +#buttonLeaveSession { + float: right; + margin-top: 20px; +} + +#video-container { + width: 100%; + max-height: 45%; + display: inline-block; + overflow: hidden; +} + +#video-container video.two{ + width: 50%; +} + +#video-container video.three{ + width: 33.33%; +} + +#video-container video.four{ + width: 25%; +} + +#video-container div { + position: absolute; + display: inline-flex; + margin-left: calc(-50% + 15px); +} + +#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; + max-height: 100%; + object-fit: cover; +} + +#session { + height: 100%; + padding-bottom: 80px; +} + +#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; +} + +#recording-btns { + display: flow-root; + padding-left: 15px; + padding-top: 20px; + width: 100%; + height: 40%; +} + +#recording-btns input { + margin-top: 5px; +} + +#recording-btns #btns { + margin-top: 5px; +} + +#recording-btns #text-area { + display: inline-block; + width: 100%; + height: 80%; + margin-top: 20px; +} + +/* 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-recording-node/server.js b/openvidu-recording-node/server.js new file mode 100644 index 00000000..d0f20d24 --- /dev/null +++ b/openvidu-recording-node/server.js @@ -0,0 +1,239 @@ +/* CONFIGURATION */ + +var OpenVidu = require('openvidu-node-client').OpenVidu; +var Session = require('openvidu-node-client').Session; +var OpenViduRole = require('openvidu-node-client').OpenViduRole; +var TokenOptions = require('openvidu-node-client').TokenOptions; + +// 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 + +// 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); + +// 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]; + +// OpenVidu object to ask openvidu-server for sessionId and token +var OV = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET); + +// Collection to pair session names and OpenVidu Session objects +var mapSessionNameSession = {}; +// Collection to pair sessionId's (identifiers of Session objects) and tokens +var mapSessionIdTokens = {}; + +console.log("App listening on port 5000"); + + + + +/* Session API */ + +// Get sessionId and token (add new user to session) +app.post('/api/get-sessionid-token', function (req, res) { + // The video-call to connect ("TUTORIAL") + var sessionName = req.body.session; + + console.log("Getting sessionId and token | {sessionName}={" + sessionName + "}"); + + // Role associated to this user + var role = OpenViduRole.PUBLISHER; + + // Build tokenOptions object with the serverData and the role + var tokenOptions = new TokenOptions.Builder() + .role(role) + .build(); + + if (mapSessionNameSession[sessionName]) { + // Session already exists: return existing sessionId and a new token + console.log('Existing session ' + sessionName); + + // Get the existing Session from the collection + var mySession = mapSessionNameSession[sessionName]; + + // Generate a new token asynchronously with the recently created tokenOptions + mySession.generateToken(tokenOptions, function (token) { + + // Get the existing sessionId + mySession.getSessionId(function (sessionId) { + + // Store the new token in the collection of tokens + mapSessionIdTokens[sessionId].push(token); + + // Return the sessionId and token to the client + console.log('SESSIONID: ' + sessionId); + console.log('TOKEN: ' + token); + res.status(200).send({ + 0: sessionId, + 1: token + }); + }); + }); + } else { // New session: return a new sessionId and a new token + console.log('New session ' + sessionName); + + // Create a new OpenVidu Session + var mySession = OV.createSession(); + + // Get the sessionId asynchronously + mySession.getSessionId(function (sessionId) { + + // Store the new Session in the collection of Sessions + mapSessionNameSession[sessionName] = mySession; + // Store a new empty array in the collection of tokens + mapSessionIdTokens[sessionId] = []; + + // Generate a new token asynchronously with the recently created tokenOptions + mySession.generateToken(tokenOptions, function (token) { + + // Store the new token in the collection of tokens + mapSessionIdTokens[sessionId].push(token); + + console.log('SESSIONID: ' + sessionId); + console.log('TOKEN: ' + token); + + // Return the sessionId and token to the client + res.status(200).send({ + 0: sessionId, + 1: token + }); + }); + }); + } +}); + +// Remove user from session +app.post('/api/remove-user', function (req, res) { + // 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 + var mySession = mapSessionNameSession[sessionName]; + if (mySession) { + mySession.getSessionId(function (sessionId) { + var tokens = mapSessionIdTokens[sessionId]; + if (tokens) { + var index = tokens.indexOf(token); + + // If the token exists + if (index !== -1) { + // Token removed! + tokens.splice(index, 1); + console.log(sessionName + ': ' + mapSessionIdTokens[sessionId].toString()); + } else { + var msg = 'Problems in the app server: the TOKEN wasn\'t valid'; + console.log(msg); + res.status(500).send(msg); + } + if (mapSessionIdTokens[sessionId].length == 0) { + // Last user left: session must be removed + console.log(sessionName + ' empty!'); + delete mapSessionNameSession[sessionName]; + } + res.status(200).send(); + } else { + var msg = 'Problems in the app server: the SESSIONID wasn\'t valid'; + console.log(msg); + res.status(500).send(msg); + } + }); + } else { + var msg = 'Problems in the app server: the SESSION does not exist'; + console.log(msg); + res.status(500).send(msg); + } +}); + + + + +/* Recording API */ + +// Start session recording +app.post('/api/recording/start', function (req, res) { + // Retrieve params from POST body + var sessionId = req.body.session; + console.log("Starting recording | {sessionId}=" + sessionId); + + OV.startRecording(sessionId) + .then(archive => res.status(200).send(archive)) + .catch(error => res.status(400).send(error.message)); +}); + +// Start session recording +app.post('/api/recording/stop', function (req, res) { + // Retrieve params from POST body + var recordingId = req.body.recording; + console.log("Stoping recording | {recordingId}=" + recordingId); + + OV.stopRecording(recordingId) + .then(archive => res.status(200).send(archive)) + .catch(error => res.status(400).send(error.message)); +}); + +// Start session recording +app.delete('/api/recording/delete', function (req, res) { + // Retrieve params from DELETE body + var recordingId = req.body.recording; + console.log("Deleting recording | {recordingId}=" + recordingId); + + OV.deleteRecording(recordingId) + .then(() => res.status(200).send()) + .catch(error => res.status(400).send(error.message)); +}); + +// Start session recording +app.get('/api/recording/get/:recordingId', function (req, res) { + // Retrieve params from GET url + var recordingId = req.params.recordingId; + console.log("Getting recording | {recordingId}=" + recordingId); + + OV.getRecording(recordingId) + .then(archive => res.status(200).send(archive)) + .catch(error => res.status(400).send(error.message)); +}); + +// Start session recording +app.get('/api/recording/list', function (req, res) { + console.log("Listing recordings"); + + OV.listRecordings() + .then(archives => res.status(200).send(archives)) + .catch(error => res.status(400).send(error.message)); +}); \ No newline at end of file