From 332fafd5df6f6264ef97ab61ed69aa3bace2bf9e Mon Sep 17 00:00:00 2001 From: bustardcelly Date: Fri, 12 Oct 2018 16:24:43 +0200 Subject: [PATCH] subscribe/unsubscribe example. 5.2.1. AF-61 --- package-lock.json | 1619 +- package.json | 2 +- src/page/test/subscribeUnsubscribe/README.md | 156 + src/page/test/subscribeUnsubscribe/index.html | 30 + src/page/test/subscribeUnsubscribe/index.js | 240 + src/page/testbed-menu.html | 1 + src/template/partial/header-scripts.hbs | 2 +- static/lib/red5pro/red5pro-sdk.min.js | 17729 +++++++++++++++- 8 files changed, 19563 insertions(+), 216 deletions(-) create mode 100644 src/page/test/subscribeUnsubscribe/README.md create mode 100644 src/page/test/subscribeUnsubscribe/index.html create mode 100644 src/page/test/subscribeUnsubscribe/index.js diff --git a/package-lock.json b/package-lock.json index 29bef96b..16ee1f9e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,7 +1,8 @@ { "name": "red5pro-html-sdk-testbed", - "version": "4.6.0-RC9", + "version": "5.2.1", "lockfileVersion": 1, + "requires": true, "dependencies": { "acorn": { "version": "5.5.3", @@ -14,6 +15,9 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, + "requires": { + "acorn": "^3.0.4" + }, "dependencies": { "acorn": { "version": "3.3.0", @@ -27,7 +31,11 @@ "version": "4.11.8", "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true + "dev": true, + "requires": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } }, "ajv-keywords": { "version": "1.5.1", @@ -40,12 +48,20 @@ "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -59,7 +75,10 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", - "dev": true + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } }, "ansi-escapes": { "version": "1.4.0", @@ -71,13 +90,19 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } }, "ansi-red": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", - "dev": true + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } }, "ansi-regex": { "version": "2.1.1", @@ -107,7 +132,10 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } }, "arr-diff": { "version": "4.0.0", @@ -155,7 +183,10 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } }, "array-uniq": { "version": "1.0.3", @@ -197,7 +228,12 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + } }, "balanced-match": { "version": "1.0.0", @@ -210,12 +246,24 @@ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, "dependencies": { "define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } } } }, @@ -229,25 +277,49 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, "braces": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.1.tgz", "integrity": "sha512-SO5lYHA3vO6gz66erVvedSCkp7AKWdv6VcQ2N4ysXfPxdAlxAMMAdwegGGcv1Bqwm7naF1hNdk5d6AAIEHV2nQ==", "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "kind-of": "^6.0.2", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, "dependencies": { "define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } } } }, @@ -262,6 +334,10 @@ "resolved": "https://registry.npmjs.org/bump-regex/-/bump-regex-2.9.0.tgz", "integrity": "sha512-o4WC1mKw/kM0zScuOxZKi243lc+/h09b41u2A7HlWbxHsEDsTTZtqDZYkQj65l24J8+9Saahn5ep+EyeqpQoCg==", "dev": true, + "requires": { + "semver": "^5.1.0", + "xtend": "^4.0.1" + }, "dependencies": { "semver": { "version": "5.5.0", @@ -275,13 +351,27 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } }, "caller-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true + "dev": true, + "requires": { + "callsites": "^0.2.0" + } }, "callsites": { "version": "0.2.0", @@ -299,20 +389,35 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true + "dev": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } }, "center-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", "dev": true, - "optional": true + "optional": true, + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } }, "circular-json": { "version": "0.3.3", @@ -325,24 +430,39 @@ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, "dependencies": { "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -351,12 +471,18 @@ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -364,7 +490,12 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } }, "kind-of": { "version": "5.1.0", @@ -378,7 +509,10 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true + "dev": true, + "requires": { + "restore-cursor": "^1.0.1" + } }, "cli-width": { "version": "2.2.0", @@ -392,6 +526,11 @@ "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", "dev": true, "optional": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + }, "dependencies": { "wordwrap": { "version": "0.0.2", @@ -430,7 +569,11 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } }, "color-support": { "version": "1.1.3", @@ -454,7 +597,12 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.1.tgz", "integrity": "sha512-gslSSJx03QKa59cIKqeJO9HQ/WZMotvYJCuaUULrLpjj8oG40kV2Z+gz82pVxlTkOADi4PJxQPPfhl1ELYrrXw==", - "dev": true + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } }, "copy-descriptor": { "version": "0.1.1", @@ -472,13 +620,19 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } }, "d": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "dev": true + "dev": true, + "requires": { + "es5-ext": "^0.10.9" + } }, "dateformat": { "version": "2.2.0", @@ -490,7 +644,10 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true + "dev": true, + "requires": { + "ms": "2.0.0" + } }, "decamelize": { "version": "1.2.0", @@ -514,19 +671,35 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true + "dev": true, + "requires": { + "clone": "^1.0.2" + } }, "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + } }, "del": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "dev": true + "dev": true, + "requires": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + } }, "deprecated": { "version": "0.0.1", @@ -544,13 +717,19 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true + "dev": true, + "requires": { + "esutils": "^2.0.2" + } }, "duplexer2": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", "dev": true, + "requires": { + "readable-stream": "~1.1.9" + }, "dependencies": { "isarray": { "version": "0.0.1", @@ -562,7 +741,13 @@ "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", @@ -577,12 +762,18 @@ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", "dev": true, + "requires": { + "once": "~1.3.0" + }, "dependencies": { "once": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true + "dev": true, + "requires": { + "wrappy": "1" + } } } }, @@ -590,43 +781,80 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "dev": true + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } }, "es5-ext": { "version": "0.10.40", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.40.tgz", "integrity": "sha512-S9Fh3oya5OOvYSNGvPZJ+vyrs6VYpe1IXPowVe3N1OhaiwVaGlwfn3Zf5P5klYcWOA0toIwYQW8XEv/QqhdHvQ==", - "dev": true + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1" + } }, "es6-iterator": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } }, "es6-map": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", - "dev": true + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } }, "es6-set": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" + } }, "es6-symbol": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } }, "es6-weak-map": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", - "dev": true + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.14", + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } }, "escape-string-regexp": { "version": "1.0.5", @@ -638,19 +866,66 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true + "dev": true, + "requires": { + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } }, "eslint": { "version": "3.19.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", - "dev": true + "dev": true, + "requires": { + "babel-code-frame": "^6.16.0", + "chalk": "^1.1.3", + "concat-stream": "^1.5.2", + "debug": "^2.1.1", + "doctrine": "^2.0.0", + "escope": "^3.6.0", + "espree": "^3.4.0", + "esquery": "^1.0.0", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "glob": "^7.0.3", + "globals": "^9.14.0", + "ignore": "^3.2.0", + "imurmurhash": "^0.1.4", + "inquirer": "^0.12.0", + "is-my-json-valid": "^2.10.0", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.5.1", + "json-stable-stringify": "^1.0.0", + "levn": "^0.3.0", + "lodash": "^4.0.0", + "mkdirp": "^0.5.0", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.1", + "pluralize": "^1.2.1", + "progress": "^1.1.8", + "require-uncached": "^1.0.2", + "shelljs": "^0.7.5", + "strip-bom": "^3.0.0", + "strip-json-comments": "~2.0.1", + "table": "^3.7.8", + "text-table": "~0.2.0", + "user-home": "^2.0.0" + } }, "espree": { "version": "3.5.4", "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "dev": true + "dev": true, + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } }, "esprima": { "version": "4.0.0", @@ -662,13 +937,19 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", - "dev": true + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } }, "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } }, "estraverse": { "version": "4.2.0", @@ -686,7 +967,11 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } }, "exit-hook": { "version": "1.1.1", @@ -699,30 +984,51 @@ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, "dependencies": { "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -731,12 +1037,18 @@ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -744,7 +1056,12 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } }, "kind-of": { "version": "5.1.0", @@ -758,7 +1075,10 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } }, "extend": { "version": "3.0.1", @@ -771,12 +1091,19 @@ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, "dependencies": { "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } } } }, @@ -785,18 +1112,34 @@ "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, "dependencies": { "define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } } } }, @@ -804,7 +1147,12 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", - "dev": true + "dev": true, + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "time-stamp": "^1.0.0" + } }, "fast-levenshtein": { "version": "2.0.6", @@ -816,25 +1164,42 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } }, "file-entry-cache": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, "dependencies": { "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } } } }, @@ -848,19 +1213,36 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } }, "findup-sync": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } }, "fined": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", - "dev": true + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + } }, "first-chunk-stream": { "version": "1.0.0", @@ -878,7 +1260,13 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", - "dev": true + "dev": true, + "requires": { + "circular-json": "^0.3.1", + "del": "^2.0.2", + "graceful-fs": "^4.1.2", + "write": "^0.2.1" + } }, "for-in": { "version": "1.0.2", @@ -890,13 +1278,19 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true + "dev": true, + "requires": { + "for-in": "^1.0.1" + } }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } }, "fs.realpath": { "version": "1.0.0", @@ -908,7 +1302,10 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", - "dev": true + "dev": true, + "requires": { + "globule": "~0.1.0" + } }, "generate-function": { "version": "2.0.0", @@ -920,7 +1317,10 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true + "dev": true, + "requires": { + "is-property": "^1.0.0" + } }, "get-stdin": { "version": "4.0.1", @@ -938,19 +1338,41 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } }, "glob-stream": { "version": "3.1.18", "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", "dev": true, + "requires": { + "glob": "^4.3.1", + "glob2base": "^0.0.12", + "minimatch": "^2.0.1", + "ordered-read-streams": "^0.1.0", + "through2": "^0.6.1", + "unique-stream": "^1.0.0" + }, "dependencies": { "glob": { "version": "4.5.3", "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", - "dev": true + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^2.0.1", + "once": "^1.3.0" + } }, "isarray": { "version": "0.0.1", @@ -962,13 +1384,22 @@ "version": "2.0.10", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "dev": true + "dev": true, + "requires": { + "brace-expansion": "^1.0.0" + } }, "readable-stream": { "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", @@ -980,7 +1411,11 @@ "version": "0.6.5", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } } } }, @@ -988,25 +1423,43 @@ "version": "0.0.6", "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true + "dev": true, + "requires": { + "gaze": "^0.5.1" + } }, "glob2base": { "version": "0.0.12", "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "dev": true + "dev": true, + "requires": { + "find-index": "^0.1.1" + } }, "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } }, "global-prefix": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } }, "globals": { "version": "9.18.0", @@ -1018,19 +1471,37 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "dev": true + "dev": true, + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } }, "globule": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", "dev": true, + "requires": { + "glob": "~3.1.21", + "lodash": "~1.0.1", + "minimatch": "~0.2.11" + }, "dependencies": { "glob": { "version": "3.1.21", "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "~1.2.0", + "inherits": "1", + "minimatch": "~0.2.11" + } }, "graceful-fs": { "version": "1.2.3", @@ -1054,7 +1525,11 @@ "version": "0.2.14", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } } } }, @@ -1062,7 +1537,10 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", - "dev": true + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } }, "graceful-fs": { "version": "4.1.11", @@ -1075,6 +1553,21 @@ "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", "dev": true, + "requires": { + "archy": "^1.0.0", + "chalk": "^1.0.0", + "deprecated": "^0.0.1", + "gulp-util": "^3.0.0", + "interpret": "^1.0.0", + "liftoff": "^2.1.0", + "minimist": "^1.1.0", + "orchestrator": "^0.3.0", + "pretty-hrtime": "^1.0.0", + "semver": "^4.1.0", + "tildify": "^1.0.0", + "v8flags": "^2.0.2", + "vinyl-fs": "^0.3.0" + }, "dependencies": { "minimist": { "version": "1.2.0", @@ -1089,6 +1582,13 @@ "resolved": "https://registry.npmjs.org/gulp-bump/-/gulp-bump-2.9.0.tgz", "integrity": "sha512-Cu+QOhwb2Jr2K6yo2u2mh4GWQRpSAMZD/z0v8FStlrOGaqML9u1On7XcyR1pS/PN3HQ9wsd/Ks6AcCQb+j3BgA==", "dev": true, + "requires": { + "bump-regex": "^2.9.0", + "plugin-error": "^0.1.2", + "plugin-log": "^0.1.0", + "semver": "^5.3.0", + "through2": "^2.0.1" + }, "dependencies": { "semver": { "version": "5.5.0", @@ -1103,6 +1603,11 @@ "resolved": "https://registry.npmjs.org/gulp-compile-handlebars/-/gulp-compile-handlebars-0.6.1.tgz", "integrity": "sha1-nMHZy5URBd+uUwko0qkEoU10xdM=", "dev": true, + "requires": { + "gulp-util": "^3.0.3", + "handlebars": ">=3.0.0", + "through2": "^0.6.3" + }, "dependencies": { "isarray": { "version": "0.0.1", @@ -1114,7 +1619,13 @@ "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", @@ -1126,7 +1637,11 @@ "version": "0.6.5", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } } } }, @@ -1141,6 +1656,26 @@ "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", "dev": true, + "requires": { + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", + "replace-ext": "0.0.1", + "through2": "^2.0.0", + "vinyl": "^0.5.0" + }, "dependencies": { "minimist": { "version": "1.2.0", @@ -1160,19 +1695,31 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true + "dev": true, + "requires": { + "glogg": "^1.0.0" + } }, "handlebars": { "version": "4.0.11", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", "dev": true, + "requires": { + "async": "^1.4.0", + "optimist": "^0.6.1", + "source-map": "^0.4.4", + "uglify-js": "^2.6" + }, "dependencies": { "source-map": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } } } }, @@ -1180,31 +1727,49 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } }, "has-gulplog": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } }, "has-values": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, "dependencies": { "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -1212,7 +1777,10 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } }, "hosted-git-info": { "version": "2.6.0", @@ -1236,13 +1804,20 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true + "dev": true, + "requires": { + "repeating": "^2.0.0" + } }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } }, "inherits": { "version": "2.0.3", @@ -1260,7 +1835,22 @@ "version": "0.12.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", - "dev": true + "dev": true, + "requires": { + "ansi-escapes": "^1.1.0", + "ansi-regex": "^2.0.0", + "chalk": "^1.0.0", + "cli-cursor": "^1.0.1", + "cli-width": "^2.0.0", + "figures": "^1.3.5", + "lodash": "^4.3.0", + "readline2": "^1.0.1", + "run-async": "^0.1.0", + "rx-lite": "^3.1.2", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" + } }, "interpret": { "version": "1.1.0", @@ -1272,13 +1862,20 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } }, "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-arrayish": { "version": "0.2.1", @@ -1296,19 +1893,30 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true + "dev": true, + "requires": { + "builtin-modules": "^1.0.0" + } }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } }, "is-extendable": { "version": "0.1.1", @@ -1326,19 +1934,28 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } }, "is-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } }, "is-my-ip-valid": { "version": "1.0.0", @@ -1350,19 +1967,32 @@ "version": "2.17.2", "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", - "dev": true + "dev": true, + "requires": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^4.0.0", + "xtend": "^4.0.0" + } }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -1371,6 +2001,9 @@ "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", "dev": true, + "requires": { + "is-number": "^4.0.0" + }, "dependencies": { "is-number": { "version": "4.0.0", @@ -1390,19 +2023,28 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", - "dev": true + "dev": true, + "requires": { + "is-path-inside": "^1.0.0" + } }, "is-path-inside": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true + "dev": true, + "requires": { + "isobject": "^3.0.1" + } }, "is-property": { "version": "1.0.2", @@ -1414,7 +2056,10 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } }, "is-resolvable": { "version": "1.1.0", @@ -1426,7 +2071,10 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } }, "is-utf8": { "version": "0.2.1", @@ -1468,13 +2116,20 @@ "version": "3.11.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", - "dev": true + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } }, "json-stable-stringify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true + "dev": true, + "requires": { + "jsonify": "~0.0.0" + } }, "jsonify": { "version": "0.0.0", @@ -1505,25 +2160,49 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } }, "liftoff": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", - "dev": true + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^2.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + } }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, "dependencies": { "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } } } }, @@ -1591,7 +2270,10 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true + "dev": true, + "requires": { + "lodash._root": "^3.0.0" + } }, "lodash.isarguments": { "version": "3.1.0", @@ -1609,7 +2291,12 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true + "dev": true, + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } }, "lodash.restparam": { "version": "3.6.1", @@ -1621,13 +2308,28 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true + "dev": true, + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" + } }, "lodash.templatesettings": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" + } }, "longest": { "version": "1.0.1", @@ -1639,7 +2341,11 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } }, "lru-cache": { "version": "2.7.3", @@ -1652,12 +2358,18 @@ "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.0.tgz", "integrity": "sha1-V7713IXSOSO6I3ZzJNjo+PPZaUs=", "dev": true, + "requires": { + "kind-of": "^3.1.0" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -1677,13 +2389,28 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } }, "meow": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, "dependencies": { "minimist": { "version": "1.2.0", @@ -1697,13 +2424,31 @@ "version": "3.1.9", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.9.tgz", "integrity": "sha512-SlIz6sv5UPaAVVFRKodKjCg48EbNoIhgetzfK/Cy0v5U52Z6zB136M8tp0UC9jM53LYbmIRihJszvvqpKkfm9g==", - "dev": true + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } }, "minimist": { "version": "0.0.8", @@ -1716,12 +2461,19 @@ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, "dependencies": { "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } } } }, @@ -1729,7 +2481,10 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true + "dev": true, + "requires": { + "minimist": "0.0.8" + } }, "ms": { "version": "2.0.0", @@ -1741,7 +2496,10 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "dev": true + "dev": true, + "requires": { + "duplexer2": "0.0.2" + } }, "mute-stream": { "version": "0.0.5", @@ -1753,7 +2511,21 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", - "dev": true + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-odd": "^2.0.0", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } }, "natives": { "version": "1.1.1", @@ -1771,7 +2543,13 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "dev": true + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } }, "number-is-nan": { "version": "1.0.1", @@ -1790,30 +2568,49 @@ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, "dependencies": { "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } }, "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, "dependencies": { "kind-of": { "version": "5.1.0", @@ -1827,7 +2624,10 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -1835,31 +2635,50 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true + "dev": true, + "requires": { + "isobject": "^3.0.0" + } }, "object.defaults": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true + "dev": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } }, "object.map": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true + "dev": true, + "requires": { + "isobject": "^3.0.1" + } }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true + "dev": true, + "requires": { + "wrappy": "1" + } }, "onetime": { "version": "1.1.0", @@ -1872,6 +2691,10 @@ "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, "dependencies": { "wordwrap": { "version": "0.0.3", @@ -1885,13 +2708,26 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } }, "orchestrator": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", - "dev": true + "dev": true, + "requires": { + "end-of-stream": "~0.1.5", + "sequencify": "~0.0.7", + "stream-consume": "~0.1.0" + } }, "ordered-read-streams": { "version": "0.1.0", @@ -1909,13 +2745,21 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } }, "parse-passwd": { "version": "1.0.0", @@ -1933,7 +2777,10 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } }, "path-is-absolute": { "version": "1.0.1", @@ -1957,7 +2804,10 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } }, "path-root-regex": { "version": "0.1.2", @@ -1969,7 +2819,12 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } }, "pify": { "version": "2.3.0", @@ -1987,19 +2842,33 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } }, "plugin-error": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", "dev": true, + "requires": { + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" + }, "dependencies": { "arr-diff": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", - "dev": true + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "array-slice": "^0.2.3" + } }, "arr-union": { "version": "2.1.0", @@ -2017,7 +2886,10 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", - "dev": true + "dev": true, + "requires": { + "kind-of": "^1.1.0" + } }, "kind-of": { "version": "1.1.0", @@ -2032,12 +2904,20 @@ "resolved": "https://registry.npmjs.org/plugin-log/-/plugin-log-0.1.0.tgz", "integrity": "sha1-hgSc9qsQgzOYqTHzaJy67nteEzM=", "dev": true, + "requires": { + "chalk": "^1.1.1", + "dateformat": "^1.0.11" + }, "dependencies": { "dateformat": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true + "dev": true, + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.3.0" + } } } }, @@ -2081,43 +2961,77 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } }, "read-pkg-up": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } }, "readable-stream": { "version": "2.3.5", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" + } }, "readline2": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", - "dev": true + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "mute-stream": "0.0.5" + } }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true + "dev": true, + "requires": { + "resolve": "^1.1.6" + } }, "redent": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true + "dev": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } }, "repeat-element": { "version": "1.1.2", @@ -2135,7 +3049,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } }, "replace-ext": { "version": "0.0.1", @@ -2147,19 +3064,30 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true + "dev": true, + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + } }, "resolve": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", - "dev": true + "dev": true, + "requires": { + "path-parse": "^1.0.5" + } }, "resolve-dir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } }, "resolve-from": { "version": "1.0.1", @@ -2177,7 +3105,11 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true + "dev": true, + "requires": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + } }, "ret": { "version": "0.1.15", @@ -2190,19 +3122,28 @@ "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", "dev": true, - "optional": true + "optional": true, + "requires": { + "align-text": "^0.1.1" + } }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true + "dev": true, + "requires": { + "glob": "^7.0.5" + } }, "run-async": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", - "dev": true + "dev": true, + "requires": { + "once": "^1.3.0" + } }, "rx-lite": { "version": "3.1.2", @@ -2220,7 +3161,10 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true + "dev": true, + "requires": { + "ret": "~0.1.10" + } }, "semver": { "version": "4.3.6", @@ -2239,12 +3183,21 @@ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, "dependencies": { "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } } } }, @@ -2252,7 +3205,12 @@ "version": "0.7.8", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", - "dev": true + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } }, "sigmund": { "version": "1.0.1", @@ -2277,30 +3235,52 @@ "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, "dependencies": { "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -2309,12 +3289,18 @@ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -2322,7 +3308,12 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } }, "kind-of": { "version": "5.1.0", @@ -2337,12 +3328,20 @@ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, "dependencies": { "define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } } } }, @@ -2351,12 +3350,18 @@ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -2370,7 +3375,14 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", - "dev": true + "dev": true, + "requires": { + "atob": "^2.0.0", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } }, "source-map-url": { "version": "0.4.0", @@ -2388,7 +3400,11 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", - "dev": true + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } }, "spdx-exceptions": { "version": "2.1.0", @@ -2400,7 +3416,11 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } }, "spdx-license-ids": { "version": "3.0.0", @@ -2412,7 +3432,10 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } }, "sprintf-js": { "version": "1.0.3", @@ -2425,24 +3448,37 @@ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, "dependencies": { "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -2451,12 +3487,18 @@ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -2464,7 +3506,12 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } }, "kind-of": { "version": "5.1.0", @@ -2480,23 +3527,34 @@ "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", "dev": true }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true - }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } }, "strip-bom": { "version": "3.0.0", @@ -2508,7 +3566,10 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + } }, "strip-json-comments": { "version": "2.0.1", @@ -2527,6 +3588,14 @@ "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", "dev": true, + "requires": { + "ajv": "^4.7.0", + "ajv-keywords": "^1.0.0", + "chalk": "^1.1.1", + "lodash": "^4.0.0", + "slice-ansi": "0.0.4", + "string-width": "^2.0.0" + }, "dependencies": { "ansi-regex": { "version": "3.0.0", @@ -2544,13 +3613,20 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } } } }, @@ -2570,13 +3646,20 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true + "dev": true, + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } }, "tildify": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true + "dev": true, + "requires": { + "os-homedir": "^1.0.0" + } }, "time-stamp": { "version": "1.1.0", @@ -2589,12 +3672,18 @@ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -2602,13 +3691,23 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } }, "to-regex-range": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } }, "trim-newlines": { "version": "1.0.0", @@ -2620,7 +3719,10 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } }, "typedarray": { "version": "0.0.6", @@ -2633,7 +3735,12 @@ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", "dev": true, - "optional": true + "optional": true, + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + } }, "uglify-to-browserify": { "version": "1.0.2", @@ -2653,18 +3760,33 @@ "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, "dependencies": { "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } }, "set-value": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } } } }, @@ -2679,18 +3801,30 @@ "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, "dependencies": { "has-value": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, "dependencies": { "isobject": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true + "dev": true, + "requires": { + "isarray": "1.0.0" + } } } }, @@ -2712,13 +3846,19 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", - "dev": true + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } }, "user-home": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", - "dev": true + "dev": true, + "requires": { + "os-homedir": "^1.0.0" + } }, "util-deprecate": { "version": "1.0.2", @@ -2731,6 +3871,9 @@ "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", "dev": true, + "requires": { + "user-home": "^1.1.1" + }, "dependencies": { "user-home": { "version": "1.1.1", @@ -2744,19 +3887,38 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", - "dev": true + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } }, "vinyl": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } }, "vinyl-fs": { "version": "0.3.14", "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", "dev": true, + "requires": { + "defaults": "^1.0.0", + "glob-stream": "^3.1.5", + "glob-watcher": "^0.0.6", + "graceful-fs": "^3.0.0", + "mkdirp": "^0.5.0", + "strip-bom": "^1.0.0", + "through2": "^0.6.1", + "vinyl": "^0.4.0" + }, "dependencies": { "clone": { "version": "0.2.0", @@ -2768,7 +3930,10 @@ "version": "3.0.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true + "dev": true, + "requires": { + "natives": "^1.1.0" + } }, "isarray": { "version": "0.0.1", @@ -2780,7 +3945,13 @@ "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } }, "string_decoder": { "version": "0.10.31", @@ -2792,19 +3963,31 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", - "dev": true + "dev": true, + "requires": { + "first-chunk-stream": "^1.0.0", + "is-utf8": "^0.2.0" + } }, "through2": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } }, "vinyl": { "version": "0.4.6", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true + "dev": true, + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } } } }, @@ -2812,7 +3995,10 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", - "dev": true + "dev": true, + "requires": { + "isexe": "^2.0.0" + } }, "window-size": { "version": "0.1.0", @@ -2837,7 +4023,10 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } }, "xtend": { "version": "4.0.1", @@ -2851,6 +4040,12 @@ "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", "dev": true, "optional": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + }, "dependencies": { "camelcase": { "version": "1.2.1", diff --git a/package.json b/package.json index 26b4c469..b8cb57a7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "red5pro-html-sdk-testbed", - "version": "5.2.0", + "version": "5.2.1", "description": "Testbed examples for Red5 Pro HTML SDK", "main": "src/js/index.js", "repository": { diff --git a/src/page/test/subscribeUnsubscribe/README.md b/src/page/test/subscribeUnsubscribe/README.md new file mode 100644 index 00000000..314cd507 --- /dev/null +++ b/src/page/test/subscribeUnsubscribe/README.md @@ -0,0 +1,156 @@ +# Subscribe Failover using Red5 Pro + +This is an example of utilizing the failover mechanism of the Red5 Pro HTML SDK to select a subscriber based on browser support. + +The default failover order is: + +1. WebRTC +2. RTMP/Flash +3. HLS + +When utilizing the auto-failover mechanism, the SDK - by default - will first test for WebRTC support and if missing will attempt to embed a subscriber SWF for the broadcast. If Flash is not supported in the browser, it will finally attempt to playback using HLS. + +You can define the desired failover order from using `setPlaybackOrder`. + +> For more detailed information on Configuring and Subscribing with the Red5 Pro SDK, please visit the [Red5 Pro Documentation](https://www.red5pro.com/docs/streaming/subscriber.html). + +## Example Code +- **[index.html](index.html)** +- **[index.js](index.js)** + +# How to Subscribe + +Subscribing to a Red5 Pro stream requires a few components to function fully. + +> The examples in this repo also utilize various es2015 shims and polyfills to support ease in such things as `Object.assign` and `Promises`. You can find the list of these utilities used in [https://github.com/red5pro/streaming-html5/tree/master/static/lib/es6](feature/update_docs_RPRO-5153). + +## Including the SDK + +You will need to include the Red5 Pro SDK library on the page. If you have not already done so, download the Red5 Pro HTML SDK from your account page: [https://account.red5pro.com/download](https://account.red5pro.com/download). + +Once downloaded, unzip and move the library files - contained in the `lib` directory of the unzipped download - that makes sens for your project. _For the purposes of these examples, we have maked the entire `lib` directory into the top level of our project._ + +Once the required SDK files are provided and loaded on the page, the root of the library is accessible from `window.red5prosdk`: + +```html + + + + Red5 Pro Subscriber + + + + + + + + + + + + + + + + + + +``` + +## Subscriber Selection & Initialization + +A Subscriber instance is required to attach a stream and request subscription. The SDK can determine browser support and instantiate the proper Subscriber implementation based on the desired failover order. + +The available Playback Techs supported by the Red5 Pro SDK are: + +* WebRTC +* Flash/RTMP +* HLS + +> *NOTE*: Aside from the recommendation to utilize the [adapter.js](https://github.com/webrtc/adapter) library to "shim" similar functionality across WebRTC-supported browesers, the Red5 Pro SDK itself does not provide any polyfills for support. As such, the SDK checks the inherent support of the browser in its failover process. For example, if your browser does not inherently support HLS (most browsers aside from Desktop and Mobile Safari), then you will need to use a 3rd Party library in order to provide such support. + +When requesting to playback a stream using failover, you will need to provide an initialization configuration for each desired tech. To do so, provide a `rtc`, a `rtmp` and a `hls` configuration property within the configuraiton object passed through `init()` invocation: + +```js +var config = { + rtcport: 8081, + rtmpport: 1935, + hlsport: 5080 +}; +var rtcConfig = Object.assign({}, config, { + protocol: 'ws', + port: config.rtcport, + subscriptionId: 'subscriber-' + instanceId, + streamName: config.stream1 +}) +var rtmpConfig = Object.assign({}, config, { + protocol: 'rtmp', + port: config.rtmpport, + streamName: config.stream1, + swf: 'lib/red5pro/red5pro-subscriber.swf', + swfobjectURL: 'lib/swfobject/swfobject.js', + productInstallURL: 'lib/swfobject/playerProductInstall.swf' +}) +var hlsConfig = Object.assign({}, config, { + protocol: 'http', + port: config.hlsport, + streamName: config.stream1, + mimeType: 'application/x-mpegURL' +}) + +var subscriber = new red5pro.Red5ProSubscriber(); +subscriber.setPlaybackOrder(subscribeOrder) + .init({ + rtc: rtcConfig, + rtmp: rtmpConfig, + hls: hlsConfig + }) + .then(function (selectedSubscriber) { + // We have successfully found a playback tech from the list... + }); +``` + +[index.js #97](index.js#L97) + +The `init` method of the `Red5ProSubscriber` returns a `Promise`-like object that will be resolved with the instantiated Subscriber implementation based on the subscriber order and browser support. + +You can determine the selected implementation by invoking `selectedSubscriber.getType()`. + +> Read more about configurations and their attributes from the [Red5 Pro HTML SDK Documentation](https://github.com/infrared5/red5pro-html-sdk#subscriber). + +### Subscribing + +The `init` method of the `Red5ProSubscriber` instance returns a `Promise`-object which, when resolved, relays the Subscriber instance determined from the failover. To start a subscribing session, call the `subscribe` method of the Subscriber resolved: + +```js +subscriber.setPlaybackOrder(subscribeOrder) + .init({ + rtc: rtcConfig, + rtmp: rtmpConfig, + hls: hlsConfig + }) + .then(function (selectedSubscriber) { + return selectedSubscriber.subscribe(); + }) + .then(function () { + console.log('Successfully started a subscription session!'); + }) + .catch(function () { + console.error('Could not start a subscription session: ' + error); + }) +``` + +[index.js #136](index.js#L136) + diff --git a/src/page/test/subscribeUnsubscribe/index.html b/src/page/test/subscribeUnsubscribe/index.html new file mode 100644 index 00000000..8fefb5fa --- /dev/null +++ b/src/page/test/subscribeUnsubscribe/index.html @@ -0,0 +1,30 @@ + + + + {{> meta title='Subscriber Unsubscribe Test'}} + {{> header-scripts}} + {{> header-stylesheets}} + + +
+ {{> version }} + {{> settings-link}} + {{> test-info testTitle='Subscribe Unsubscribe Test'}} + {{> status-field-subscriber}} + {{> statistics-field}} +
+

+ + +

+ +
+
+ {{> body-scripts}} + + + diff --git a/src/page/test/subscribeUnsubscribe/index.js b/src/page/test/subscribeUnsubscribe/index.js new file mode 100644 index 00000000..8a2a82ff --- /dev/null +++ b/src/page/test/subscribeUnsubscribe/index.js @@ -0,0 +1,240 @@ +(function(window, document, red5prosdk) { + 'use strict'; + + var serverSettings = (function() { + var settings = sessionStorage.getItem('r5proServerSettings'); + try { + return JSON.parse(settings); + } + catch (e) { + console.error('Could not read server settings from sessionstorage: ' + e.message); + } + return {}; + })(); + + var configuration = (function () { + var conf = sessionStorage.getItem('r5proTestBed'); + try { + return JSON.parse(conf); + } + catch (e) { + console.error('Could not read testbed configuration from sessionstorage: ' + e.message); + } + return {} + })(); + red5prosdk.setLogLevel(configuration.verboseLogging ? red5prosdk.LOG_LEVELS.TRACE : red5prosdk.LOG_LEVELS.WARN); + + var targetSubscriber; + + var updateStatusFromEvent = window.red5proHandleSubscriberEvent; // defined in src/template/partial/status-field-subscriber.hbs + var streamTitle = document.getElementById('stream-title'); + var statisticsField = document.getElementById('statistics-field'); + var subscribeButton = document.getElementById('subscribe-button'); + var unsubscribeButton = document.getElementById('unsubscribe-button'); + + var protocol = serverSettings.protocol; + var isSecure = protocol === 'https'; + + var bitrate = 0; + var packetsReceived = 0; + var frameWidth = 0; + var frameHeight = 0; + + function getInstanceId () { + return 'susbcriber-' + Math.floor(Math.random() * 0x10000).toString(16); + } + + function updateStatistics (b, p, w, h) { + statisticsField.innerText = 'Bitrate: ' + Math.floor(b) + '. Packets Received: ' + p + '.' + ' Resolution: ' + w + ', ' + h + '.'; + } + + function onBitrateUpdate (b, p) { + bitrate = b; + packetsReceived = p; + updateStatistics(bitrate, packetsReceived, frameWidth, frameHeight); + } + + function onResolutionUpdate (w, h) { + frameWidth = w; + frameHeight = h; + updateStatistics(bitrate, packetsReceived, frameWidth, frameHeight); + } + + // Determines the ports and protocols based on being served over TLS. + function getSocketLocationFromProtocol () { + return !isSecure + ? {protocol: 'ws', port: serverSettings.wsport} + : {protocol: 'wss', port: serverSettings.wssport}; + } + + // Base configuration to extend in ptoviding specific tech failover configurations. + var defaultConfiguration = (function(useVideo, useAudio) { + var c = { + protocol: getSocketLocationFromProtocol().protocol, + port: getSocketLocationFromProtocol().port + }; + if (!useVideo) { + c.videoEncoding = red5prosdk.PlaybackVideoEncoder.NONE; + } + if (!useAudio) { + c.audioEncoding = red5prosdk.PlaybackAudioEncoder.NONE; + } + return c; + })(configuration.useVideo, configuration.useAudio); + + // Local lifecycle notifications. + function onSubscriberEvent (event) { + if (event.type !== 'Subscribe.Time.Update') { + console.log('[Red5ProSubscriber] ' + event.type + '.'); + updateStatusFromEvent(event); + } + } + function onSubscribeFail (message) { + console.error('[Red5ProSubsriber] Subscribe Error :: ' + message); + } + function onSubscribeSuccess (subscriber) { + console.log('[Red5ProSubsriber] Subscribe Complete.'); + if (subscriber.getType().toLowerCase() === 'rtc') { + try { + window.trackBitrate(subscriber.getPeerConnection(), onBitrateUpdate, onResolutionUpdate); + } + catch (e) { + // + } + } + } + function onUnsubscribeFail (message) { + console.error('[Red5ProSubsriber] Unsubscribe Error :: ' + message); + } + function onUnsubscribeSuccess () { + console.log('[Red5ProSubsriber] Unsubscribe Complete.'); + } + + // Request to unsubscribe. + function unsubscribe () { + return new Promise(function(resolve, reject) { + var subscriber = targetSubscriber + subscriber.unsubscribe() + .then(function () { + targetSubscriber.off('*', onSubscriberEvent); + targetSubscriber = undefined; + onUnsubscribeSuccess(); + enableSubscribe(); + resolve(); + }) + .catch(function (error) { + var jsonError = typeof error === 'string' ? error : JSON.stringify(error, null, 2); + onUnsubscribeFail(jsonError); + enableSubscribe(); + reject(error); + }); + }); + } + + // Define tech spefific configurations for each failover item. + var config = Object.assign({}, configuration, defaultConfiguration); + var rtcConfig = Object.assign({}, config, { + protocol: getSocketLocationFromProtocol().protocol, + port: getSocketLocationFromProtocol().port, + subscriptionId: getInstanceId(), + streamName: config.stream1, + }) + var rtmpConfig = Object.assign({}, config, { + protocol: 'rtmp', + port: serverSettings.rtmpport, + streamName: config.stream1, + width: config.cameraWidth, + height: config.cameraHeight, + backgroundColor: '#000000', + swf: '../../lib/red5pro/red5pro-subscriber.swf', + swfobjectURL: '../../lib/swfobject/swfobject.js', + productInstallURL: '../../lib/swfobject/playerProductInstall.swf' + }) + var hlsConfig = Object.assign({}, config, { + protocol: protocol, + port: isSecure ? serverSettings.hlssport : serverSettings.hlsport, + streamName: config.stream1, + mimeType: 'application/x-mpegURL' + }) + + // Define failover order. + var subscribeOrder = config.subscriberFailoverOrder + .split(',').map(function (item) { + return item.trim(); + }); + + // Override for providing ?view= query param. + if (window.query('view')) { + subscribeOrder = [window.query('view')]; + } + + function doSubscribe () { + // generate new UUID. + rtcConfig.subscriptionId = getInstanceId(); + // Request to initialization and start subscribing through failover support. + var subscriber = new red5prosdk.Red5ProSubscriber() + subscriber.setPlaybackOrder(subscribeOrder) + .init({ + rtc: rtcConfig, + rtmp: rtmpConfig, + hls: hlsConfig + }) + .then(function (subscriberImpl) { + streamTitle.innerText = configuration.stream1; + targetSubscriber = subscriberImpl + // Subscribe to events. + targetSubscriber.on('*', onSubscriberEvent); + return targetSubscriber.subscribe() + }) + .then(function () { + enableUnsubscribe(); + onSubscribeSuccess(targetSubscriber); + }) + .catch(function (error) { + enableSubscribe(); + var jsonError = typeof error === 'string' ? error : JSON.stringify(error, null, 2); + console.error('[Red5ProSubscriber] :: Error in subscribing - ' + jsonError); + onSubscribeFail(jsonError); + }); + } + + function doUnsubscribe () { + unsubscribe(); + } + + function enableUnsubscribe () { + subscribeButton.setAttribute('disabled', true) + unsubscribeButton.removeAttribute('disabled') + } + function enableSubscribe () { + unsubscribeButton.setAttribute('disabled', true) + subscribeButton.removeAttribute('disabled') + } + function disableSubscribe () { + subscribeButton.setAttribute('disabled', true) + unsubscribeButton.setAttribute('disabled', true) + } + + subscribeButton.addEventListener('click', function () { + disableSubscribe(); + doSubscribe(); + }); + unsubscribeButton.addEventListener('click', function () { + disableSubscribe(); + doUnsubscribe(); + }); + + // Clean up. + window.addEventListener('beforeunload', function() { + function clearRefs () { + if (targetSubscriber) { + targetSubscriber.off('*', onSubscriberEvent); + } + targetSubscriber = undefined; + } + unsubscribe().then(clearRefs).catch(clearRefs); + window.untrackBitrate(); + }); + +})(this, document, window.red5prosdk); + diff --git a/src/page/testbed-menu.html b/src/page/testbed-menu.html index 48f88051..ccf38ab8 100644 --- a/src/page/testbed-menu.html +++ b/src/page/testbed-menu.html @@ -41,6 +41,7 @@

Red5 Pro HTML Testbed

  • Subscribe - Reconnect
  • Subscribe - Shared Object
  • Subscribe - Cluster
  • +
  • Subscribe - Unsubscribe
  • Subscribe - Audio Only (WebRTC)
  • Subscribe - Image Capture (WebRTC)
  • Subscribe - Retry On Connection (WebRTC)
  • diff --git a/src/template/partial/header-scripts.hbs b/src/template/partial/header-scripts.hbs index c7767098..d331bf0f 100644 --- a/src/template/partial/header-scripts.hbs +++ b/src/template/partial/header-scripts.hbs @@ -1,4 +1,4 @@ - + diff --git a/static/lib/red5pro/red5pro-sdk.min.js b/static/lib/red5pro/red5pro-sdk.min.js index 2f3c0a00..989e3692 100644 --- a/static/lib/red5pro/red5pro-sdk.min.js +++ b/static/lib/red5pro/red5pro-sdk.min.js @@ -2,8 +2,17733 @@ * * red5pro-sdk - Red5 Pro HTML Publisher and Subscriber SDK. * Author: Infrared5 Inc. - * Version: 5.2.0 + * Version: 5.2.1 * Url: https://github.com/red5pro/red5pro-html-sdk#readme * */ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.red5prosdk=t():e.red5prosdk=t()}(this,function(){return function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,t),i.l=!0,i.exports}var n={};return t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=208)}([function(e,t,n){"use strict";t.__esModule=!0,t.default=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}},function(e,t,n){"use strict";t.__esModule=!0;var r=n(91),i=function(e){return e&&e.__esModule?e:{default:e}}(r);t.default=function(){function e(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:void 0,n=[];if(n.push({level:e,stream:new i.RawStream,type:"raw"}),t){var s=t.map(function(t){t.level=e});n=n.concat(s)}o=(0,r.createLogger)({level:e,name:"red5pro-sdk",streams:n})},t.getLogger=function(){return o},t.trace=a(u.TRACE),t.info=a(u.INFO),t.debug=a(u.DEBUG),t.warn=a(u.WARN),t.error=a(u.ERROR),t.fatal=a(u.FATAL)},function(e,t){var n=e.exports={version:"2.4.0"};"number"==typeof __e&&(__e=n)},function(e,t,n){"use strict";function r(){!p&&window.screenfull&&window.screenfull.enabled&&(p=!0,window.screenfull.onchange(function(){var e=void 0,t=h.length;for(e=0;e0||e.canPlayType("application/x-mpegURL").length>0||e.canPlayType("audio/mpegurl").length>0||e.canPlayType("audio/x-mpegurl").length>0},supportsFlashVersion:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:".";return _()[0]>=e.split(t)[0]},resolveElement:function(e){try{var t=document.getElementById(e);if(!t)throw new c.NoElementFoundError("Element with id("+e+") could not be found.");return t}catch(t){throw new c.NoElementFoundError("Error in accessing element with id("+e+"). "+t.message)}},createWebSocket:function(e){return new WebSocket(e)},setVideoSource:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(e.onloadedmetadata=function(){(0,d.debug)("[videoelement:event]","loadedmetadata"),(0,d.debug)("[video:constraints]","Video actual dimensions are: "+e.videoWidth+", "+e.videoHeight)},"srcObject"in e?e.srcObject=t:g?e.mozSrcObject=t:e.src=window.URL.createObjectURL(t),n)try{var r=e.play();r&&r.then(function(){return(0,d.debug)("[setVideoSource:action]","play (START)")}).catch(function(e){return(0,d.warn)("[setVideoSource:action]","play (FAULT) "+(e.message?e.message:e))})}catch(t){(0,d.warn)("[setVideoSource:action]","play (CATCH::FAULT) "+t.message);try{e.setAttribute("autoplay",!1),e.pause()}catch(e){(0,d.warn)("[setVideoSource:action]","pause (CATCH::FAULT) "+e.message)}}else try{e.setAttribute("autoplay",!1),e.pause()}catch(e){}},injectScript:function(e){var t=new u.DeferredPromise,n=document.createElement("script");return n.type="text/javascript",n.onload=function(){t.resolve()},n.onreadystatechange=function(){"loaded"!==n.readyState&&"complete"!==n.readyState||(n.onreadystatechange=null,t.resolve())},n.src=e,document.getElementsByTagName("head")[0].appendChild(n),t.promise},gUM:function(e){return(navigator.mediaDevices||navigator).getUserMedia(e)},setGlobal:function(e,t){window[e]=t},getSwfObject:function(){return window.swfobject},getEmbedObject:function(e){return document.getElementById(e)},getElementId:function(e){return e.getAttribute("id")},addOrientationChangeHandler:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];"onorientationchange"in window&&((0,d.debug)("[window:orientation]","[addOrientationChangeHandler]","adding responder."),v.push(e),t&&i()),1===v.length&&((0,d.debug)("[window:orientation]","[addOrientationChangeHandler]","onorientationchange added."),window.addEventListener("orientationchange",i))},removeOrientationChangeHandler:function(e){for(var t=v.length;--t>-1;)if(v[t]===e){v.slice(t,1);break}0===v.length&&((0,d.debug)("[window:orientation]","[removeOrientationChangeHandler]:: onorientationchange removed."),window.removeEventListener("onorientationchange",i))},addCloseHandler:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1;b.splice(-1===t?b.length:t,0,e),m||window.addEventListener("unload",o)},removeCloseHandler:function(e){for(var t=b.length;--t>-1;)if(b[t]===e){b.slice(t,1);break}},invoke:function(e,t){window.hasOwnProperty(e)&&window[e].call(window,t)},toggleFullScreen:function(e){window.screenfull&&window.screenfull.enabled&&window.screenfull.toggle(e)},onFullScreenStateChange:function(e){h.push(e),r(window.screenfull)},onOrientationMetadata:l.onOrientationMetadata,hasAttributeDefined:function(e,t){var n=e.getAttribute(t);return null!==n&&void 0!==(void 0===n?"undefined":(0,a.default)(n))&&"string"==typeof n&&(""===n||"true"===n||n===t)},hasClassDefined:function(e,t){return e.classList.contains(t)},createElement:function(e,t){return"text"===e?document.createTextNode(t.toString()):document.createElement(e,t)},addSubscriptionAssignmentHandler:function(e){f.push(e),void 0===window.setSubscriberId&&(window.setSubscriberId=function(e){f.shift()(e)})},getMouseXFromEvent:function(e){return e||(e=window.event),e.pageX?e.pageX:e.clientX?e.clientX+document.body.scrollLeft+document.documentElement.scrollLeft:0},getScrollX:function(){return void 0!==window.pageXOffset?window.pageXOffset:(document.documentElement||document.body.parentNode||document.body).scrollLeft},createEvent:function(e){return document.createEvent(e)},getGlobal:function(){return window}}},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0}),t.Future=t.DeferredPromise=void 0;var i=n(61),o=r(i),s=n(0),a=r(s),u=function e(){var t=this;(0,a.default)(this,e),this.resolve=void 0,this.reject=void 0,this.promise=new o.default(function(e,n){t.resolve=e,t.reject=n})},c={createIfNotExist:function(e){var t=e;return t||(t=new u),t}};t.DeferredPromise=u,t.Future=c},function(e,t,n){e.exports={default:n(157),__esModule:!0}},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}t.__esModule=!0;var i=n(139),o=r(i),s=n(137),a=r(s),u=n(62),c=r(u);t.default=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+(void 0===t?"undefined":(0,c.default)(t)));e.prototype=(0,a.default)(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(o.default?(0,o.default)(e,t):e.__proto__=t)}},function(e,t,n){"use strict";t.__esModule=!0;var r=n(62),i=function(e){return e&&e.__esModule?e:{default:e}}(r);t.default=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!==(void 0===t?"undefined":(0,i.default)(t))&&"function"!=typeof t?e:t}},function(e,t,n){var r=n(74)("wks"),i=n(53),o=n(11).Symbol,s="function"==typeof o;(e.exports=function(e){return r[e]||(r[e]=s&&o[e]||(s?o:i)("Symbol."+e))}).store=r},function(e,t,n){var r=n(11),i=n(3),o=n(19),s=n(21),a=function(e,t,n){var u,c,l,d=e&a.F,f=e&a.G,h=e&a.S,p=e&a.P,v=e&a.B,b=e&a.W,m=f?i:i[t]||(i[t]={}),_=m.prototype,y=f?r:h?r[t]:(r[t]||{}).prototype;f&&(n=t);for(u in n)(c=!d&&y&&void 0!==y[u])&&u in m||(l=c?y[u]:n[u],m[u]=f&&"function"!=typeof y[u]?n[u]:v&&c?o(l,r):b&&y[u]==l?function(e){var t=function(t,n,r){if(this instanceof e){switch(arguments.length){case 0:return new e;case 1:return new e(t);case 2:return new e(t,n)}return new e(t,n,r)}return e.apply(this,arguments)};return t.prototype=e.prototype,t}(l):p&&"function"==typeof l?o(Function.call,l):l,p&&((m.virtual||(m.virtual={}))[u]=l,e&a.R&&_&&!_[u]&&s(_,u,l)))};a.F=1,a.G=2,a.S=4,a.P=8,a.B=16,a.W=32,a.U=64,a.R=128,e.exports=a},function(e,t){var n=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},function(e,t,n){e.exports={default:n(148),__esModule:!0}},function(e,t){e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},function(e,t,n){var r=n(16),i=n(99),o=n(76),s=Object.defineProperty;t.f=n(17)?Object.defineProperty:function(e,t,n){if(r(e),t=o(t,!0),r(n),i)try{return s(e,t,n)}catch(e){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(e[t]=n.value),e}},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0}),t.SharedObjectEventTypes=t.FailoverSubscriberEventTypes=t.RTMPSubscriberEventTypes=t.RTCSubscriberEventTypes=t.SubscriberEventTypes=t.FailoverPublisherEventTypes=t.RTMPPublisherEventTypes=t.RTCPublisherEventTypes=t.PublisherEventTypes=t.SharedObjectEvent=t.SubscriberEvent=t.PublisherEvent=t.Event=void 0;var i=n(6),o=r(i),s=n(8),a=r(s),u=n(7),c=r(u),l=n(0),d=r(l),f=n(1),h=r(f),p=n(82);Object.defineProperty(t,"PublisherEventTypes",{enumerable:!0,get:function(){return p.PublisherEventTypes}}),Object.defineProperty(t,"RTCPublisherEventTypes",{enumerable:!0,get:function(){return p.RTCPublisherEventTypes}}),Object.defineProperty(t,"RTMPPublisherEventTypes",{enumerable:!0,get:function(){return p.RTMPPublisherEventTypes}}),Object.defineProperty(t,"FailoverPublisherEventTypes",{enumerable:!0,get:function(){return p.FailoverPublisherEventTypes}});var v=n(83);Object.defineProperty(t,"SubscriberEventTypes",{enumerable:!0,get:function(){return v.SubscriberEventTypes}}),Object.defineProperty(t,"RTCSubscriberEventTypes",{enumerable:!0,get:function(){return v.RTCSubscriberEventTypes}}),Object.defineProperty(t,"RTMPSubscriberEventTypes",{enumerable:!0,get:function(){return v.RTMPSubscriberEventTypes}}),Object.defineProperty(t,"FailoverSubscriberEventTypes",{enumerable:!0,get:function(){return v.FailoverSubscriberEventTypes}});var b=n(56);Object.defineProperty(t,"SharedObjectEventTypes",{enumerable:!0,get:function(){return b.SharedObjectEventTypes}});var m=function(){function e(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0;(0,d.default)(this,e),this._type=t,this._data=n}return(0,h.default)(e,[{key:"type",get:function(){return this._type}},{key:"data",get:function(){return this._data}}]),e}(),_=function(e){function t(e,n,r){(0,d.default)(this,t);var i=(0,a.default)(this,(t.__proto__||(0,o.default)(t)).call(this,e,r));return i._publisher=n,i}return(0,c.default)(t,e),(0,h.default)(t,[{key:"publisher",get:function(){return this._publisher}}]),t}(m),y=function(e){function t(e,n,r){(0,d.default)(this,t);var i=(0,a.default)(this,(t.__proto__||(0,o.default)(t)).call(this,e,r));return i._subscriber=n,i}return(0,c.default)(t,e),(0,h.default)(t,[{key:"subscriber",get:function(){return this._subscriber}}]),t}(m),g=function(e){function t(e,n,r){(0,d.default)(this,t);var i=(0,a.default)(this,(t.__proto__||(0,o.default)(t)).call(this,e,r));return i._name=n,i}return(0,c.default)(t,e),(0,h.default)(t,[{key:"name",get:function(){return this._name}}]),t}(m);t.Event=m,t.PublisherEvent=_,t.SubscriberEvent=y,t.SharedObjectEvent=g},function(e,t,n){var r=n(13);e.exports=function(e){if(!r(e))throw TypeError(e+" is not an object!");return e}},function(e,t,n){e.exports=!n(25)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(e,t,n){e.exports={default:n(155),__esModule:!0}},function(e,t,n){var r=n(63);e.exports=function(e,t,n){if(r(e),void 0===t)return e;switch(n){case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,i){return e.call(t,n,r,i)}}return function(){return e.apply(t,arguments)}}},function(e,t){var n={}.hasOwnProperty;e.exports=function(e,t){return n.call(e,t)}},function(e,t,n){var r=n(14),i=n(38);e.exports=n(17)?function(e,t,n){return r.f(e,t,i(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t,n){var r=n(68),i=n(46);e.exports=function(e){return r(i(e))}},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var i=n(0),o=r(i),s=n(1),a=r(s),u="RED5PRO",c=function(){function e(){(0,o.default)(this,e),this._callbacks={},this._callbacks[u]=[]}return(0,a.default)(e,[{key:"_notify",value:function(e,t){var n=void 0,r=e.length;for(n=0;n1&&void 0!==arguments[1]&&arguments[1]}},{key:"toggleFullScreen",value:function(){}}]),t}(v.default),P=function(){function e(){(0,a.default)(this,e)}return(0,c.default)(e,[{key:"getVolume",value:function(){}},{key:"setVolume",value:function(e){}},{key:"setSeekTime",value:function(e){arguments.length>1&&void 0!==arguments[1]&&arguments[1]}},{key:"setPlaybackDuration",value:function(e){}},{key:"getState",value:function(){}},{key:"setState",value:function(e){}},{key:"setAsVOD",value:function(e){}},{key:"enable",value:function(e){}}]),e}(),C=function(e){function t(e,n){(0,a.default)(this,t);var r=(0,d.default)(this,(t.__proto__||(0,o.default)(t)).call(this));return r.player=e,r.container=n,r._controlbar=void 0,r._playPauseButton=void 0,r._muteButton=void 0,r._volumeField=void 0,r._seekTimeField=void 0,r._timeField=void 0,r._fullScreenButton=void 0,r._state=S.PlaybackState.IDLE,r._mutedState=!1,r._resumeAfterSeek=!1,r._playbackDuration=0,r._volumeValue=1,r._onPlayPauseClickBound=r._onPlayPauseClick.bind(r),r.decorate(r.container),r}return(0,h.default)(t,e),(0,c.default)(t,[{key:"decorate",value:function(e){(0,E.debug)(w,"[decorate]");var t=m.default.createElement("div");t.classList.add("red5pro-media-control-bar"),this._playPauseButton=this._createPlayPauseButton(),this._muteButton=this._createMuteButton(),this._volumeField=this._createVolumeControl(),this._seekTimeField=this._createSeekControl(),this._timeField=this._createPlaybackTime(),this._fullScreenButton=this._createFullScreenToggle(),t.appendChild(this._playPauseButton),t.appendChild(this._timeField),t.appendChild(this._seekTimeField.view),t.appendChild(this._muteButton),t.appendChild(this._volumeField.view),t.appendChild(this._fullScreenButton),e.appendChild(t),this._controlbar=t,m.default.isTouchEnabled()?t.classList.add("red5pro-media-control-bar-show"):(this.container.addEventListener("mouseover",function(){t.classList.add("red5pro-media-control-bar-show")}),this.container.addEventListener("mouseout",function(){t.classList.remove("red5pro-media-control-bar-show")})),this.setState(S.PlaybackState.IDLE).onFullScreenChange(!1).setSeekTime(0).enable(!1)}},{key:"_onPlayPauseClick",value:function(){this.getState()===S.PlaybackState.PLAYING?this.player.pause():this.getState()===S.PlaybackState.PAUSED?this.player.resume():this.player.play()}},{key:"_createPlayPauseButton",value:function(){var e=m.default.createElement("button");return e.setAttribute("aria-label","Toggle Playback"),e.classList.add("red5pro-media-control-element"),e.classList.add("red5pro-media-element-button"),e.classList.add("red5pro-media-playpause-button"),e}},{key:"_createMuteButton",value:function(){var e=this,t=m.default.createElement("button");return t.setAttribute("aria-label","Toggle Mute Audio"),t.classList.add("red5pro-media-control-element"),t.classList.add("red5pro-media-element-button"),t.classList.add("red5pro-media-muteunmute-button"),t.addEventListener("click",function(){e.getMutedState()?(e.player.unmute(),e.setMutedState(!1)):(e.player.mute(),e.setMutedState(!0))}),t}},{key:"_createVolumeControl",value:function(){var e=this,t=new y.default("volume");return t.view.classList.add("red5pro-media-control-element"),t.view.classList.add("red5pro-media-volume-slider"),t.view.classList.add("red5pro-media-slider"),t.on(g.SliderEventTypes.CHANGE,function(t){var n=Number(t.data);e.player.setVolume(n)}),t}},{key:"_createSeekControl",value:function(){var e=this,t=new y.default("seek");return t.view.classList.add("red5pro-media-control-element"),t.view.classList.add("red5pro-media-seektime-slider"),t.view.classList.add("red5pro-media-slider"),t.on(g.SliderEventTypes.CHANGE_START,function(){e.getState()===S.PlaybackState.PLAYING&&(e._resumeAfterSeek=!0,e.player.pause())}),t.on(g.SliderEventTypes.CHANGE,function(t){var n=Number(t.data);e.player.seekTo(n,0===e._playbackDuration?void 0:e._playbackDuration),e.setSeekTime(n*e._playbackDuration,e._playbackDuration)}),t.on(g.SliderEventTypes.CHANGE_COMPLETE,function(){e._resumeAfterSeek&&e.getState()===S.PlaybackState.PAUSED&&(e._resumeAfterSeek=!1,e.player.resume())}),t}},{key:"_createPlaybackTime",value:function(){var e=m.default.createElement("span"),t=m.default.createElement("text","hello!");return e.classList.add("red5pro-media-control-element"),e.classList.add("red5pro-media-time-field"),e.appendChild(t),e}},{key:"_createFullScreenToggle",value:function(){var e=this,t=m.default.createElement("button");return t.setAttribute("aria-label","Toggle Fullscreen"),t.classList.add("red5pro-media-control-element"),t.classList.add("red5pro-media-element-button"),t.classList.add("red5pro-media-fullscreen-button"),t.addEventListener("click",function(){e.player.toggleFullScreen()}),t}},{key:"enable",value:function(e){e?(this._playPauseButton.classList.remove("red5pro-media-element-button-disabled"),this._playPauseButton.addEventListener("click",this._onPlayPauseClickBound)):(this._playPauseButton.classList.add("red5pro-media-element-button-disabled"),this._playPauseButton.removeEventListener("click",this._onPlayPauseClickBound))}},{key:"formatTime",value:function(e){var t=0,n=0===e?0:parseInt(e/60),r=0;n>=60&&(t=parseInt(n/60),n%=60),r=0===e?0:parseInt(e%60);var i=t<10?["0"+t]:[t];return i.push(n<10?["0"+n]:[n]),i.push(r<10?["0"+r]:[r]),i.join(":")}},{key:"getVolume",value:function(){return this._volumeValue}},{key:"setVolume",value:function(e){return this._volumeField.value=e,this._volumeValue=e,0===e?this.setMutedState(!0):this.getMutedState()&&this.setMutedState(!1),this}},{key:"setSeekTime",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;return this._seekTimeField.value=0===t?0:e/t,0!==this._playbackDuration&&parseInt(this._playbackDuration)<=parseInt(e)&&(this._seekTimeField.value=1),this._timeField.innerText=this.formatTime(Math.floor(e)),this}},{key:"setPlaybackDuration",value:function(e){(0,E.debug)(w,"[setplaybackduration]: "+e),this._playbackDuration=e}},{key:"getState",value:function(){return this._state}},{key:"setState",value:function(e){return(0,E.debug)(w,"[setState]: "+S.PlaybackStateReadable[e]),this._state=e,this.onStateChange(this._state),this}},{key:"getMutedState",value:function(){return"muted"in this.player?this.player.muted:this._mutedState}},{key:"setMutedState",value:function(e){return this._mutedState=e,this.onMutedStateChange(this._mutedState),this}},{key:"onStateChange",value:function(e){return e===S.PlaybackState.PLAYING?(this._playPauseButton.classList.remove("red5pro-media-play-button"),this._playPauseButton.classList.add("red5pro-media-pause-button")):(this._playPauseButton.classList.add("red5pro-media-play-button"),this._playPauseButton.classList.remove("red5pro-media-pause-button")),this}},{key:"onMutedStateChange",value:function(e){e?(this._muteButton.classList.add("red5pro-media-mute-button"),this._muteButton.classList.remove("red5pro-media-unmute-button"),this._volumeField.value=0):(this._muteButton.classList.remove("red5pro-media-mute-button"),this._muteButton.classList.add("red5pro-media-unmute-button"),this._volumeField.value=this._volumeValue)}},{key:"onFullScreenChange",value:function(e){return e?(this._fullScreenButton.classList.add("red5pro-media-exit-fullscreen-button"),this._fullScreenButton.classList.remove("red5pro-media-fullscreen-button")):(this._fullScreenButton.classList.remove("red5pro-media-exit-fullscreen-button"),this._fullScreenButton.classList.add("red5pro-media-fullscreen-button")),this}},{key:"setAsVOD",value:function(e){(0,E.debug)(w,"[setAsVOD]: "+e),e?this._seekTimeField.disabled=!1:(this._seekTimeField.value=0,this._seekTimeField.disabled=!0)}},{key:"detach",value:function(){this.enable(!1),this.container.removeChild(this._controlbar)}}]),t}(P);t.PlaybackController=k,t.PlaybackControls=P,t.PlaybackControlsImpl=C},function(e,t){e.exports=function(e){try{return!!e()}catch(e){return!0}}},function(e,t,n){"use strict";var r=n(181)(!0);n(69)(String,"String",function(e){this._t=String(e),this._i=0},function(){var e,t=this._t,n=this._i;return n>=t.length?{value:void 0,done:!0}:(e=r(t,n),this._i+=e.length,{value:e,done:!1})})},function(e,t,n){n(186);for(var r=n(11),i=n(21),o=n(30),s=n(9)("toStringTag"),a=["NodeList","DOMTokenList","MediaList","StyleSheetList","CSSRuleList"],u=0;u<5;u++){var c=a[u],l=r[c],d=l&&l.prototype;d&&!d[s]&&i(d,s,c),o[c]=o.Array}},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0}),t.isObjectEmpty=t.metadataResolutionToObject=t.deepCopy=t.deepDefine=void 0;var i=n(60),o=r(i),s=n(12),a=r(s);t.deepDefine=function(e,t,n){var r=0,i=e,o=t.pop(),s=t.length;for(r;ry;y++)if((b=t?_(s(p=e[y])[0],p[1]):_(e[y]))===c||b===l)return b}else for(v=m.call(e);!(p=v.next()).done;)if((b=i(v,_,p.value,t))===c||b===l)return b};t.BREAK=c,t.RETURN=l},function(e,t){e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},function(e,t,n){var r=n(14).f,i=n(20),o=n(9)("toStringTag");e.exports=function(e,t,n){e&&!i(e=n?e:e.prototype,o)&&r(e,o,{configurable:!0,value:t})}},function(e,t){},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0}),t.RTCSessionDescription=t.RTCIceCandidate=t.RTCPeerConnection=t.updateBandwidth=t.forceUserMedia=t.getUserMedia=t.isSupported=t.determineSupportedResolution=t.quickResolutionSupport=void 0;var i=n(12),o=r(i),s=n(4),a=r(s),u=n(5),c=n(88),l=n(28),d=n(2),f=[{label:"4K(UHD)",width:3840,height:2160},{label:"1080p(FHD)",width:1920,height:1080},{label:"UXGA",width:1600,height:1200},{label:"720p(HD)",width:1280,height:720},{label:"SVGA",width:800,height:600},{label:"VGA",width:640,height:480},{label:"360p(nHD)",width:640,height:360},{label:"CIF",width:352,height:288},{label:"QVGA",width:320,height:240},{label:"QCIF",width:176,height:144},{label:"QQVGA",width:160,height:120}],h=function(e){return e.hasOwnProperty("video")&&(e.video.hasOwnProperty("width")||e.video.hasOwnProperty("height"))},p=function(e){return e.exact||e.ideal||e.max||e.min||e},v=(0,c.curry)(function(e,t){if("boolean"==typeof e.video)return!0;var n=e.video.hasOwnProperty("width")?p(e.video.width):0,r=e.video.hasOwnProperty("height")?p(e.video.height):0,i=n===t.width&&r===t.height;return i&&(0,d.debug)("[gum:isExact]","Found matching resolution for "+t.width+", "+t.height+"."),i}),b=(0,c.curry)(function(e,t){var n=e.video.hasOwnProperty("width")?p(e.video.width):0,r=e.video.hasOwnProperty("height")?p(e.video.height):0,i=n*r;return t.width*t.height0}),_=(0,c.curry)(function(e,t){var n=b(t);return(0,c.filter)(n)(e)}),y=function(e,t){e.video=!0,a.default.gUM(e).then(function(n){t.resolve({media:n,constraints:e})}).catch(function(n){var r="string"==typeof n?n:[n.name,n.message].join(": ");(0,d.debug)("[gum:getUserMedia]","Failure in getUserMedia: "+r+". Attempting other resolution tests..."),(0,d.debug)("[gUM:findformat]","Constraints declined by browser: "+(0,o.default)(e,null,2)),t.reject("Could not find proper camera for provided constraints.")})},g=function e(t,n,r){if(0==n.length)return void y(t,r);var i=n.shift();t.video.width={exact:i.width},t.video.height={exact:i.height},a.default.gUM(t).then(function(e){r.resolve({media:e,constraints:t})}).catch(function(i){var s="string"==typeof i?i:[i.name,i.message].join(": ");(0,d.debug)("[gum:getUserMedia]","Failure in getUserMedia: "+s+". Attempting other resolution tests..."),(0,d.debug)("[gUM:findformat]","Constraints declined by browser: "+(0,o.default)(t,null,2)),e(t,n,r)})},S=t.quickResolutionSupport=function(e){var t=(0,l.deepCopy)(e);return"boolean"==typeof e.video?t:(e.video.width&&(t.video.width={exact:p(e.video.width)}),e.video.height&&(t.video.height={exact:p(e.video.height)}),t)},E=t.determineSupportedResolution=function(e){(0,d.debug)("[gum:determineSupportedResolution]","Determine next neighbor based on constraints: "+(0,o.default)(e,null,2));var t=new u.DeferredPromise,n=_(f)(e),r=(0,l.deepCopy)(e);return g(r,n,t),t.promise},w=(t.isSupported=function(){return w&&k&&P},t.getUserMedia=function(e){var t=new u.DeferredPromise,n=m(f);(0,d.debug)("[gum:getUserMedia]","Is Available in format listing: "+n(e));var r=function(n){if(n){var r="string"==typeof n?n:[n.name,n.message].join(": ");(0,d.debug)("[gum:getUserMedia]","Failure in getUserMedia: "+r+". Attempting other resolution tests...")}E(e).then(function(e){t.resolve({media:e.media,constraints:e.constraints})}).catch(function(n){t.reject({error:n,constraints:e})})};if(h(e))if(n(e)){(0,d.debug)("[gum:getUserMedia]","Found constraints in list. Checking quick support for faster setup with: "+(0,o.default)(e,null,2));var i=S(e);a.default.gUM(i).then(function(e){t.resolve({media:e,constraints:i})}).catch(r)}else(0,d.debug)("[gum:getUserMedia]","Could not find contraints in list. Attempting failover..."),r();else(0,d.debug)("[gum:getUserMedia]","Constraints were not defined properly. Attempting failover..."),a.default.gUM(e).then(function(n){t.resolve({media:n,constraints:e})}).catch(r);return t.promise},t.forceUserMedia=function(e){return a.default.gUM(e)},t.updateBandwidth=function(e,t){if(a.default.getIsMoz()){var n=void 0,r=void 0,i=void 0,o=void 0;e.audio&&(n=t.indexOf("m=audio"),r=t.indexOf("\r\n",n),i=t.slice(0,r),o=t.slice(r+"\r\n".length,t.length),t=[i,"b=AS:"+e.audio,o].join("\r\n")),e.video&&(n=t.indexOf("m=video"),r=t.indexOf("\r\n",n),i=t.slice(0,r),o=t.slice(r+"\r\n".length,t.length),t=[i,"b=AS:"+e.video,o].join("\r\n"))}else t=t.replace(/b=AS([^\r\n]+\r\n)/g,""),e.audio&&(t=t.replace(/a=mid:audio\r\n/g,"a=mid:audio\r\nb=AS:"+e.audio+"\r\n")),e.video&&(t=t.replace(/a=mid:video\r\n/g,"a=mid:video\r\nb=AS:"+e.video+"\r\n"));return t},window.RTCPeerConnection||window.mozRTCPeerConnection||window.webkitRTCPeerConnection),k=window.RTCIceCandidate||window.mozRTCIceCandidate||window.webkitRTCIceCandidate,P=window.RTCSessionDescription||window.mozRTCSessionDescription||window.webkitRTCSessionDescription;t.RTCPeerConnection=w,t.RTCIceCandidate=k,t.RTCSessionDescription=P},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.create=t.isSupported=void 0;var r=n(4),i=function(e){return e&&e.__esModule?e:{default:e}}(r);t.isSupported=function(){return i.default.supportsWebSocket()},t.create=function(e){return i.default.createWebSocket(e)}},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0}),t.PlaybackView=void 0;var i=n(0),o=r(i),s=n(1),a=r(s),u=n(4),c=r(u),l=n(2),d="R5ProPlaybackView",f="red5pro-subscriber",h=t.PlaybackView=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:f;(0,o.default)(this,e);try{this._targetElement=c.default.resolveElement(t)}catch(e){throw(0,l.error)(d,"Could not instantiate a new instance of Red5ProSubscriber. Reason: "+e.message),e}}return(0,a.default)(e,[{key:"attachSubscriber",value:function(e){(0,l.debug)(d,"[attachsubscriber]"),e.setView(this,c.default.getElementId(this._targetElement))}},{key:"attachStream",value:function(e){var t=this.isAutoplay;(0,l.debug)(d,"[attachstream]"),c.default.setVideoSource(this._targetElement,e,t)}},{key:"isAutoplay",get:function(){return c.default.hasAttributeDefined(this._targetElement,"autoplay")}},{key:"view",get:function(){return this._targetElement}}]),e}();t.default=h},function(e,t){e.exports=function(e,t,n,r){if(!(e instanceof t)||void 0!==r&&r in e)throw TypeError(n+": incorrect invocation!");return e}},function(e,t,n){var r=n(36),i=n(9)("toStringTag"),o="Arguments"==r(function(){return arguments}()),s=function(e,t){try{return e[t]}catch(e){}};e.exports=function(e){var t,n,a;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(n=s(t=Object(e),i))?n:o?r(t):"Object"==(a=r(t))&&"function"==typeof t.callee?"Arguments":a}},function(e,t){e.exports=function(e){if(void 0==e)throw TypeError("Can't call method on "+e);return e}},function(e,t){e.exports=!0},function(e,t,n){var r=n(16),i=n(177),o=n(67),s=n(73)("IE_PROTO"),a=function(){},u=function(){var e,t=n(66)("iframe"),r=o.length;for(t.style.display="none",n(98).appendChild(t),t.src="javascript:",e=t.contentWindow.document,e.open(),e.write(" + toggleFullScreen: function toggleFullScreen(element) { + if (window.screenfull && window.screenfull.enabled) { + window.screenfull.toggle(element); + } + }, + + onFullScreenStateChange: function onFullScreenStateChange(cb) { + fullscreenHandlers.push(cb); + enableScreenfullHandler(window.screenfull); + }, + + onOrientationMetadata: _metadataUtil.onOrientationMetadata, + + hasAttributeDefined: function hasAttributeDefined(elem, attribute) { + var att = elem.getAttribute(attribute); + return att !== null && (typeof att === 'undefined' ? 'undefined' : (0, _typeof3.default)(att)) !== undefined && typeof att === 'string' && (att === '' || att === 'true' || att === attribute); + }, + + hasClassDefined: function hasClassDefined(elem, className) { + return elem.classList.contains(className); + }, + + createElement: function createElement(tagName, opts) { + if (tagName === 'text') { + return document.createTextNode(opts.toString()); + } + return document.createElement(tagName, opts); + }, + + addSubscriptionAssignmentHandler: function addSubscriptionAssignmentHandler(fn) { + rtmpSubscriberAssignments.push(fn); + if (window.setSubscriberId === undefined) { + window.setSubscriberId = function (id) { + rtmpSubscriberAssignments.shift()(id); + }; + } + }, + + getMouseXFromEvent: function getMouseXFromEvent(event) { + if (!event) { + event = window.event; + } + + if (event.pageX) { + return event.pageX; + } else if (event.clientX) { + return event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; + } + + return 0; + }, + + getScrollX: function getScrollX() { + return window.pageXOffset !== undefined ? window.pageXOffset : (document.documentElement || document.body.parentNode || document.body).scrollLeft; + }, + + createEvent: function createEvent(EventType) { + return document.createEvent(EventType); + }, + + getGlobal: function getGlobal() { + return window; + } + +}; + +/***/ }), +/* 5 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/** + * A DeferredPromise allows for construction and assignment of a future fullfilment of a `Promise`. + * + * @private + */ + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Future = exports.DeferredPromise = undefined; + +var _promise = __webpack_require__(61); + +var _promise2 = _interopRequireDefault(_promise); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var _DeferredPromise = function _DeferredPromise() { + var _this = this; + + (0, _classCallCheck3.default)(this, _DeferredPromise); + + this.resolve = undefined; + this.reject = undefined; + this.promise = new _promise2.default(function (resolve, reject) { + _this.resolve = resolve; + _this.reject = reject; + }); +}; + +/** + * A Future determines if existant DeferredPromise is available or creates and returns a new one. + * + * @param {DeferredPromise} deferredIfExist + * An object tested for truthy-ness. + * @return {DeferredPromise} + * + * @private + */ + + +var _Future = { + createIfNotExist: function createIfNotExist(deferredIfExist) { + var f = deferredIfExist; + if (!f) { + f = new _DeferredPromise(); + } + return f; + } +}; + +var DeferredPromise = exports.DeferredPromise = _DeferredPromise; +var Future = exports.Future = _Future; + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = { "default": __webpack_require__(157), __esModule: true }; + +/***/ }), +/* 7 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +exports.__esModule = true; + +var _setPrototypeOf = __webpack_require__(139); + +var _setPrototypeOf2 = _interopRequireDefault(_setPrototypeOf); + +var _create = __webpack_require__(137); + +var _create2 = _interopRequireDefault(_create); + +var _typeof2 = __webpack_require__(62); + +var _typeof3 = _interopRequireDefault(_typeof2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = function (subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + (typeof superClass === "undefined" ? "undefined" : (0, _typeof3.default)(superClass))); + } + + subClass.prototype = (0, _create2.default)(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf2.default ? (0, _setPrototypeOf2.default)(subClass, superClass) : subClass.__proto__ = superClass; +}; + +/***/ }), +/* 8 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +exports.__esModule = true; + +var _typeof2 = __webpack_require__(62); + +var _typeof3 = _interopRequireDefault(_typeof2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = function (self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return call && ((typeof call === "undefined" ? "undefined" : (0, _typeof3.default)(call)) === "object" || typeof call === "function") ? call : self; +}; + +/***/ }), +/* 9 */ +/***/ (function(module, exports, __webpack_require__) { + +var store = __webpack_require__(74)('wks') + , uid = __webpack_require__(53) + , Symbol = __webpack_require__(11).Symbol + , USE_SYMBOL = typeof Symbol == 'function'; + +var $exports = module.exports = function(name){ + return store[name] || (store[name] = + USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name)); +}; + +$exports.store = store; + +/***/ }), +/* 10 */ +/***/ (function(module, exports, __webpack_require__) { + +var global = __webpack_require__(11) + , core = __webpack_require__(3) + , ctx = __webpack_require__(19) + , hide = __webpack_require__(21) + , PROTOTYPE = 'prototype'; + +var $export = function(type, name, source){ + var IS_FORCED = type & $export.F + , IS_GLOBAL = type & $export.G + , IS_STATIC = type & $export.S + , IS_PROTO = type & $export.P + , IS_BIND = type & $export.B + , IS_WRAP = type & $export.W + , exports = IS_GLOBAL ? core : core[name] || (core[name] = {}) + , expProto = exports[PROTOTYPE] + , target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE] + , key, own, out; + if(IS_GLOBAL)source = name; + for(key in source){ + // contains in native + own = !IS_FORCED && target && target[key] !== undefined; + if(own && key in exports)continue; + // export native or passed + out = own ? target[key] : source[key]; + // prevent global pollution for namespaces + exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] + // bind timers to global for call from export context + : IS_BIND && own ? ctx(out, global) + // wrap global constructors for prevent change them in library + : IS_WRAP && target[key] == out ? (function(C){ + var F = function(a, b, c){ + if(this instanceof C){ + switch(arguments.length){ + case 0: return new C; + case 1: return new C(a); + case 2: return new C(a, b); + } return new C(a, b, c); + } return C.apply(this, arguments); + }; + F[PROTOTYPE] = C[PROTOTYPE]; + return F; + // make static versions for prototype methods + })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; + // export proto methods to core.%CONSTRUCTOR%.methods.%NAME% + if(IS_PROTO){ + (exports.virtual || (exports.virtual = {}))[key] = out; + // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME% + if(type & $export.R && expProto && !expProto[key])hide(expProto, key, out); + } + } +}; +// type bitmap +$export.F = 1; // forced +$export.G = 2; // global +$export.S = 4; // static +$export.P = 8; // proto +$export.B = 16; // bind +$export.W = 32; // wrap +$export.U = 64; // safe +$export.R = 128; // real proto method for `library` +module.exports = $export; + +/***/ }), +/* 11 */ +/***/ (function(module, exports) { + +// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 +var global = module.exports = typeof window != 'undefined' && window.Math == Math + ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')(); +if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef + +/***/ }), +/* 12 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = { "default": __webpack_require__(148), __esModule: true }; + +/***/ }), +/* 13 */ +/***/ (function(module, exports) { + +module.exports = function(it){ + return typeof it === 'object' ? it !== null : typeof it === 'function'; +}; + +/***/ }), +/* 14 */ +/***/ (function(module, exports, __webpack_require__) { + +var anObject = __webpack_require__(16) + , IE8_DOM_DEFINE = __webpack_require__(99) + , toPrimitive = __webpack_require__(76) + , dP = Object.defineProperty; + +exports.f = __webpack_require__(17) ? Object.defineProperty : function defineProperty(O, P, Attributes){ + anObject(O); + P = toPrimitive(P, true); + anObject(Attributes); + if(IE8_DOM_DEFINE)try { + return dP(O, P, Attributes); + } catch(e){ /* empty */ } + if('get' in Attributes || 'set' in Attributes)throw TypeError('Accessors not supported!'); + if('value' in Attributes)O[P] = Attributes.value; + return O; +}; + +/***/ }), +/* 15 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.SharedObjectEventTypes = exports.FailoverSubscriberEventTypes = exports.RTMPSubscriberEventTypes = exports.RTCSubscriberEventTypes = exports.SubscriberEventTypes = exports.FailoverPublisherEventTypes = exports.RTMPPublisherEventTypes = exports.RTCPublisherEventTypes = exports.PublisherEventTypes = exports.SharedObjectEvent = exports.SubscriberEvent = exports.PublisherEvent = exports.Event = undefined; + +var _getPrototypeOf = __webpack_require__(6); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _possibleConstructorReturn2 = __webpack_require__(8); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = __webpack_require__(7); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _publisherEvent = __webpack_require__(82); + +Object.defineProperty(exports, 'PublisherEventTypes', { + enumerable: true, + get: function get() { + return _publisherEvent.PublisherEventTypes; + } +}); +Object.defineProperty(exports, 'RTCPublisherEventTypes', { + enumerable: true, + get: function get() { + return _publisherEvent.RTCPublisherEventTypes; + } +}); +Object.defineProperty(exports, 'RTMPPublisherEventTypes', { + enumerable: true, + get: function get() { + return _publisherEvent.RTMPPublisherEventTypes; + } +}); +Object.defineProperty(exports, 'FailoverPublisherEventTypes', { + enumerable: true, + get: function get() { + return _publisherEvent.FailoverPublisherEventTypes; + } +}); + +var _subscriberEvent = __webpack_require__(83); + +Object.defineProperty(exports, 'SubscriberEventTypes', { + enumerable: true, + get: function get() { + return _subscriberEvent.SubscriberEventTypes; + } +}); +Object.defineProperty(exports, 'RTCSubscriberEventTypes', { + enumerable: true, + get: function get() { + return _subscriberEvent.RTCSubscriberEventTypes; + } +}); +Object.defineProperty(exports, 'RTMPSubscriberEventTypes', { + enumerable: true, + get: function get() { + return _subscriberEvent.RTMPSubscriberEventTypes; + } +}); +Object.defineProperty(exports, 'FailoverSubscriberEventTypes', { + enumerable: true, + get: function get() { + return _subscriberEvent.FailoverSubscriberEventTypes; + } +}); + +var _sharedobjectEvent = __webpack_require__(56); + +Object.defineProperty(exports, 'SharedObjectEventTypes', { + enumerable: true, + get: function get() { + return _sharedobjectEvent.SharedObjectEventTypes; + } +}); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Base class for all events. + */ +var Event = function () { + function Event(type) { + var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + (0, _classCallCheck3.default)(this, Event); + + this._type = type; + this._data = data; + } + + /** + * Type accessor. + * + * @type {String} + */ + + + (0, _createClass3.default)(Event, [{ + key: 'type', + get: function get() { + return this._type; + } + + /** + * Data related to event. + * + * @type {Object} + */ + + }, { + key: 'data', + get: function get() { + return this._data; + } + }]); + return Event; +}(); + +/** + * Base Publisher-related Event. + * + * @extends Event + */ + + +var PublisherEvent = function (_Event) { + (0, _inherits3.default)(PublisherEvent, _Event); + + function PublisherEvent(type, publisher, data) { + (0, _classCallCheck3.default)(this, PublisherEvent); + + var _this = (0, _possibleConstructorReturn3.default)(this, (PublisherEvent.__proto__ || (0, _getPrototypeOf2.default)(PublisherEvent)).call(this, type, data)); + + _this._publisher = publisher; + return _this; + } + + /** + * The Publisher instance that dispatched the event. + * + * @type {Object} + * + * @see Red5ProPublisher + * @see RTCPublisher + * @see RTMPPublisher + */ + + + (0, _createClass3.default)(PublisherEvent, [{ + key: 'publisher', + get: function get() { + return this._publisher; + } + }]); + return PublisherEvent; +}(Event); + +/** + * Base Subscriber-related Event. + * + * @extends Event + */ + + +var SubscriberEvent = function (_Event2) { + (0, _inherits3.default)(SubscriberEvent, _Event2); + + function SubscriberEvent(type, subscriber, data) { + (0, _classCallCheck3.default)(this, SubscriberEvent); + + var _this2 = (0, _possibleConstructorReturn3.default)(this, (SubscriberEvent.__proto__ || (0, _getPrototypeOf2.default)(SubscriberEvent)).call(this, type, data)); + + _this2._subscriber = subscriber; + return _this2; + } + + /** + * The Subscriber instance that dispatched the event. + * + * @type {Object} + * + * @see Red5ProSubscriber + * @see RTCSubscriber + * @see RTMPSubscriber + * @see HLSubscriber + */ + + + (0, _createClass3.default)(SubscriberEvent, [{ + key: 'subscriber', + get: function get() { + return this._subscriber; + } + }]); + return SubscriberEvent; +}(Event); + +/** + * Base SharedObject-related Event. + * + * @extends Event + */ + + +var SharedObjectEvent = function (_Event3) { + (0, _inherits3.default)(SharedObjectEvent, _Event3); + + function SharedObjectEvent(type, sharedObjectName, data) { + (0, _classCallCheck3.default)(this, SharedObjectEvent); + + var _this3 = (0, _possibleConstructorReturn3.default)(this, (SharedObjectEvent.__proto__ || (0, _getPrototypeOf2.default)(SharedObjectEvent)).call(this, type, data)); + + _this3._name = sharedObjectName; + return _this3; + } + + /** + * The name of the Shared Object. + * + * @type {String} + * + * @see {Red5ProSharedObject} + */ + + + (0, _createClass3.default)(SharedObjectEvent, [{ + key: 'name', + get: function get() { + return this._name; + } + }]); + return SharedObjectEvent; +}(Event); + +exports.Event = Event; +exports.PublisherEvent = PublisherEvent; +exports.SubscriberEvent = SubscriberEvent; +exports.SharedObjectEvent = SharedObjectEvent; + +/***/ }), +/* 16 */ +/***/ (function(module, exports, __webpack_require__) { + +var isObject = __webpack_require__(13); +module.exports = function(it){ + if(!isObject(it))throw TypeError(it + ' is not an object!'); + return it; +}; + +/***/ }), +/* 17 */ +/***/ (function(module, exports, __webpack_require__) { + +// Thank's IE8 for his funny defineProperty +module.exports = !__webpack_require__(25)(function(){ + return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7; +}); + +/***/ }), +/* 18 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = { "default": __webpack_require__(155), __esModule: true }; + +/***/ }), +/* 19 */ +/***/ (function(module, exports, __webpack_require__) { + +// optional / simple context binding +var aFunction = __webpack_require__(63); +module.exports = function(fn, that, length){ + aFunction(fn); + if(that === undefined)return fn; + switch(length){ + case 1: return function(a){ + return fn.call(that, a); + }; + case 2: return function(a, b){ + return fn.call(that, a, b); + }; + case 3: return function(a, b, c){ + return fn.call(that, a, b, c); + }; + } + return function(/* ...args */){ + return fn.apply(that, arguments); + }; +}; + +/***/ }), +/* 20 */ +/***/ (function(module, exports) { + +var hasOwnProperty = {}.hasOwnProperty; +module.exports = function(it, key){ + return hasOwnProperty.call(it, key); +}; + +/***/ }), +/* 21 */ +/***/ (function(module, exports, __webpack_require__) { + +var dP = __webpack_require__(14) + , createDesc = __webpack_require__(38); +module.exports = __webpack_require__(17) ? function(object, key, value){ + return dP.f(object, key, createDesc(1, value)); +} : function(object, key, value){ + object[key] = value; + return object; +}; + +/***/ }), +/* 22 */ +/***/ (function(module, exports, __webpack_require__) { + +// to indexed object, toObject with fallback for non-array-like ES3 strings +var IObject = __webpack_require__(68) + , defined = __webpack_require__(46); +module.exports = function(it){ + return IObject(defined(it)); +}; + +/***/ }), +/* 23 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var WILDCARD = '*'; +var WILDCARD_KEY = 'RED5PRO'; + +/** + * Base class for an Event Emitter. + */ + +var EventEmitter = function () { + function EventEmitter() { + (0, _classCallCheck3.default)(this, EventEmitter); + + this._callbacks = {}; + this._callbacks[WILDCARD_KEY] = []; + } + + /** + * Invokes event handlers. + * + * @param {Array} callbacks + * @param {Event} event + * + * @private + */ + + + (0, _createClass3.default)(EventEmitter, [{ + key: '_notify', + value: function _notify(callbacks, event) { + var i = void 0, + length = callbacks.length; + for (i = 0; i < length; i++) { + callbacks[i](event); + } + } + + /** + * Assign a callback handler to an event type. + * + * @param {String} type + * @param {Function} fn + */ + + }, { + key: 'on', + value: function on(type, fn) { + if (typeof fn !== 'function') { + return; + } + + if (type === WILDCARD) { + this._callbacks[WILDCARD_KEY].push(fn); + return; + } + + if (this._callbacks[type] === undefined) { + this._callbacks[type] = []; + } + + if (this._callbacks[type].indexOf(fn) === -1) { + this._callbacks[type].push(fn); + } + } + + /** + * Remove a callback handler for an event type. + * + * @param {String} type + * @param {Function} fn + */ + + }, { + key: 'off', + value: function off(type, fn) { + var map = this._callbacks[type]; + if (type === WILDCARD) { + map = this._callbacks[WILDCARD_KEY]; + } + if (map) { + var index = map.indexOf(fn); + if (index !== -1) { + map.splice(index, 1); + } + } + } + + /** + * Dispatch an event to be handled by any assigned callbacks. + * + * @param {Event} event + */ + + }, { + key: 'trigger', + value: function trigger(event) { + var type = event.type; + if (this._callbacks[type]) { + this._notify(this._callbacks[type], event); + } + this._notify(this._callbacks[WILDCARD_KEY], event); + } + }]); + return EventEmitter; +}(); + +exports.default = EventEmitter; + +/***/ }), +/* 24 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PlaybackControlsImpl = exports.PlaybackControls = exports.PlaybackController = undefined; + +var _getPrototypeOf = __webpack_require__(6); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = __webpack_require__(8); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = __webpack_require__(7); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _eventEmitter = __webpack_require__(23); + +var _eventEmitter2 = _interopRequireDefault(_eventEmitter); + +var _browser = __webpack_require__(4); + +var _browser2 = _interopRequireDefault(_browser); + +var _slider = __webpack_require__(124); + +var _slider2 = _interopRequireDefault(_slider); + +var _event = __webpack_require__(86); + +var _state = __webpack_require__(35); + +var _log = __webpack_require__(2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var NAME = 'PlaybackControls'; + +/** + * Interface contract for playback controller actions. + * + * @extends EventEmitter + */ + +var SubscriberPlaybackController = function (_EventEmitter) { + (0, _inherits3.default)(SubscriberPlaybackController, _EventEmitter); + + function SubscriberPlaybackController() { + (0, _classCallCheck3.default)(this, SubscriberPlaybackController); + return (0, _possibleConstructorReturn3.default)(this, (SubscriberPlaybackController.__proto__ || (0, _getPrototypeOf2.default)(SubscriberPlaybackController)).call(this)); + } + + /** + * Request to start playing the stream. + */ + + + (0, _createClass3.default)(SubscriberPlaybackController, [{ + key: 'play', + value: function play() {} + /** + * Request to pause playback of stream. + */ + + }, { + key: 'pause', + value: function pause() {} + /** + * Request to resume playback od stream. + */ + + }, { + key: 'resume', + value: function resume() {} + /** + * Request to stop playback of stream. + */ + + }, { + key: 'stop', + value: function stop() {} + /** + * Request to mute the audio of the stream. + */ + + }, { + key: 'mute', + value: function mute() {} + /** + * Request to unmute the audio of the stream. + */ + + }, { + key: 'unmute', + value: function unmute() {} + /** + * Request to set volume of audio of stream. + * + * @param {Number} value + * From 0..1. + */ + + }, { + key: 'setVolume', + value: function setVolume(value) {} // eslint-disable-line no-unused-vars + /** + * Request to set playback point in time. + * + * @param {Number} value + * Either the percentage of the duration (if provided) or the time in seconds. + * @param {Number} duration + * Optional duration of video (when known through VOD) to use to determine time based on first param passed as percentage. + */ + + }, { + key: 'seekTo', + value: function seekTo(value) { + var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + } // eslint-disable-line no-unused-vars + /** + * Request to toggle fullscreen state. + */ + + }, { + key: 'toggleFullScreen', + value: function toggleFullScreen() {} + }]); + return SubscriberPlaybackController; +}(_eventEmitter2.default); + +/** + * Interface for PlaybackControls used by Subscribers with `controls` and `class="red5pro-media` defined on target elements. This interface serves as a presentation controller and playback API for target DOM elements. + * + * You can use this as a prototype for creating and providing your own custom Playback Controls. To do so: provide an implementation of this Class as the `controls` property on the initialization configuration map provided in the `init()` call of a Subscriber. + * + * TODO: Fully vet the viability of developers being adhere to this contract for custom controls. + * @private + */ + + +var SubscriberPlaybackControls = function () { + function SubscriberPlaybackControls() { + (0, _classCallCheck3.default)(this, SubscriberPlaybackControls); + } + + /** + * Returns the volume level. + * + * @return {Number} 0..1 + */ + + + (0, _createClass3.default)(SubscriberPlaybackControls, [{ + key: 'getVolume', + value: function getVolume() {} + + /** + * Sets the volume level of playback. + * + * @param {Number} value + * 0..1 + */ + + }, { + key: 'setVolume', + value: function setVolume(value) {} // eslint-disable-line no-unused-vars + + /** + * Request to set playback point in time. + * + * @param {Number} value + * Either the percentage of the duration (if provided) or the time in seconds. + * @param {Number} duration + * Optional duration of video (when known through VOD) to use to determine time based on first param passed as percentage. + */ + + }, { + key: 'setSeekTime', + value: function setSeekTime(value) { + var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + } // eslint-disable-line no-unused-vars + + /** + * Sets the playback duration of the stream, if available from VOD (Video On Demand). + * + * @param {Number} value + * In seconds. + */ + + }, { + key: 'setPlaybackDuration', + value: function setPlaybackDuration(value) {} // eslint-disable-line no-unused-vars + + /** + * Returns the current playback state. + * + * @return {Number} + * @see {PlaybackState} + */ + + }, { + key: 'getState', + value: function getState() {} + + /** + * Set the current playback state. + * + * @param {Number} state + * @see {PlaybackState} + */ + + }, { + key: 'setState', + value: function setState(state) {} // eslint-disable-line no-unused-vars + + /** + * Sets playback as VOD (Video On Demand) type. + * + * @param {Boolean} value + */ + + }, { + key: 'setAsVOD', + value: function setAsVOD(value) {} // eslint-disable-line no-unused-vars + + /** + * Enables controls and event handlers. + * + * @private + */ + + }, { + key: 'enable', + value: function enable(value) {} // eslint-disable-line no-unused-vars + + }]); + return SubscriberPlaybackControls; +}(); + +/** + * Default implementation of `SubscriberPlaybackControls` used internally in the SDK. + * + * @private + */ + + +var SubscriberPlaybackControlsImpl = function (_SubscriberPlaybackCo) { + (0, _inherits3.default)(SubscriberPlaybackControlsImpl, _SubscriberPlaybackCo); + + function SubscriberPlaybackControlsImpl(player, container) { + (0, _classCallCheck3.default)(this, SubscriberPlaybackControlsImpl); + + var _this2 = (0, _possibleConstructorReturn3.default)(this, (SubscriberPlaybackControlsImpl.__proto__ || (0, _getPrototypeOf2.default)(SubscriberPlaybackControlsImpl)).call(this)); + + _this2.player = player; + _this2.container = container; + _this2._controlbar = undefined; + _this2._playPauseButton = undefined; + _this2._muteButton = undefined; + _this2._volumeField = undefined; + _this2._seekTimeField = undefined; + _this2._timeField = undefined; + _this2._fullScreenButton = undefined; + _this2._state = _state.PlaybackState.IDLE; + _this2._mutedState = false; + _this2._resumeAfterSeek = false; + _this2._playbackDuration = 0; + _this2._volumeValue = 1; + _this2._onPlayPauseClickBound = _this2._onPlayPauseClick.bind(_this2); + _this2.decorate(_this2.container); + return _this2; + } + + /** + * Decorates target container with playback control elements. + * + * @param {Element} container + * + * @private + */ + + + (0, _createClass3.default)(SubscriberPlaybackControlsImpl, [{ + key: 'decorate', + value: function decorate(container) { + (0, _log.debug)(NAME, '[decorate]'); + var controlbar = _browser2.default.createElement('div'); + controlbar.classList.add('red5pro-media-control-bar'); + this._playPauseButton = this._createPlayPauseButton(); + this._muteButton = this._createMuteButton(); + this._volumeField = this._createVolumeControl(); + this._seekTimeField = this._createSeekControl(); + this._timeField = this._createPlaybackTime(); + this._fullScreenButton = this._createFullScreenToggle(); + controlbar.appendChild(this._playPauseButton); + controlbar.appendChild(this._timeField); + controlbar.appendChild(this._seekTimeField.view); + controlbar.appendChild(this._muteButton); + controlbar.appendChild(this._volumeField.view); + controlbar.appendChild(this._fullScreenButton); + container.appendChild(controlbar); + this._controlbar = controlbar; + + if (_browser2.default.isTouchEnabled()) { + controlbar.classList.add('red5pro-media-control-bar-show'); + // this.container.addEventListener('click', () => { + // controlbar.classList.toggle('red5pro-media-control-bar-show') + // }) + } else { + this.container.addEventListener('mouseover', function () { + controlbar.classList.add('red5pro-media-control-bar-show'); + }); + this.container.addEventListener('mouseout', function () { + controlbar.classList.remove('red5pro-media-control-bar-show'); + }); + } + + this.setState(_state.PlaybackState.IDLE).onFullScreenChange(false).setSeekTime(0).enable(false); + } + + /** + * Click handler for play/pause control. + * + * @private + */ + + }, { + key: '_onPlayPauseClick', + value: function _onPlayPauseClick() { + if (this.getState() === _state.PlaybackState.PLAYING) { + this.player.pause(); + } else if (this.getState() === _state.PlaybackState.PAUSED) { + this.player.resume(); + } else { + this.player.play(); + } + } + + /** + * Creates play/pause control. + * + * @private + */ + + }, { + key: '_createPlayPauseButton', + value: function _createPlayPauseButton() { + var button = _browser2.default.createElement('button'); + button.setAttribute('aria-label', 'Toggle Playback'); + button.classList.add('red5pro-media-control-element'); + button.classList.add('red5pro-media-element-button'); + button.classList.add('red5pro-media-playpause-button'); + return button; + } + + /** + * Creates mute/unmute control. + * + * @private + */ + + }, { + key: '_createMuteButton', + value: function _createMuteButton() { + var self = this; + var button = _browser2.default.createElement('button'); + button.setAttribute('aria-label', 'Toggle Mute Audio'); + button.classList.add('red5pro-media-control-element'); + button.classList.add('red5pro-media-element-button'); + button.classList.add('red5pro-media-muteunmute-button'); + button.addEventListener('click', function () { + if (self.getMutedState()) { + self.player.unmute(); + self.setMutedState(false); + } else { + self.player.mute(); + self.setMutedState(true); + } + }); + return button; + } + + /** + * Creates volume control. + * + * @private + */ + + }, { + key: '_createVolumeControl', + value: function _createVolumeControl() { + var self = this; + var slider = new _slider2.default('volume'); + slider.view.classList.add('red5pro-media-control-element'); + slider.view.classList.add('red5pro-media-volume-slider'); + slider.view.classList.add('red5pro-media-slider'); + slider.on(_event.SliderEventTypes.CHANGE, function (event) { + var percentage = Number(event.data); + self.player.setVolume(percentage); + }); + return slider; + } + + /** + * Creates seek control. + * + * @private + */ + + }, { + key: '_createSeekControl', + value: function _createSeekControl() { + var self = this; + var slider = new _slider2.default('seek'); + slider.view.classList.add('red5pro-media-control-element'); + slider.view.classList.add('red5pro-media-seektime-slider'); + slider.view.classList.add('red5pro-media-slider'); + slider.on(_event.SliderEventTypes.CHANGE_START, function () { + if (self.getState() === _state.PlaybackState.PLAYING) { + self._resumeAfterSeek = true; + self.player.pause(); + } + }); + slider.on(_event.SliderEventTypes.CHANGE, function (event) { + var percentage = Number(event.data); + self.player.seekTo(percentage, self._playbackDuration === 0 ? undefined : self._playbackDuration); + self.setSeekTime(percentage * self._playbackDuration, self._playbackDuration); + }); + slider.on(_event.SliderEventTypes.CHANGE_COMPLETE, function () { + if (self._resumeAfterSeek && self.getState() === _state.PlaybackState.PAUSED) { + self._resumeAfterSeek = false; + self.player.resume(); + } + }); + return slider; + } + + /** + * Creates playback time field. + * + * @private + */ + + }, { + key: '_createPlaybackTime', + value: function _createPlaybackTime() { + var span = _browser2.default.createElement('span'); + var text = _browser2.default.createElement('text', 'hello!'); + span.classList.add('red5pro-media-control-element'); + span.classList.add('red5pro-media-time-field'); + span.appendChild(text); + return span; + } + + /** + * Create fullscreen toggle control. + * + * @private + */ + + }, { + key: '_createFullScreenToggle', + value: function _createFullScreenToggle() { + var self = this; + var button = _browser2.default.createElement('button'); + button.setAttribute('aria-label', 'Toggle Fullscreen'); + button.classList.add('red5pro-media-control-element'); + button.classList.add('red5pro-media-element-button'); + button.classList.add('red5pro-media-fullscreen-button'); + button.addEventListener('click', function () { + self.player.toggleFullScreen(); + }); + return button; + } + + /** + * Enables controls and event handlers. + * + * @private + */ + + }, { + key: 'enable', + value: function enable(value) { + if (value) { + this._playPauseButton.classList.remove('red5pro-media-element-button-disabled'); + this._playPauseButton.addEventListener('click', this._onPlayPauseClickBound); + } else { + this._playPauseButton.classList.add('red5pro-media-element-button-disabled'); + this._playPauseButton.removeEventListener('click', this._onPlayPauseClickBound); + } + } + + /** + * Formats the time value. + * + * @param {value} Number + * @return {String} + */ + + }, { + key: 'formatTime', + value: function formatTime(value) { + var hrs = 0; + var mins = value === 0 ? 0 : parseInt(value / 60); + var secs = 0; + if (mins >= 60) { + hrs = parseInt(mins / 60); + mins = mins % 60; + } + secs = value === 0 ? 0 : parseInt(value % 60); + + var formattedArr = hrs < 10 ? ['0' + hrs] : [hrs]; + formattedArr.push(mins < 10 ? ['0' + mins] : [mins]); + formattedArr.push(secs < 10 ? ['0' + secs] : [secs]); + return formattedArr.join(':'); + } + + /** + * Returns the volume level. + * + * @return {Number} 0..1 + */ + + }, { + key: 'getVolume', + value: function getVolume() { + return this._volumeValue; + } + + /** + * Sets the volume level of playback. + * + * @param {Number} value + * 0..1 + */ + + }, { + key: 'setVolume', + value: function setVolume(value) { + this._volumeField.value = value; + this._volumeValue = value; + if (value === 0) { + this.setMutedState(true); + } else if (this.getMutedState()) { + this.setMutedState(false); + } + return this; + } + + /** + * Request to set playback point in time. + * + * @param {Number} value + * Either the percentage of the duration (if provided) or the time in seconds. + * @param {Number} duration + * Optional duration of video (when known through VOD) to use to determine time based on first param passed as percentage. + */ + + }, { + key: 'setSeekTime', + value: function setSeekTime(value) { + var length = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + + this._seekTimeField.value = length === 0 ? 0 : value / length; + if (this._playbackDuration !== 0 && parseInt(this._playbackDuration) <= parseInt(value)) { + this._seekTimeField.value = 1; + } + this._timeField.innerText = this.formatTime(Math.floor(value)); + return this; + } + + /** + * Sets the playback duration of the stream, if available from VOD (Video On Demand). + * + * @param {Number} value + * In seconds. + */ + + }, { + key: 'setPlaybackDuration', + value: function setPlaybackDuration(value) { + (0, _log.debug)(NAME, '[setplaybackduration]: ' + value); + this._playbackDuration = value; + } + + /** + * Returns the current playback state. + * + * @return {Number} + * @see {PlaybackState} + */ + + }, { + key: 'getState', + value: function getState() { + return this._state; + } + + /** + * Set the current playback state. + * + * @param {Number} state + * @see {PlaybackState} + */ + + }, { + key: 'setState', + value: function setState(state) { + (0, _log.debug)(NAME, '[setState]: ' + _state.PlaybackStateReadable[state]); + this._state = state; + this.onStateChange(this._state); + return this; + } + + /** + * Returns the current state of the playback being muted. + * This differs from just the volume level being 0. The controls can be muted, but have a volume level greater than 0 - meaning, unmute will return back to the volume level previously set. + * + * @return {Boolean} + */ + + }, { + key: 'getMutedState', + value: function getMutedState() { + return 'muted' in this.player ? this.player.muted : this._mutedState; + } + + /** + * Sets the muted state of the playback. + * + * @param {Boolean} state + */ + + }, { + key: 'setMutedState', + value: function setMutedState(state) { + this._mutedState = state; + this.onMutedStateChange(this._mutedState); + return this; + } + + /** + * Handler for change in state. + * + * @param {Number} state + * The PlaybackState + * + * @private + */ + + }, { + key: 'onStateChange', + value: function onStateChange(state) { + if (state === _state.PlaybackState.PLAYING) { + this._playPauseButton.classList.remove('red5pro-media-play-button'); + this._playPauseButton.classList.add('red5pro-media-pause-button'); + } else { + this._playPauseButton.classList.add('red5pro-media-play-button'); + this._playPauseButton.classList.remove('red5pro-media-pause-button'); + } + return this; + } + + /** + * Handler for change in mute state. + * + * @param {Boolean} state + * + * @private + */ + + }, { + key: 'onMutedStateChange', + value: function onMutedStateChange(state) { + if (state) { + this._muteButton.classList.add('red5pro-media-mute-button'); + this._muteButton.classList.remove('red5pro-media-unmute-button'); + this._volumeField.value = 0; + } else { + this._muteButton.classList.remove('red5pro-media-mute-button'); + this._muteButton.classList.add('red5pro-media-unmute-button'); + this._volumeField.value = this._volumeValue; + } + } + + /** + * Handler for change in fullscreen state. + * + * @param {Boolean} isFullScreen + * + * @private + */ + + }, { + key: 'onFullScreenChange', + value: function onFullScreenChange(isFullScreen) { + if (isFullScreen) { + this._fullScreenButton.classList.add('red5pro-media-exit-fullscreen-button'); + this._fullScreenButton.classList.remove('red5pro-media-fullscreen-button'); + } else { + this._fullScreenButton.classList.remove('red5pro-media-exit-fullscreen-button'); + this._fullScreenButton.classList.add('red5pro-media-fullscreen-button'); + } + return this; + } + + /** + * Sets playback as VOD (Video On Demand) type. + * + * @param {Boolean} value + */ + + }, { + key: 'setAsVOD', + value: function setAsVOD(isVOD) { + (0, _log.debug)(NAME, '[setAsVOD]: ' + isVOD); + if (!isVOD) { + this._seekTimeField.value = 0; + this._seekTimeField.disabled = true; + } else { + this._seekTimeField.disabled = false; + } + } + + /** + * Request to detach the control bar to provided container. + */ + + }, { + key: 'detach', + value: function detach() { + this.enable(false); + if (this._controlbar && this._controlbar.parentNode === this.container) { + this.container.removeChild(this._controlbar); + } + } + }]); + return SubscriberPlaybackControlsImpl; +}(SubscriberPlaybackControls); + +var PlaybackController = exports.PlaybackController = SubscriberPlaybackController; +var PlaybackControls = exports.PlaybackControls = SubscriberPlaybackControls; +var PlaybackControlsImpl = exports.PlaybackControlsImpl = SubscriberPlaybackControlsImpl; + +/***/ }), +/* 25 */ +/***/ (function(module, exports) { + +module.exports = function(exec){ + try { + return !!exec(); + } catch(e){ + return true; + } +}; + +/***/ }), +/* 26 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var $at = __webpack_require__(181)(true); + +// 21.1.3.27 String.prototype[@@iterator]() +__webpack_require__(69)(String, 'String', function(iterated){ + this._t = String(iterated); // target + this._i = 0; // next index +// 21.1.5.2.1 %StringIteratorPrototype%.next() +}, function(){ + var O = this._t + , index = this._i + , point; + if(index >= O.length)return {value: undefined, done: true}; + point = $at(O, index); + this._i += point.length; + return {value: point, done: false}; +}); + +/***/ }), +/* 27 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(186); +var global = __webpack_require__(11) + , hide = __webpack_require__(21) + , Iterators = __webpack_require__(30) + , TO_STRING_TAG = __webpack_require__(9)('toStringTag'); + +for(var collections = ['NodeList', 'DOMTokenList', 'MediaList', 'StyleSheetList', 'CSSRuleList'], i = 0; i < 5; i++){ + var NAME = collections[i] + , Collection = global[NAME] + , proto = Collection && Collection.prototype; + if(proto && !proto[TO_STRING_TAG])hide(proto, TO_STRING_TAG, NAME); + Iterators[NAME] = Iterators.Array; +} + +/***/ }), +/* 28 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/** + * Deep-defines an `Object` in place with namespaced attribute value. + * + * @private + */ + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.isObjectEmpty = exports.metadataResolutionToObject = exports.deepCopy = exports.deepDefine = undefined; + +var _keys = __webpack_require__(60); + +var _keys2 = _interopRequireDefault(_keys); + +var _stringify = __webpack_require__(12); + +var _stringify2 = _interopRequireDefault(_stringify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var deepDefine = exports.deepDefine = function deepDefine(object, paths, value) { + var i = 0; + var tail = object; + var prop = paths.pop(); + var length = paths.length; + for (i; i < length; i++) { + var path = paths[i]; + tail[path] = tail[path] || {}; + tail = tail[path]; + } + tail[prop] = value; +}; + +/** + * Deep-copy utilizing JSON API. + * + * @private + */ +var deepCopy = exports.deepCopy = function deepCopy(obj) { + var str = (0, _stringify2.default)(obj); + return JSON.parse(str); +}; + +/** + * Simple util to parse resolution from metadata. + * + * @param {String} value + * The resolution value from metadata: e.g, `640,480`. + * @return {Object} + * The structured dimensions Object with `width` and `height` properties. + * + * @private + */ +var metadataResolutionToObject = exports.metadataResolutionToObject = function metadataResolutionToObject(value) { + if (typeof value === 'string') { + var dims = value.split(','); + return { + width: parseInt(dims[0]), + height: parseInt(dims[1]) + }; + } + return value; +}; + +/** + * Utility check if providing Object is empty (without any properties. + * + * @private + */ +var isObjectEmpty = exports.isObjectEmpty = function isObjectEmpty(obj) { + return (0, _keys2.default)(obj).length === 0 && obj.constructor === Object; +}; + +/***/ }), +/* 29 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +exports.__esModule = true; + +var _assign = __webpack_require__(136); + +var _assign2 = _interopRequireDefault(_assign); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = _assign2.default || function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target; +}; + +/***/ }), +/* 30 */ +/***/ (function(module, exports) { + +module.exports = {}; + +/***/ }), +/* 31 */ +/***/ (function(module, exports, __webpack_require__) { + +var META = __webpack_require__(53)('meta') + , isObject = __webpack_require__(13) + , has = __webpack_require__(20) + , setDesc = __webpack_require__(14).f + , id = 0; +var isExtensible = Object.isExtensible || function(){ + return true; +}; +var FREEZE = !__webpack_require__(25)(function(){ + return isExtensible(Object.preventExtensions({})); +}); +var setMeta = function(it){ + setDesc(it, META, {value: { + i: 'O' + ++id, // object ID + w: {} // weak collections IDs + }}); +}; +var fastKey = function(it, create){ + // return primitive with prefix + if(!isObject(it))return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it; + if(!has(it, META)){ + // can't set metadata to uncaught frozen object + if(!isExtensible(it))return 'F'; + // not necessary to add metadata + if(!create)return 'E'; + // add missing metadata + setMeta(it); + // return object ID + } return it[META].i; +}; +var getWeak = function(it, create){ + if(!has(it, META)){ + // can't set metadata to uncaught frozen object + if(!isExtensible(it))return true; + // not necessary to add metadata + if(!create)return false; + // add missing metadata + setMeta(it); + // return hash weak collections IDs + } return it[META].w; +}; +// add metadata on freeze-family methods calling +var onFreeze = function(it){ + if(FREEZE && meta.NEED && isExtensible(it) && !has(it, META))setMeta(it); + return it; +}; +var meta = module.exports = { + KEY: META, + NEED: false, + fastKey: fastKey, + getWeak: getWeak, + onFreeze: onFreeze +}; + +/***/ }), +/* 32 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.14 / 15.2.3.14 Object.keys(O) +var $keys = __webpack_require__(108) + , enumBugKeys = __webpack_require__(67); + +module.exports = Object.keys || function keys(O){ + return $keys(O, enumBugKeys); +}; + +/***/ }), +/* 33 */ +/***/ (function(module, exports, __webpack_require__) { + +// 7.1.13 ToObject(argument) +var defined = __webpack_require__(46); +module.exports = function(it){ + return Object(defined(it)); +}; + +/***/ }), +/* 34 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PlaybackVideoEncoder = exports.PlaybackAudioEncoder = exports.PlaybackTypes = undefined; + +var _freeze = __webpack_require__(18); + +var _freeze2 = _interopRequireDefault(_freeze); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Enumeration of Playback Types. + */ +var PlaybackTypes = exports.PlaybackTypes = (0, _freeze2.default)({ + RTC: 'rtc', + RTMP: 'rtmp', + HLS: 'hls' +}); + +/** + * Enumeration of Audio Encoder types to request for Playback + */ +var PlaybackAudioEncoder = exports.PlaybackAudioEncoder = (0, _freeze2.default)({ + OPUS: 'Opus', + PCMU: 'PCMU', + PCMA: 'PCMA', + SPEEX: 'Speex', + NONE: 'NONE' +}); + +/** + * Enumeration of Video Encoder types to request for Playback. + */ +var PlaybackVideoEncoder = exports.PlaybackVideoEncoder = (0, _freeze2.default)({ + VP8: 'VP8', + H264: 'H264', + NONE: 'NONE' +}); + +/***/ }), +/* 35 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PlaybackStateReadable = exports.PlaybackState = undefined; + +var _freeze = __webpack_require__(18); + +var _freeze2 = _interopRequireDefault(_freeze); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Enumeration of Playback State. + * + * @see {SubscriberPlaybackControls} + */ +var PlaybackState = exports.PlaybackState = (0, _freeze2.default)({ + UNAVAILABLE: 1000, + AVAILABLE: 0, + IDLE: 1, + PLAYING: 2, + PAUSED: 3 +}); + +/** + * Human readable playback state. + * + * @see {SubscriberPlaybackControls} + * @private + */ +var PlaybackStateReadable = exports.PlaybackStateReadable = (0, _freeze2.default)({ + 1000: 'Playback.UNAVAILABLE', + 0: 'Playback.AVAILABLE', + 1: 'Playback.IDLE', + 2: 'Playback.PLAYING', + 3: 'Playback.PAUSED' +}); + +/***/ }), +/* 36 */ +/***/ (function(module, exports) { + +var toString = {}.toString; + +module.exports = function(it){ + return toString.call(it).slice(8, -1); +}; + +/***/ }), +/* 37 */ +/***/ (function(module, exports, __webpack_require__) { + +var ctx = __webpack_require__(19) + , call = __webpack_require__(102) + , isArrayIter = __webpack_require__(100) + , anObject = __webpack_require__(16) + , toLength = __webpack_require__(52) + , getIterFn = __webpack_require__(79) + , BREAK = {} + , RETURN = {}; +var exports = module.exports = function(iterable, entries, fn, that, ITERATOR){ + var iterFn = ITERATOR ? function(){ return iterable; } : getIterFn(iterable) + , f = ctx(fn, that, entries ? 2 : 1) + , index = 0 + , length, step, iterator, result; + if(typeof iterFn != 'function')throw TypeError(iterable + ' is not iterable!'); + // fast case for arrays with default iterator + if(isArrayIter(iterFn))for(length = toLength(iterable.length); length > index; index++){ + result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]); + if(result === BREAK || result === RETURN)return result; + } else for(iterator = iterFn.call(iterable); !(step = iterator.next()).done; ){ + result = call(iterator, f, step.value, entries); + if(result === BREAK || result === RETURN)return result; + } +}; +exports.BREAK = BREAK; +exports.RETURN = RETURN; + +/***/ }), +/* 38 */ +/***/ (function(module, exports) { + +module.exports = function(bitmap, value){ + return { + enumerable : !(bitmap & 1), + configurable: !(bitmap & 2), + writable : !(bitmap & 4), + value : value + }; +}; + +/***/ }), +/* 39 */ +/***/ (function(module, exports, __webpack_require__) { + +var def = __webpack_require__(14).f + , has = __webpack_require__(20) + , TAG = __webpack_require__(9)('toStringTag'); + +module.exports = function(it, tag, stat){ + if(it && !has(it = stat ? it : it.prototype, TAG))def(it, TAG, {configurable: true, value: tag}); +}; + +/***/ }), +/* 40 */ +/***/ (function(module, exports) { + + + +/***/ }), +/* 41 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.RTCSessionDescription = exports.RTCIceCandidate = exports.RTCPeerConnection = exports.updateBandwidth = exports.forceUserMedia = exports.getUserMedia = exports.isSupported = exports.determineSupportedResolution = exports.quickResolutionSupport = undefined; + +var _stringify = __webpack_require__(12); + +var _stringify2 = _interopRequireDefault(_stringify); + +var _browser = __webpack_require__(4); + +var _browser2 = _interopRequireDefault(_browser); + +var _promise = __webpack_require__(5); + +var _util = __webpack_require__(88); + +var _object = __webpack_require__(28); + +var _log = __webpack_require__(2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// import { NoSupportedCameraResolutionsError } from '../exception/errors' + +// Resolutions borrowed from https://github.com/webrtcHacks/WebRTC-Camera-Resolution/blob/master/js/resolutionScan.js +var formats = [{ + "label": "4K(UHD)", + "width": 3840, + "height": 2160 +}, { + "label": "1080p(FHD)", + "width": 1920, + "height": 1080 +}, { + "label": "UXGA", + "width": 1600, + "height": 1200 +}, { + "label": "720p(HD)", + "width": 1280, + "height": 720 +}, { + "label": "SVGA", + "width": 800, + "height": 600 +}, { + "label": "VGA", + "width": 640, + "height": 480 +}, { + "label": "360p(nHD)", + "width": 640, + "height": 360 +}, { + "label": "CIF", + "width": 352, + "height": 288 +}, { + "label": "QVGA", + "width": 320, + "height": 240 +}, { + "label": "QCIF", + "width": 176, + "height": 144 +}, { + "label": "QQVGA", + "width": 160, + "height": 120 +}]; + +/** + * Detects if resolutions are defined on the provied constraints. + * + * @param {Object} constraints + * The Media Constraints to test against. + * @return {Boolean} + * + * @private + */ +var hasResolutionsDefined = function hasResolutionsDefined(constraints) { + return constraints.hasOwnProperty('video') && (constraints.video.hasOwnProperty('width') || constraints.video.hasOwnProperty('height')); +}; + +/** + * Return value on attribute based on failover test of attribute availability on provided object. + * + * @param {Object} attribute + * @return {Object} + * + * @private + */ +var getValueFromConstraintAttribute = function getValueFromConstraintAttribute(attribute) { + return attribute.exact || attribute.ideal || attribute.max || attribute.min || attribute; +}; + +/** + * Test if video on Media Constraint is either set to `true` or if the constraints and format objects have the same dimension values. + * + * @param {Object} constraints + * @param {Object} format + * @return {Boolean} + * + * @private + */ +var isExact = (0, _util.curry)(function (constraints, format) { + if (typeof constraints.video === 'boolean') { + return true; + } + var w = constraints.video.hasOwnProperty('width') ? getValueFromConstraintAttribute(constraints.video.width) : 0; + var h = constraints.video.hasOwnProperty('height') ? getValueFromConstraintAttribute(constraints.video.height) : 0; + var confirmed = w === format.width && h === format.height; + if (confirmed) { + (0, _log.debug)('[gum:isExact]', 'Found matching resolution for ' + format.width + ', ' + format.height + '.'); + } + return confirmed; +}); + +/** + * Test if the area on the provide format is lower than the area on the Media Constraints. + * This is used in trying to find the next nearest neighbor of dimensions that the browser supports. + * + * @param {Object} constraints + * @param {Object} format + * @return {Boolean} + * + * @private + */ +var isLower = (0, _util.curry)(function (constraints, format) { + var w = constraints.video.hasOwnProperty('width') ? getValueFromConstraintAttribute(constraints.video.width) : 0; + var h = constraints.video.hasOwnProperty('height') ? getValueFromConstraintAttribute(constraints.video.height) : 0; + var desired = w * h; + var dimensions = format.width * format.height; + return dimensions < desired; +}); + +/** + * Returns filtered of Media Constraint format if matching the canned list of support form `formats`. + * + * @param {Array} formatList + * @param {Object} constraints + * @return {Array} + * + * @private + */ +var hasMatchingFormat = (0, _util.curry)(function (formatsList, constraints) { + (0, _log.debug)('[gum:hasMatchingFormat]', 'Filtered list: ' + (0, _stringify2.default)((0, _util.filter)(isExact(constraints))(formatsList), null, 2)); + return (0, _util.filter)(isExact(constraints))(formatsList).length > 0; +}); + +/** + * Returns list of filter lower resolution constraints from the provided Media constraints. + * + * @param {Array} formayList + * @param {Object} constraints + * @return {Array} + * + * @private + */ +var findLowerResolutions = (0, _util.curry)(function (formatsList, constraints) { + var resIsLower = isLower(constraints); + return (0, _util.filter)(resIsLower)(formatsList); +}); + +/** + * Allows the browser to try and determine the resolution to use based on `video: true` attribute in `getUserMedia` call. + * + * @param {Object} data + * The Media Constaints object. + * @param {Promise} p + * The `Promise` to resolve or reject on detemination of allowed Media Constraints on the browser. + * + * @private + */ +var allowBrowserToDefineResolution = function allowBrowserToDefineResolution(data, p) { + // default to `video: true` in hopes the browser can decide on its own. + data.video = true; + _browser2.default.gUM(data).then(function (media) { + p.resolve({ + media: media, + constraints: data + }); + }).catch(function (err) { + // eslint-disable-line no-unused-vars + var msg = typeof err === 'string' ? err : [err.name, err.message].join(': '); + (0, _log.debug)('[gum:getUserMedia]', 'Failure in getUserMedia: ' + msg + '. Attempting other resolution tests...'); + (0, _log.debug)('[gUM:findformat]', 'Constraints declined by browser: ' + (0, _stringify2.default)(data, null, 2)); + p.reject('Could not find proper camera for provided constraints.'); + }); +}; + +/** + * Attempts to select the best resolution based on whether the browser throws an exception when requesting `MediaStream` on `getUserMedia`. + * + * @param {Object} data + * The Media Constaints object. + * @param {Array} selections + * The listing of formats to test on. + * @param {Promise} p + * The `Promise` to resolve or reject on detemination of allowed Media Constraints on the browser. + * + * @private + */ +var findNextSelection = function findNextSelection(data, selections, p) { + if (selections.length == 0) { + // if we got here, there is no support. + allowBrowserToDefineResolution(data, p); + return; + } + var selection = selections.shift(); + data.video.width = { exact: selection.width }; + data.video.height = { exact: selection.height }; + _browser2.default.gUM(data).then(function (media) { + p.resolve({ + media: media, + constraints: data + }); + }).catch(function (err) { + // eslint-disable-line no-unused-vars + var msg = typeof err === 'string' ? err : [err.name, err.message].join(': '); + (0, _log.debug)('[gum:getUserMedia]', 'Failure in getUserMedia: ' + msg + '. Attempting other resolution tests...'); + (0, _log.debug)('[gUM:findformat]', 'Constraints declined by browser: ' + (0, _stringify2.default)(data, null, 2)); + findNextSelection(data, selections, p); + }); +}; + +/** + * Quick test if resolution is supported on the browser. + * + * @param {Object} constraints + * + * @private + */ +var quickResolutionSupport = exports.quickResolutionSupport = function quickResolutionSupport(constraints) { + var data = (0, _object.deepCopy)(constraints); + // if video: `true`, returned unscathed. + if (typeof constraints.video === 'boolean') { + return data; + } + // else, define exact. + if (constraints.video.width) { + data.video.width = { exact: getValueFromConstraintAttribute(constraints.video.width) }; + } + if (constraints.video.height) { + data.video.height = { exact: getValueFromConstraintAttribute(constraints.video.height) }; + } + return data; +}; + +/** + * Detemine the supported resolution on the browser based on the Media Constraints requested. + * + * @param {Object} constraints + * + * @private + */ +var determineSupportedResolution = exports.determineSupportedResolution = function determineSupportedResolution(constraints) { + (0, _log.debug)('[gum:determineSupportedResolution]', 'Determine next neighbor based on constraints: ' + (0, _stringify2.default)(constraints, null, 2)); + var deferred = new _promise.DeferredPromise(); + var selections = findLowerResolutions(formats)(constraints); + var data = (0, _object.deepCopy)(constraints); + findNextSelection(data, selections, deferred); + return deferred.promise; +}; + +/** + * Quick test to see if WebRTC is supported in the current environment. + * + * @return {Boolean} + * + * @private + */ +var isSupported = exports.isSupported = function isSupported() { + return _RTCPeerConnection && _RTCIceCandidate && _RTCSessionDescription; +}; + +/** + * Proxy on `getUserMedia` to try and resolve to the best possible resolution for broadcast based on Media Constraints object provided. + * + * @param {Object} constraints + * @return {Promise} + * The `Promise` will resolve or reject on properly accessing a `MediaStream` from `getUserMedia` on the browser. + * + * @private + */ +var getUserMedia = exports.getUserMedia = function getUserMedia(constraints) { + // Wrapping `getUserMedia` requests in another deferred promise so we can return the selected resolutions if successful. + var dfd = new _promise.DeferredPromise(); + var isAvailableInFormats = hasMatchingFormat(formats); + (0, _log.debug)('[gum:getUserMedia]', 'Is Available in format listing: ' + isAvailableInFormats(constraints)); + var failover = function failover(err) { + if (err) { + var msg = typeof err === 'string' ? err : [err.name, err.message].join(': '); + (0, _log.debug)('[gum:getUserMedia]', 'Failure in getUserMedia: ' + msg + '. Attempting other resolution tests...'); + } + determineSupportedResolution(constraints).then(function (res) { + dfd.resolve({ + media: res.media, + constraints: res.constraints + }); + }).catch(function (error) { + dfd.reject({ + error: error, + constraints: constraints + }); + }); + }; + if (!hasResolutionsDefined(constraints)) { + (0, _log.debug)('[gum:getUserMedia]', 'Constraints were not defined properly. Attempting failover...'); + _browser2.default.gUM(constraints).then(function (media) { + dfd.resolve({ + media: media, + constraints: constraints + }); + }).catch(failover); + } else if (isAvailableInFormats(constraints)) { + (0, _log.debug)('[gum:getUserMedia]', 'Found constraints in list. Checking quick support for faster setup with: ' + (0, _stringify2.default)(constraints, null, 2)); + // Try quick setting of `exact` resolution... + var available = quickResolutionSupport(constraints); + _browser2.default.gUM(available).then(function (media) { + dfd.resolve({ + media: media, + constraints: available + }); + }).catch(failover); + } else { + (0, _log.debug)('[gum:getUserMedia]', 'Could not find contraints in list. Attempting failover...'); + failover(); + } + return dfd.promise; +}; + +/** + * Force to call `getUserMedia` directly on the browser and bypass the resolution detection mechanism provided by other methods on this module. + * + * @private + */ +var forceUserMedia = exports.forceUserMedia = function forceUserMedia(constraints) { + return _browser2.default.gUM(constraints); +}; + +// https://github.com/muaz-khan/WebRTC-Experiment/blob/master/RTCPeerConnection/RTCPeerConnection-v1.6.js#L158 +// Muaz Khan - github.com/muaz-khan +// MIT License - www.WebRTC-Experiment.com/licence +// Documentation - github.com/muaz-khan/WebRTC-Experiment/tree/master/RTCPeerConnection +var updateBandwidth = exports.updateBandwidth = function updateBandwidth(options, sdp) { + if (_browser2.default.getIsMoz()) { + var a_index = void 0, + l_index = void 0, + front = void 0, + back = void 0; + if (options.audio) { + a_index = sdp.indexOf('m=audio'); + l_index = sdp.indexOf('\r\n', a_index); + front = sdp.slice(0, l_index); + back = sdp.slice(l_index + '\r\n'.length, sdp.length); + sdp = [front, 'b=AS:' + options.audio, back].join('\r\n'); + } + if (options.video) { + a_index = sdp.indexOf('m=video'); + l_index = sdp.indexOf('\r\n', a_index); + front = sdp.slice(0, l_index); + back = sdp.slice(l_index + '\r\n'.length, sdp.length); + sdp = [front, 'b=AS:' + options.video, back].join('\r\n'); + } + } else { + sdp = sdp.replace(/b=AS([^\r\n]+\r\n)/g, ''); + if (options.audio) { + sdp = sdp.replace(/a=mid:audio\r\n/g, 'a=mid:audio\r\nb=AS:' + options.audio + '\r\n'); + } + if (options.video) { + sdp = sdp.replace(/a=mid:video\r\n/g, 'a=mid:video\r\nb=AS:' + options.video + '\r\n'); + } + } + return sdp; +}; + +/* -- handled by adapter.js -- */ +var _RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; +var _RTCIceCandidate = window.RTCIceCandidate || window.mozRTCIceCandidate || window.webkitRTCIceCandidate; +var _RTCSessionDescription = window.RTCSessionDescription || window.mozRTCSessionDescription || window.webkitRTCSessionDescription; + +var RTCPeerConnection = exports.RTCPeerConnection = _RTCPeerConnection; +var RTCIceCandidate = exports.RTCIceCandidate = _RTCIceCandidate; +var RTCSessionDescription = exports.RTCSessionDescription = _RTCSessionDescription; + +/***/ }), +/* 42 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.create = exports.isSupported = undefined; + +var _browser = __webpack_require__(4); + +var _browser2 = _interopRequireDefault(_browser); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Test for WebSocket support in environment. + * + * @return {Boolean} + * + * @private + */ +var isSupported = exports.isSupported = function isSupported() { + return _browser2.default.supportsWebSocket(); +}; + +/** + * Attempt at creating new instance of a `WebSocket` at endpoint URL. + * + * @param {String} url + * @return {WebSocket} + * + * @private + */ +var create = exports.create = function create(url) { + return _browser2.default.createWebSocket(url); +}; + +/***/ }), +/* 43 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PlaybackView = undefined; + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _browser = __webpack_require__(4); + +var _browser2 = _interopRequireDefault(_browser); + +var _log = __webpack_require__(2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var NAME = 'R5ProPlaybackView'; +var playbackId = 'red5pro-subscriber'; + +/** + * Bridge between DOM Element view and Subscriber implementation. + * Still used, but internalized as of 4.0.0. Up for deprecation, up for discussion. + * + * @private + */ + +var PlaybackView = exports.PlaybackView = function () { + + /** + * @param {String} elementId + * The element `id` to use for playback display. + * + * @private + */ + function PlaybackView() { + var elementId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : playbackId; + (0, _classCallCheck3.default)(this, PlaybackView); + + try { + // Target video/audio element. + this._targetElement = _browser2.default.resolveElement(elementId); + } catch (e) { + (0, _log.error)(NAME, 'Could not instantiate a new instance of Red5ProSubscriber. Reason: ' + e.message); + throw e; + } + } + + /** + * Associates Subscriber instance with this view manager. + * + * @param {Object} subscriber + * The Subscriber instance. + * + * @private + */ + + + (0, _createClass3.default)(PlaybackView, [{ + key: 'attachSubscriber', + value: function attachSubscriber(subscriber) { + (0, _log.debug)(NAME, '[attachsubscriber]'); + subscriber.setView(this, _browser2.default.getElementId(this._targetElement)); + } + + /** + * Assign the `MediaStream` object to the view. + * + * @param {MediaStream} mediaStream + * + * @private + */ + + }, { + key: 'attachStream', + value: function attachStream(mediaStream) { + var autoplay = this.isAutoplay; + (0, _log.debug)(NAME, '[attachstream]'); + _browser2.default.setVideoSource(this._targetElement, mediaStream, autoplay); + } + + /** + * Returns recognized `autoplay` attribute on the DOM element. + * + * @private + */ + + }, { + key: 'isAutoplay', + get: function get() { + return _browser2.default.hasAttributeDefined(this._targetElement, 'autoplay'); + } + + /** + * Returns the DOM element. + * + * @private + */ + + }, { + key: 'view', + get: function get() { + return this._targetElement; + } + }]); + return PlaybackView; +}(); + +exports.default = PlaybackView; + +/***/ }), +/* 44 */ +/***/ (function(module, exports) { + +module.exports = function(it, Constructor, name, forbiddenField){ + if(!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)){ + throw TypeError(name + ': incorrect invocation!'); + } return it; +}; + +/***/ }), +/* 45 */ +/***/ (function(module, exports, __webpack_require__) { + +// getting tag from 19.1.3.6 Object.prototype.toString() +var cof = __webpack_require__(36) + , TAG = __webpack_require__(9)('toStringTag') + // ES3 wrong here + , ARG = cof(function(){ return arguments; }()) == 'Arguments'; + +// fallback for IE11 Script Access Denied error +var tryGet = function(it, key){ + try { + return it[key]; + } catch(e){ /* empty */ } +}; + +module.exports = function(it){ + var O, T, B; + return it === undefined ? 'Undefined' : it === null ? 'Null' + // @@toStringTag case + : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T + // builtinTag case + : ARG ? cof(O) + // ES3 arguments fallback + : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B; +}; + +/***/ }), +/* 46 */ +/***/ (function(module, exports) { + +// 7.2.1 RequireObjectCoercible(argument) +module.exports = function(it){ + if(it == undefined)throw TypeError("Can't call method on " + it); + return it; +}; + +/***/ }), +/* 47 */ +/***/ (function(module, exports) { + +module.exports = true; + +/***/ }), +/* 48 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) +var anObject = __webpack_require__(16) + , dPs = __webpack_require__(177) + , enumBugKeys = __webpack_require__(67) + , IE_PROTO = __webpack_require__(73)('IE_PROTO') + , Empty = function(){ /* empty */ } + , PROTOTYPE = 'prototype'; + +// Create object with fake `null` prototype: use iframe Object with cleared prototype +var createDict = function(){ + // Thrash, waste and sodomy: IE GC bug + var iframe = __webpack_require__(66)('iframe') + , i = enumBugKeys.length + , lt = '<' + , gt = '>' + , iframeDocument; + iframe.style.display = 'none'; + __webpack_require__(98).appendChild(iframe); + iframe.src = 'javascript:'; // eslint-disable-line no-script-url + // createDict = iframe.contentWindow.Object; + // html.removeChild(iframe); + iframeDocument = iframe.contentWindow.document; + iframeDocument.open(); + iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt); + iframeDocument.close(); + createDict = iframeDocument.F; + while(i--)delete createDict[PROTOTYPE][enumBugKeys[i]]; + return createDict(); +}; + +module.exports = Object.create || function create(O, Properties){ + var result; + if(O !== null){ + Empty[PROTOTYPE] = anObject(O); + result = new Empty; + Empty[PROTOTYPE] = null; + // add "__proto__" for Object.getPrototypeOf polyfill + result[IE_PROTO] = O; + } else result = createDict(); + return Properties === undefined ? result : dPs(result, Properties); +}; + + +/***/ }), +/* 49 */ +/***/ (function(module, exports) { + +exports.f = {}.propertyIsEnumerable; + +/***/ }), +/* 50 */ +/***/ (function(module, exports, __webpack_require__) { + +// most Object methods by ES6 should accept primitives +var $export = __webpack_require__(10) + , core = __webpack_require__(3) + , fails = __webpack_require__(25); +module.exports = function(KEY, exec){ + var fn = (core.Object || {})[KEY] || Object[KEY] + , exp = {}; + exp[KEY] = exec(fn); + $export($export.S + $export.F * fails(function(){ fn(1); }), 'Object', exp); +}; + +/***/ }), +/* 51 */ +/***/ (function(module, exports, __webpack_require__) { + +var hide = __webpack_require__(21); +module.exports = function(target, src, safe){ + for(var key in src){ + if(safe && target[key])target[key] = src[key]; + else hide(target, key, src[key]); + } return target; +}; + +/***/ }), +/* 52 */ +/***/ (function(module, exports, __webpack_require__) { + +// 7.1.15 ToLength +var toInteger = __webpack_require__(75) + , min = Math.min; +module.exports = function(it){ + return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991 +}; + +/***/ }), +/* 53 */ +/***/ (function(module, exports) { + +var id = 0 + , px = Math.random(); +module.exports = function(key){ + return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36)); +}; + +/***/ }), +/* 54 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PublishModeTypes = exports.PublishTypes = undefined; + +var _freeze = __webpack_require__(18); + +var _freeze2 = _interopRequireDefault(_freeze); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var PublishTypes = exports.PublishTypes = (0, _freeze2.default)({ + RTMP: 'rtmp', + RTC: 'rtc' +}); + +var PublishModeTypes = exports.PublishModeTypes = (0, _freeze2.default)({ + LIVE: 'live', + RECORD: 'record', + APPEND: 'append' +}); + +/***/ }), +/* 55 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.IceTransportTypes = undefined; + +var _freeze = __webpack_require__(18); + +var _freeze2 = _interopRequireDefault(_freeze); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Enumeration of Support ICE Transport types. + */ +var IceTransportTypes = exports.IceTransportTypes = (0, _freeze2.default)({ + UDP: 'udp', + TCP: 'tcp' +}); + +/***/ }), +/* 56 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.SharedObjectEventTypes = undefined; + +var _freeze = __webpack_require__(18); + +var _freeze2 = _interopRequireDefault(_freeze); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Common event types on SharedObject. + * + * @see {Red5ProSharedObject} + */ +var SharedObjectEventTypes = exports.SharedObjectEventTypes = (0, _freeze2.default)({ + CONNECT_SUCCESS: 'Connect.Success', + CONNECT_FAILURE: 'Connect.Failure', + PROPERTY_UPDATE: 'SharedObject.PropertyUpdate', + METHOD_UPDATE: 'SharedObject.MethodUpdate' +}); + +/***/ }), +/* 57 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _stringify = __webpack_require__(12); + +var _stringify2 = _interopRequireDefault(_stringify); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _websocket = __webpack_require__(42); + +var websocket = _interopRequireWildcard(_websocket); + +var _browser = __webpack_require__(4); + +var _browser2 = _interopRequireDefault(_browser); + +var _promise = __webpack_require__(5); + +var _log = __webpack_require__(2); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Base Proxy for communication with WebSocket. + * + * @private + */ +var SocketHelper = function () { + function SocketHelper(responder, name) { + (0, _classCallCheck3.default)(this, SocketHelper); + + this._responder = responder; + this._pendingPostRequests = []; + this._websocket = undefined; + this._connectionPromise = undefined; + this._name = name; + this._responseHandlers = []; + this._isTerminated = false; + this._retryCount = 0; + this._retryLimit = 1; + this._readyCheckCount = 0; + this._readyCheckLimit = 10; + this._onclose = this.tearDown.bind(this); + + this._onopenTimeout = 0; + + this._asyncTickets = []; + } + + (0, _createClass3.default)(SocketHelper, [{ + key: '_resetOnopenTimeout', + value: function _resetOnopenTimeout(ws, promise) { + var _this = this; + + var isMoz = _browser2.default.getIsMoz(); + var timeout = setTimeout(function () { + clearTimeout(timeout); + if (ws.readyState === 1) { + (0, _log.info)(_this._name, '[websocketopen]'); + while (_this._pendingPostRequests.length > 0) { + _this.post(_this._pendingPostRequests.shift()); + } + if (_this._responder && _this._responder.onSocketOpen) { + _this._responder.onSocketOpen(); + } + } else if (ws.readyState === 0) { + if (++_this._readyCheckCount > _this._readyCheckLimit) { + (0, _log.warn)(_this._name, 'WebSocket connection issue. We have waited for ' + (_this._readyCheckCount - 1) + ' samples, without any connection.'); + // If Firefox, try a second connection attempt or fail. + /* + if (isMoz && ++this._retryCount < this._retryLimit) { + warn(this._name, `WebSocket attempting retry...`) + this._removeSocketHandlers(ws) + this._onopenTimeout = setTimeout(() => { + clearTimeout(this._onopenTimeout) + this.setUp(ws.url, promise) + }, 2000) + } else { + promise.reject({type: 'Timeout'}) + } + */ + _this.clearRetry(); + promise.reject({ type: 'Timeout' }); + _this.tearDown(); + } else { + (0, _log.info)(_this._name, 'WebSocket connection is still opening, will let it continue (' + _this._readyCheckCount + ')...'); + _this._onopenTimeout = _this._resetOnopenTimeout(ws, promise); + } + } else { + (0, _log.info)(_this._name, 'WebSocket connection attempts have ended with state (' + ws.readyState + ').'); + } + }, 500); + return timeout; + } + + /** + * Removes event handlers from WebSocket. + * + * @param {WebSocket} ws + * + * @private + */ + + }, { + key: '_removeSocketHandlers', + value: function _removeSocketHandlers(ws) { + if (ws) { + ws.onopen = undefined; + ws.onmessage = undefined; + ws.onerror = undefined; + ws.onclose = undefined; + } + } + + /** + * Assigns event handler to WebSocket. + * + * @param {WebSocket} ws + * @param {Promise} + * The `Promise` to reject on error in connection to WebSocket. + * + * @private + */ + + }, { + key: '_addSocketHandlers', + value: function _addSocketHandlers(ws, promise) { + var _this2 = this; + + /* + * Removing this in favor of checking readyState for verification of open. + * + ws.onopen = () => { + info(this._name, '[websocketopen]') + while (this._pendingPostRequests.length > 0) { + this.post(this._pendingPostRequests.shift()) + } + } + */ + + this._readyCheckCount = 0; + clearTimeout(this._onopenTimeout); + this._onopenTimeout = this._resetOnopenTimeout(ws, promise); + + ws.onerror = function (error) { + (0, _log.warn)(_this2._name, '[websocketerror]: Error from WebSocket. ' + error.type + '.'); + _this2.clearRetry(); + promise.reject(error); + }; + + ws.onmessage = function (message) { + _this2.respond(message); + }; + + ws.onclose = function (event) { + (0, _log.warn)(_this2._name, '[websocketclose]: ' + event.code); + if (_this2._responder) { + _this2._responder.onSocketClose(event); + } + _this2.clearRetry(); + _this2._removeSocketHandlers(ws || _this2._websocket); + }; + } + + /** + * Handler for unexpected error through WebSocket. + * + * @param {Object} error + * + * @private + */ + + }, { + key: '_onUnexpectedSocketError', + value: function _onUnexpectedSocketError(error) { + if (this._responder) { + this._responder.onSocketClose(error); + } + (0, _log.warn)(this._name, '[websocketerror]: Possible Unexpected Error from WebSocket. ' + error.type + ', ' + error.detail); + this.clearRetry(); + this._removeSocketHandlers(this._websocket); + } + + /** + * Clears the retry count to allow for single publisher to retry again after an unpublish. + * + * @private + */ + + }, { + key: 'clearRetry', + value: function clearRetry() { + this._retryCount = 0; + this._readyCheckCount = 0; + clearTimeout(this._onopenTimeout); + } + + /** + * Request to setup WebSocket connection for communication. + * + * @param {String} url + * Endpoint URL of the socket to connect to. + * @param {Promise} setupPromise + * The `Promise` to resolve or reject on success of setup WebSocket connection. + */ + + }, { + key: 'setUp', + value: function setUp(url, setupPromise) { + var _this3 = this; + + var isMoz = _browser2.default.getIsMoz(); + (0, _log.debug)(this._name, '[websocket:setup] ' + url + '.'); + this.tearDown(); + this._isTerminated = false; + this._connectionPromise = setupPromise; + _browser2.default.addCloseHandler(this._onclose); + this._websocket = websocket.create(url); + this._addSocketHandlers(this._websocket, this._connectionPromise); + if (isMoz && this._retryCount++ < this._retryLimit) { + (0, _log.debug)(this._name, 'We have determined it is Firefox and are setting up a retry limit.'); + var timeout = setTimeout(function () { + if (_this3._websocket && _this3._websocket.readyState === 0) { + (0, _log.debug)(_this3._name, '[websocket:FF-timeout]'); + (0, _log.debug)(_this3._name, 'Our connection on Firefox to the wss endpoint has timed out. Let\'s try that again.'); + _this3._removeSocketHandlers(_this3._websocket); + _this3.setUp(url, setupPromise); + } + clearTimeout(timeout); + }, 2000); + } + } + + /** + * Request to tear down any WebSocket connection. + */ + + }, { + key: 'tearDown', + value: function tearDown() { + this._pendingPostRequests.length = 0; + if (typeof this._websocket !== 'undefined' && !this._isTerminated) { + (0, _log.debug)(this._name, '[teardown] >>'); + (0, _log.debug)(this._name, '[WebSocket(' + this._websocket.url + ')] close() >>'); + // this._removeSocketHandlers(this._websocket) + try { + this._websocket.close(); + } catch (e) { + (0, _log.warn)(this._name, 'Attempt to close WebSocket failed: ' + e.message + '.'); + this._removeSocketHandlers(this._websocket); + } finally { + if (this._websocket) { + (0, _log.debug)(this._name, '<< [WebSocket(' + this._websocket.url + ')] close()'); + } + } + (0, _log.debug)(this._name, '<< [teardown]'); + } + this._websocket = undefined; + this._isTerminated = true; + while (this._responseHandlers.length > 0) { + this._responseHandlers.shift(); + } + _browser2.default.removeCloseHandler(this._onclose); + } + + /** + * Request to parse JSON from message received over WebSocket. + * + * @param {Object} message + * String or Object. + */ + + }, { + key: 'getJsonFromSocketMessage', + value: function getJsonFromSocketMessage(message) { + try { + return typeof message.data === 'string' ? JSON.parse(message.data) : message.data; + } catch (e) { + (0, _log.warn)(this._name, 'Could not parse message as JSON. Message= ' + message.data + '. Error= ' + e.message); + } + return null; + } + + /** + * Adds a SharedObject response handler. Handlers are requested to respond to a message in `handleMessageResponse`. + * + * @param {Object} handler + */ + + }, { + key: 'addSharedObjectResponseHandler', + value: function addSharedObjectResponseHandler(handler) { + this._responseHandlers.push(handler); + } + + /** + * Removes a SharedObject response handler. + * + * @param {Object} handler + */ + + }, { + key: 'removeSharedObjectResponseHandler', + value: function removeSharedObjectResponseHandler(handler) { + var i = this._responseHandlers.length; + var rHandler = void 0; + while (--i > -1) { + rHandler = this._responseHandlers[i]; + if (rHandler === handler) { + this._responseHandlers.splice(i, 1); + return; + } + } + } + + /** + * Traverses list of response handlers and returns flag of it being handled within the chain. + * + * @param {Object} message + * @return {Boolean} + */ + + }, { + key: 'handleMessageResponse', + value: function handleMessageResponse(message) { + var i = void 0, + handler = void 0; + var length = this._responseHandlers.length; + for (i = 0; i < length; i++) { + handler = this._responseHandlers[i]; + if (handler.respond(message)) { + return true; + } + } + return false; + } + + /** + * Request to post notification of end of candidates in WebRTC scenario. + */ + + }, { + key: 'postEndOfCandidates', + value: function postEndOfCandidates(streamName) { + this.post({ + handleCandidate: streamName, + data: { + candidate: { + type: 'candidate', + candidate: '' + } + } + }); + } + + /** + * Request to post data over WebSocket connection. + * Queues messages if WebSocket connection is still being established. + * + * @param {Object} sendRequest + */ + + }, { + key: 'post', + value: function post(sendRequest) { + if (this._websocket !== undefined && this._websocket.readyState === 1 /* WebSocket.OPEN */) { + try { + (0, _log.debug)(this._name, '[websocket-post]: ' + (0, _stringify2.default)(sendRequest, null, 2)); + this._websocket.send((0, _stringify2.default)(sendRequest)); + return true; + } catch (e) { + (0, _log.debug)(this._name, 'Could not send request: ' + sendRequest + '. ' + e); + return false; + } + } else if (this._websocket !== undefined && (this._websocket.readyState === 2 || this._websocket.readyState === 3)) /* WebSocket.(CLOSING | CLOSED) */{ + return false; + } else if (this._isTerminated) { + return false; + } else { + this._pendingPostRequests.push(sendRequest); + return true; + } + } + }, { + key: 'postAsync', + value: function postAsync(sendRequest) { + var p = new _promise.DeferredPromise(); + var id = Math.floor(Math.random() * 0x10000).toString(16); + sendRequest.id = id; + sendRequest.async = true; + this._asyncTickets.push({ id: id, promise: p }); + this.post(sendRequest); + return p.promise; + } + + /** + * Responds to messages coming over the WebSocket connection. + * + * @param {Object} message + */ + + }, { + key: 'respond', + value: function respond(message) { + // eslint-disable-line no-unused-vars + var handled = this.handleMessageResponse(message); + if (!handled && message.data) { + var json = this.getJsonFromSocketMessage(message); + if (json === null) { + (0, _log.warn)(this._name, 'Determined websocket response not in correct format. Aborting message handle.'); + return true; + } + (0, _log.debug)(this._name, '[websocket-response]: ' + (0, _stringify2.default)(json, null, 2)); + if (json.isAvailable !== undefined) { + if (typeof json.isAvailable === 'boolean' && json.isAvailable) { + this._responder.onStreamAvailable(json); + return true; + } else { + this._responder.onStreamUnavailable(json); + return true; + } + } else if (json.async && json.id) { + var ticket = this._asyncTickets.find(function (el) { + return el.id === json.id; + }); + var promise = ticket.promise; + + if (promise && json.data) { + promise.resolve(json.data); + } else if (promise && json.error) { + promise.reject(json.error); + } + } else if (json.data !== undefined) { + var data = json.data; + + if (data.message !== undefined) { + if (data.type === 'error') { + this._responder.onSocketMessageError(data.message, data.detail); + return true; + } + } else if (data.type === 'status') { + if (data.code === 'NetConnection.Connect.Success') { + this._websocket.onerror = this._onUnexpectedSocketError.bind(this); + this._connectionPromise.resolve(); + return true; + } else if (data.code === 'NetConnection.Connect.Rejected') { + this._connectionPromise.reject('NetConnection.Connect.Rejected'); + return true; + } + } else if (data.type === 'error') { + if (data.code === 'NetConnection.Connect.Rejected') { + this._connectionPromise.reject('NetConnection.Connect.Rejected'); + return true; + } else if (data.code === 'NetConnection.Connect.Failed') { + this._connectionPromise.reject('NetConnection.Connect.Failed'); + return true; + } + } + } + } + return handled; + } + + /** + * Request to get SharedObject from server over WebSocket. + * + * @param {String} name + */ + + }, { + key: 'getRemoteSharedObject', + value: function getRemoteSharedObject(name) { + this.post({ + sharedObjectGetRemote: { + name: name + } + }); + } + + /** + * Request to connect to SharedObject from server over WebSocket. + * + * @param {String} name + */ + + }, { + key: 'connectToSharedObject', + value: function connectToSharedObject(name) { + this.post({ + sharedObjectConnect: { + name: name + } + }); + } + + /** + * Request to send method call to SharedObject over WebSocket. + * + * @param {String} name + * @param {String} callName + * @param {Object} data + */ + + }, { + key: 'sendToSharedObject', + value: function sendToSharedObject(name, callName, data) { + this.post({ + sharedObjectSend: { + name: name, + call: callName, + params: [data] + } + }); + } + + /** + * Request to update property on SharedObject over WebSocket. + * + * @param {String} name + * @param {String} key + * @param {String} value + */ + + }, { + key: 'sendPropertyToSharedObject', + value: function sendPropertyToSharedObject(name, key, value) { + this.post({ + sharedObjectSetProperty: { + name: name, + key: key, + value: value + } + }); + } + + /** + * Request to close the SharedObject connection over WebSocket. + * + * @param {String} name + */ + + }, { + key: 'closeSharedObject', + value: function closeSharedObject(name) { + this.post({ + sharedObjectClose: { + name: name + } + }); + } + + /** + * Returns flag of socket being closed and temrinated. + * + * @returns {Boolean} + */ + + }, { + key: 'isTerminated', + get: function get() { + return this._isTerminated; + } + }]); + return SocketHelper; +}(); + +exports.default = SocketHelper; + +/***/ }), +/* 58 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/** + * Encode the value of each key and return a new object. + * + * @param {Object} valueObject + * The object whose values should be encoded. + * @return {Object} + * + * @private + */ + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.hlsSocketEndpointFromOptions = exports.rtcSocketEndpointFromOptions = exports.encodeKeyValues = undefined; + +var _extends2 = __webpack_require__(29); + +var _extends3 = _interopRequireDefault(_extends2); + +var _keys = __webpack_require__(60); + +var _keys2 = _interopRequireDefault(_keys); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var encodeKeyValues = exports.encodeKeyValues = function encodeKeyValues(valueObject) { + var encoded = {}; + (0, _keys2.default)(valueObject).forEach(function (key, index) { + // eslint-disable-line no-unused-vars + encoded[key] = encodeURIComponent(valueObject[key]); + }); + return encoded; +}; + +/** + * Construct endpoint to use for WebSocket connection based on configuration object and optional params to append to query. + * + * @param {Object} options + * The configuration options provided in `init()` of WebRTC based publisher or subscriber. + * @param {Object} params + * The optional params to append to the endpoint. Used by server in connection parse. + * @private + */ +var rtcSocketEndpointFromOptions = exports.rtcSocketEndpointFromOptions = function rtcSocketEndpointFromOptions(options) { + var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + + var protocol = options.wsprotocol || options.protocol; + var port = options.wsport || options.port; + var appEndpoint = options.context ? [options.app, options.context].join('/') : options.app; + var endpoint = protocol + '://' + options.host + ':' + port + '/' + appEndpoint; + if (typeof options.connectionParams !== 'undefined') { + var encodedParams = encodeKeyValues(options.connectionParams); + params = (0, _extends3.default)(params, encodedParams); + } + if (typeof params !== 'undefined') { + var kv = []; + (0, _keys2.default)(params).forEach(function (key, index) { + // eslint-disable-line no-unused-vars + kv.push([key, params[key]].join('=')); + }); + if (kv.length > 0) { + endpoint += '?' + kv.join('&'); + } + } + + return endpoint; +}; + +/** + * Construct endpoint to use for WebSocket connection based on configuration object and optional params to append to query. + * This allows for such things as authentication prior to request of playback of HLS file. + * Requires a `socketParams` attribute in the init configuration that describe the WebSocket endpoint to make the request on. + * + * @param {Object} options + * The configuration options provided in `init()` of HLS based subscriber. + * @param {Object} params + * The optional params to append to the endpoint. Used by server in connection parse. + * + * @example + * var subscriber = new HLSubscriber() + * subscriber.init({ + * protocol: 'https', + * host: 'mycompany.org', + * app: 'live', + * streamName: 'mystream', + * socketParams: { + * protocol: 'wss', + * host: 'mycompany.org', + * app: 'live' + * }, + * connectionParams: { + * user: 'foo', + * password: 'bar' + * } + * }) + * @private + */ +var hlsSocketEndpointFromOptions = exports.hlsSocketEndpointFromOptions = function hlsSocketEndpointFromOptions(options) { + var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + var socketParams = options.socketParams, + connectionParams = options.connectionParams; + + var protocol = socketParams.protocol; + var port = socketParams.port || (protocol === 'wss' ? 8083 : 8081); + var endpoint = protocol + '://' + socketParams.host + ':' + port + '/' + socketParams.app; + if (connectionParams) { + var encodedParams = encodeKeyValues(options.connectionParams); + params = (0, _extends3.default)(params, encodedParams); + } + if (params) { + var kv = []; + (0, _keys2.default)(params).forEach(function (key, index) { + // eslint-disable-line no-unused-vars + kv.push([key, params[key]].join('=')); + }); + if (kv.length > 0) { + endpoint += '?' + kv.join('&'); + } + } + + return endpoint; +}; + +/***/ }), +/* 59 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _browser = __webpack_require__(4); + +var _browser2 = _interopRequireDefault(_browser); + +var _log = __webpack_require__(2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var NAME = 'R5ProPublishView'; +var publisherId = 'red5pro-publisher'; + +/** + * Bridge between DOM Element view and Publisher implementation. + * Still used, but internalized as of 4.0.0. Up for deprecation, up for discussion. + * + * @private + */ + +var PublishView = function () { + + /** + * @param {String} elementId + * The element `id` to use for playback display. + * @private + */ + function PublishView() { + var elementId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : publisherId; + (0, _classCallCheck3.default)(this, PublishView); + + try { + this._targetElement = _browser2.default.resolveElement(elementId); + } catch (e) { + (0, _log.error)(NAME, 'Could not instantiate a new instance of Red5ProPublisher. Reason: ' + e.message); + throw e; + } + } + + (0, _createClass3.default)(PublishView, [{ + key: 'attachPublisher', + value: function attachPublisher(publisher) { + (0, _log.debug)(NAME, '[attachpublisher]'); + publisher.setView(this, _browser2.default.getElementId(this._targetElement)); + } + }, { + key: 'preview', + value: function preview(mediaStream) { + var autoplay = this.isAutoplay; + (0, _log.debug)(NAME, '[preview]: autoplay(' + autoplay + ')'); + _browser2.default.setVideoSource(this._targetElement, mediaStream, autoplay); + } + }, { + key: 'isAutoplay', + get: function get() { + return _browser2.default.hasAttributeDefined(this._targetElement, 'autoplay'); + } + }, { + key: 'view', + get: function get() { + return this._targetElement; + } + }]); + return PublishView; +}(); + +exports.default = PublishView; + +/***/ }), +/* 60 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = { "default": __webpack_require__(158), __esModule: true }; + +/***/ }), +/* 61 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = { "default": __webpack_require__(160), __esModule: true }; + +/***/ }), +/* 62 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +exports.__esModule = true; + +var _iterator = __webpack_require__(141); + +var _iterator2 = _interopRequireDefault(_iterator); + +var _symbol = __webpack_require__(140); + +var _symbol2 = _interopRequireDefault(_symbol); + +var _typeof = typeof _symbol2.default === "function" && typeof _iterator2.default === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof _symbol2.default === "function" && obj.constructor === _symbol2.default && obj !== _symbol2.default.prototype ? "symbol" : typeof obj; }; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = typeof _symbol2.default === "function" && _typeof(_iterator2.default) === "symbol" ? function (obj) { + return typeof obj === "undefined" ? "undefined" : _typeof(obj); +} : function (obj) { + return obj && typeof _symbol2.default === "function" && obj.constructor === _symbol2.default && obj !== _symbol2.default.prototype ? "symbol" : typeof obj === "undefined" ? "undefined" : _typeof(obj); +}; + +/***/ }), +/* 63 */ +/***/ (function(module, exports) { + +module.exports = function(it){ + if(typeof it != 'function')throw TypeError(it + ' is not a function!'); + return it; +}; + +/***/ }), +/* 64 */ +/***/ (function(module, exports, __webpack_require__) { + +// 0 -> Array#forEach +// 1 -> Array#map +// 2 -> Array#filter +// 3 -> Array#some +// 4 -> Array#every +// 5 -> Array#find +// 6 -> Array#findIndex +var ctx = __webpack_require__(19) + , IObject = __webpack_require__(68) + , toObject = __webpack_require__(33) + , toLength = __webpack_require__(52) + , asc = __webpack_require__(169); +module.exports = function(TYPE, $create){ + var IS_MAP = TYPE == 1 + , IS_FILTER = TYPE == 2 + , IS_SOME = TYPE == 3 + , IS_EVERY = TYPE == 4 + , IS_FIND_INDEX = TYPE == 6 + , NO_HOLES = TYPE == 5 || IS_FIND_INDEX + , create = $create || asc; + return function($this, callbackfn, that){ + var O = toObject($this) + , self = IObject(O) + , f = ctx(callbackfn, that, 3) + , length = toLength(self.length) + , index = 0 + , result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined + , val, res; + for(;length > index; index++)if(NO_HOLES || index in self){ + val = self[index]; + res = f(val, index, O); + if(TYPE){ + if(IS_MAP)result[index] = res; // map + else if(res)switch(TYPE){ + case 3: return true; // some + case 5: return val; // find + case 6: return index; // findIndex + case 2: result.push(val); // filter + } else if(IS_EVERY)return false; // every + } + } + return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result; + }; +}; + +/***/ }), +/* 65 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var global = __webpack_require__(11) + , $export = __webpack_require__(10) + , meta = __webpack_require__(31) + , fails = __webpack_require__(25) + , hide = __webpack_require__(21) + , redefineAll = __webpack_require__(51) + , forOf = __webpack_require__(37) + , anInstance = __webpack_require__(44) + , isObject = __webpack_require__(13) + , setToStringTag = __webpack_require__(39) + , dP = __webpack_require__(14).f + , each = __webpack_require__(64)(0) + , DESCRIPTORS = __webpack_require__(17); + +module.exports = function(NAME, wrapper, methods, common, IS_MAP, IS_WEAK){ + var Base = global[NAME] + , C = Base + , ADDER = IS_MAP ? 'set' : 'add' + , proto = C && C.prototype + , O = {}; + if(!DESCRIPTORS || typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function(){ + new C().entries().next(); + }))){ + // create collection constructor + C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER); + redefineAll(C.prototype, methods); + meta.NEED = true; + } else { + C = wrapper(function(target, iterable){ + anInstance(target, C, NAME, '_c'); + target._c = new Base; + if(iterable != undefined)forOf(iterable, IS_MAP, target[ADDER], target); + }); + each('add,clear,delete,forEach,get,has,set,keys,values,entries,toJSON'.split(','),function(KEY){ + var IS_ADDER = KEY == 'add' || KEY == 'set'; + if(KEY in proto && !(IS_WEAK && KEY == 'clear'))hide(C.prototype, KEY, function(a, b){ + anInstance(this, C, KEY); + if(!IS_ADDER && IS_WEAK && !isObject(a))return KEY == 'get' ? undefined : false; + var result = this._c[KEY](a === 0 ? 0 : a, b); + return IS_ADDER ? this : result; + }); + }); + if('size' in proto)dP(C.prototype, 'size', { + get: function(){ + return this._c.size; + } + }); + } + + setToStringTag(C, NAME); + + O[NAME] = C; + $export($export.G + $export.W + $export.F, O); + + if(!IS_WEAK)common.setStrong(C, NAME, IS_MAP); + + return C; +}; + +/***/ }), +/* 66 */ +/***/ (function(module, exports, __webpack_require__) { + +var isObject = __webpack_require__(13) + , document = __webpack_require__(11).document + // in old IE typeof document.createElement is 'object' + , is = isObject(document) && isObject(document.createElement); +module.exports = function(it){ + return is ? document.createElement(it) : {}; +}; + +/***/ }), +/* 67 */ +/***/ (function(module, exports) { + +// IE 8- don't enum bug keys +module.exports = ( + 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf' +).split(','); + +/***/ }), +/* 68 */ +/***/ (function(module, exports, __webpack_require__) { + +// fallback for non-array-like ES3 and non-enumerable old V8 strings +var cof = __webpack_require__(36); +module.exports = Object('z').propertyIsEnumerable(0) ? Object : function(it){ + return cof(it) == 'String' ? it.split('') : Object(it); +}; + +/***/ }), +/* 69 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var LIBRARY = __webpack_require__(47) + , $export = __webpack_require__(10) + , redefine = __webpack_require__(72) + , hide = __webpack_require__(21) + , has = __webpack_require__(20) + , Iterators = __webpack_require__(30) + , $iterCreate = __webpack_require__(174) + , setToStringTag = __webpack_require__(39) + , getPrototypeOf = __webpack_require__(107) + , ITERATOR = __webpack_require__(9)('iterator') + , BUGGY = !([].keys && 'next' in [].keys()) // Safari has buggy iterators w/o `next` + , FF_ITERATOR = '@@iterator' + , KEYS = 'keys' + , VALUES = 'values'; + +var returnThis = function(){ return this; }; + +module.exports = function(Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED){ + $iterCreate(Constructor, NAME, next); + var getMethod = function(kind){ + if(!BUGGY && kind in proto)return proto[kind]; + switch(kind){ + case KEYS: return function keys(){ return new Constructor(this, kind); }; + case VALUES: return function values(){ return new Constructor(this, kind); }; + } return function entries(){ return new Constructor(this, kind); }; + }; + var TAG = NAME + ' Iterator' + , DEF_VALUES = DEFAULT == VALUES + , VALUES_BUG = false + , proto = Base.prototype + , $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT] + , $default = $native || getMethod(DEFAULT) + , $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined + , $anyNative = NAME == 'Array' ? proto.entries || $native : $native + , methods, key, IteratorPrototype; + // Fix native + if($anyNative){ + IteratorPrototype = getPrototypeOf($anyNative.call(new Base)); + if(IteratorPrototype !== Object.prototype){ + // Set @@toStringTag to native iterators + setToStringTag(IteratorPrototype, TAG, true); + // fix for some old engines + if(!LIBRARY && !has(IteratorPrototype, ITERATOR))hide(IteratorPrototype, ITERATOR, returnThis); + } + } + // fix Array#{values, @@iterator}.name in V8 / FF + if(DEF_VALUES && $native && $native.name !== VALUES){ + VALUES_BUG = true; + $default = function values(){ return $native.call(this); }; + } + // Define iterator + if((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])){ + hide(proto, ITERATOR, $default); + } + // Plug for library + Iterators[NAME] = $default; + Iterators[TAG] = returnThis; + if(DEFAULT){ + methods = { + values: DEF_VALUES ? $default : getMethod(VALUES), + keys: IS_SET ? $default : getMethod(KEYS), + entries: $entries + }; + if(FORCED)for(key in methods){ + if(!(key in proto))redefine(proto, key, methods[key]); + } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods); + } + return methods; +}; + +/***/ }), +/* 70 */ +/***/ (function(module, exports, __webpack_require__) { + +var pIE = __webpack_require__(49) + , createDesc = __webpack_require__(38) + , toIObject = __webpack_require__(22) + , toPrimitive = __webpack_require__(76) + , has = __webpack_require__(20) + , IE8_DOM_DEFINE = __webpack_require__(99) + , gOPD = Object.getOwnPropertyDescriptor; + +exports.f = __webpack_require__(17) ? gOPD : function getOwnPropertyDescriptor(O, P){ + O = toIObject(O); + P = toPrimitive(P, true); + if(IE8_DOM_DEFINE)try { + return gOPD(O, P); + } catch(e){ /* empty */ } + if(has(O, P))return createDesc(!pIE.f.call(O, P), O[P]); +}; + +/***/ }), +/* 71 */ +/***/ (function(module, exports) { + +exports.f = Object.getOwnPropertySymbols; + +/***/ }), +/* 72 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = __webpack_require__(21); + +/***/ }), +/* 73 */ +/***/ (function(module, exports, __webpack_require__) { + +var shared = __webpack_require__(74)('keys') + , uid = __webpack_require__(53); +module.exports = function(key){ + return shared[key] || (shared[key] = uid(key)); +}; + +/***/ }), +/* 74 */ +/***/ (function(module, exports, __webpack_require__) { + +var global = __webpack_require__(11) + , SHARED = '__core-js_shared__' + , store = global[SHARED] || (global[SHARED] = {}); +module.exports = function(key){ + return store[key] || (store[key] = {}); +}; + +/***/ }), +/* 75 */ +/***/ (function(module, exports) { + +// 7.1.4 ToInteger +var ceil = Math.ceil + , floor = Math.floor; +module.exports = function(it){ + return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it); +}; + +/***/ }), +/* 76 */ +/***/ (function(module, exports, __webpack_require__) { + +// 7.1.1 ToPrimitive(input [, PreferredType]) +var isObject = __webpack_require__(13); +// instead of the ES6 spec version, we didn't implement @@toPrimitive case +// and the second argument - flag - preferred type is a string +module.exports = function(it, S){ + if(!isObject(it))return it; + var fn, val; + if(S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; + if(typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it)))return val; + if(!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; + throw TypeError("Can't convert object to primitive value"); +}; + +/***/ }), +/* 77 */ +/***/ (function(module, exports, __webpack_require__) { + +var global = __webpack_require__(11) + , core = __webpack_require__(3) + , LIBRARY = __webpack_require__(47) + , wksExt = __webpack_require__(78) + , defineProperty = __webpack_require__(14).f; +module.exports = function(name){ + var $Symbol = core.Symbol || (core.Symbol = LIBRARY ? {} : global.Symbol || {}); + if(name.charAt(0) != '_' && !(name in $Symbol))defineProperty($Symbol, name, {value: wksExt.f(name)}); +}; + +/***/ }), +/* 78 */ +/***/ (function(module, exports, __webpack_require__) { + +exports.f = __webpack_require__(9); + +/***/ }), +/* 79 */ +/***/ (function(module, exports, __webpack_require__) { + +var classof = __webpack_require__(45) + , ITERATOR = __webpack_require__(9)('iterator') + , Iterators = __webpack_require__(30); +module.exports = __webpack_require__(3).getIteratorMethod = function(it){ + if(it != undefined)return it[ITERATOR] + || it['@@iterator'] + || Iterators[classof(it)]; +}; + +/***/ }), +/* 80 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.embedSwfObject = exports.defineEmbedElement = undefined; + +var _browser = __webpack_require__(4); + +var _browser2 = _interopRequireDefault(_browser); + +var _promise = __webpack_require__(5); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Replaces a `video` element with a container for embedding a Flash object. + * + * @param {Element} targetElement + * @param {Element} targetParent + * + * @private + */ +var defineEmbedElement = exports.defineEmbedElement = function defineEmbedElement(targetElement, targetParent) { + var dfd = new _promise.DeferredPromise(); + var elementId = targetElement.id; + if (targetElement.nodeName.toLowerCase() === 'video') { + var div = _browser2.default.createElement('div'); + div.id = elementId + '_rtmp'; + targetParent.appendChild(div); + if (targetElement.parentElement) { + targetElement.parentElement.removeChild(targetElement); + } + dfd.resolve(div.id); + } else { + dfd.resolve(elementId); + } + return dfd.promise; +}; + +/** + * Request to embed a Flash object using SWFObject library. + * + * @param {String} idName + * @param {Object} options + * Initialization configuration map. + * @param {Object} flashvars + * The FlashVars to pass into the embedded object. + * @param {Object} swfobject + * The loaded SWFObject library util. + * @param {String} elementId + * The id of the Element to embed. + * @return {Promise} + * + * @private + */ +var embedSwfObject = exports.embedSwfObject = function embedSwfObject(idName, options, flashvars, swfobject, elementId) { + var dfd = new _promise.DeferredPromise(); + var params = { + quality: 'high', + wmode: 'opaque', + bgcolor: options.backgroundColor || '#000', + allowscriptaccess: 'always', + allowfullscreen: 'true', + allownetworking: 'all' + }; + var attributes = { + id: idName, + name: idName, + align: 'middle' + }; + if (swfobject.hasFlashPlayerVersion(options.minFlashVersion)) { + swfobject.embedSWF(options.swf, elementId, options.embedWidth || 640, options.embedHeight || 480, options.minFlashVersion, options.productInstallURL, flashvars, params, attributes, function (result) { + if (result.success) { + dfd.resolve(); + } else { + dfd.reject('Flash Object embed failed.'); + } + }); + } else { + dfd.reject('Flash Player Version is not supported.'); + } + return dfd.promise; +}; + +/***/ }), +/* 81 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.applyOrientation = undefined; + +var _browser = __webpack_require__(4); + +var _browser2 = _interopRequireDefault(_browser); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var requestFrame = _browser2.default.requestFrame; + +/* || Translation Styles used on Orientation-change metadata from Mobile broadcasters. || */ + +var origin = ['webkitTransformOrigin', 'mozTransformOrigin', 'msTransformOrigin', 'oTransformOrigin', 'transformOrigin']; +var styles = ['webkitTransform', 'mozTransform', 'msTransform', 'oTransform', 'transform']; +var transition = ['webkitTransition', 'mozTransition', 'msTransition', 'oTransition', 'transition']; +var rotationTranslations = { + '0': { + origin: 'center center', + transform: 'rotate(0deg)' + }, + '90': { + origin: 'left top', + transform: 'rotate(90deg) translateY(-100%)' + }, + '180': { + origin: 'center center', + transform: 'rotate(180deg)' + }, + '270': { + origin: 'top left', + transform: 'rotate(270deg) translateX(-100%) translateY(0%)' + }, + '-90': { + origin: 'left top', + transform: 'rotate(-90deg) translateX(-100%)' + }, + '-180': { + origin: 'center center', + transform: 'rotate(-180deg)' + }, + '-270': { + origin: 'top left', + transform: 'rotate(-270deg) translateY(-100%)' + } + + /* Utility method to track and resize an element on enter frame. */ +};var trackResize = function trackResize(element, raf) { + var isRotated = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + return function () { + var parent = element.parentNode; + if (parent) { + var pwidth = parent.clientWidth; + var pheight = parent.clientHeight; + if (isRotated) { + element.style.width = pheight + 'px'; + } else { + element.style.width = pwidth + 'px'; + } + var ewidth = element.clientWidth; + var eheight = element.clientHeight; + var margin = (isRotated ? pwidth - eheight : pwidth - ewidth) * 0.5; + element.style.position = 'relative'; + element.style.left = margin + 'px'; + } + if (raf) { + raf(trackResize(element, raf, isRotated)); + } + }; +}; + +var applyOrientation = exports.applyOrientation = function applyOrientation(element, value, resolution) { + // eslint-disable-line no-unused-vars + var i = void 0, + length = styles.length; + value = value % 360; + var isRotated = value % 180 !== 0; + var parent = element.parentNode; + var pwidth = element.width ? element.width : parent.clientWidth; + var pheight = element.height ? element.height : parent.clientHeight; + var translations = rotationTranslations[value.toString()]; + for (i = 0; i < length; i++) { + element.style[origin[i]] = translations.origin; + element.style[styles[i]] = translations.transform; + element.style[transition[i]] = 'transform 0.0s linear'; + } + if (isRotated) { + // const scale = pwidth > pheight ? pheight / pwidth : pwidth / pheight + element.style.width = pheight + 'px'; + parent.style.height = pheight + 'px'; + // element.style.height = (pwidth * scale) + 'px' + } else { + element.style.width = pwidth + 'px'; + element.style.height = pheight + 'px'; + // parent.style.width = pwidth + 'px' + } + + if (document.attachEvent) { + parent.attachEvent('resize', trackResize(element, requestFrame, isRotated)); + } else { + trackResize(element, requestFrame, isRotated)(); + } +}; + +/***/ }), +/* 82 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.RTMPPublisherEventTypes = exports.RTCPublisherEventTypes = exports.FailoverPublisherEventTypes = exports.PublisherEventTypes = undefined; + +var _freeze = __webpack_require__(18); + +var _freeze2 = _interopRequireDefault(_freeze); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Common Publisher-based event types. + */ +var PublisherEventTypes = exports.PublisherEventTypes = (0, _freeze2.default)({ + CONNECT_SUCCESS: 'Connect.Success', + CONNECT_FAILURE: 'Connect.Failure', + PUBLISH_START: 'Publish.Start', + PUBLISH_FAIL: 'Publish.Fail', + PUBLISH_INVALID_NAME: 'Publish.InvalidName', + UNPUBLISH_SUCCESS: 'Unpublish.Success', + PUBLISH_METADATA: 'Publish.Metadata', + CONNECTION_CLOSED: 'Publisher.Connection.Closed', + DIMENSION_CHANGE: 'Publisher.Video.DimensionChange' +}); + +/** + * Event types dispacthed from and specific to `Red5ProPublisher`. + * + * @see {Red5ProPublisher} + */ +var FailoverPublisherEventTypes = exports.FailoverPublisherEventTypes = (0, _freeze2.default)({ + PUBLISHER_REJECT: 'Publisher.Reject', + PUBLISHER_ACCEPT: 'Publisher.Accept' +}); + +/** + * Event types dispatched from and specific to `RTCPublisher`. + * + * @see {RTCPublisher} + */ +var RTCPublisherEventTypes = exports.RTCPublisherEventTypes = (0, _freeze2.default)({ + MEDIA_STREAM_AVAILABLE: 'WebRTC.MediaStream.Available', + PEER_CONNECTION_AVAILABLE: 'WebRTC.PeerConnection.Available', + OFFER_START: 'WebRTC.Offer.Start', + OFFER_END: 'WebRTC.Offer.End', + PEER_CANDIDATE_END: 'WebRTC.PeerConnection.CandidateEnd', + ICE_TRICKLE_COMPLETE: 'WebRTC.IceTrickle.Complete' +}); + +/** + * Event types dispatched from and specific to `RTMPPublisher`. + * + * @see {RTMPPublisher} + */ +var RTMPPublisherEventTypes = exports.RTMPPublisherEventTypes = (0, _freeze2.default)({ + EMBED_SUCCESS: 'FlashPlayer.Embed.Success', + EMBED_FAILURE: 'FlashPlayer.Embed.Failure' +}); + +/***/ }), +/* 83 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.RTMPSubscriberEventTypes = exports.RTCSubscriberEventTypes = exports.FailoverSubscriberEventTypes = exports.SubscriberEventTypes = undefined; + +var _freeze = __webpack_require__(18); + +var _freeze2 = _interopRequireDefault(_freeze); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Common event types on all Subscribers. + */ +var SubscriberEventTypes = exports.SubscriberEventTypes = (0, _freeze2.default)({ + CONNECT_SUCCESS: 'Connect.Success', + CONNECT_FAILURE: 'Connect.Failure', + SUBSCRIBE_START: 'Subscribe.Start', + SUBSCRIBE_STOP: 'Subscribe.Stop', + SUBSCRIBE_FAIL: 'Subscribe.Fail', + SUBSCRIBE_INVALID_NAME: 'Subscribe.InvalidName', + SUBSCRIBE_METADATA: 'Subscribe.Metadata', + SUBSCRIBE_SEND_INVOKE: 'Subscribe.Send.Invoke', + PLAY_UNPUBLISH: 'Subscribe.Play.Unpublish', + CONNECTION_CLOSED: 'Subscribe.Connection.Closed', + ORIENTATION_CHANGE: 'Subscribe.Orientation.Change', + VOLUME_CHANGE: 'Subscribe.Volume.Change', + PLAYBACK_TIME_UPDATE: 'Subscribe.Time.Update', + PLAYBACK_STATE_CHANGE: 'Subscribe.Playback.Change', + FULL_SCREEN_STATE_CHANGE: 'Subscribe.FullScreen.Change' +}); + +/** + * Event types dispatched from and specific to `Red5ProSubscriber`. + * + * @see {Red5ProSubscriber} + */ +var FailoverSubscriberEventTypes = exports.FailoverSubscriberEventTypes = (0, _freeze2.default)({ + SUBSCRIBER_REJECT: 'Subscriber.Reject', + SUBSCRIBER_ACCEPT: 'Subscriber.Accept' +}); + +/** + * Event types dispatched from and specific to `RTCSubscriber`. + * + * @see {RTCSubscriber} + */ +var RTCSubscriberEventTypes = exports.RTCSubscriberEventTypes = (0, _freeze2.default)({ + PEER_CONNECTION_AVAILABLE: 'WebRTC.PeerConnection.Available', + OFFER_START: 'WebRTC.Offer.Start', + OFFER_END: 'WebRTC.Offer.End', + ANSWER_START: 'WebRTC.Answer.Start', + ANSWER_END: 'WebRTC.Answer.End', + CANDIDATE_START: 'WebRTC.Candidate.Start', + CANDIDATE_END: 'WebRTC.Candidate.End', + PEER_CANDIDATE_END: 'WebRTC.PeerConnection.CandidateEnd', + ICE_TRICKLE_COMPLETE: 'WebRTC.IceTrickle.Complete', + ON_ADD_STREAM: 'WebRTC.Add.Stream' +}); + +/** + * Event type dispatched from and specific to `RTMPSubscriber`. + * + * @see {RTMPSubscriber} + */ +var RTMPSubscriberEventTypes = exports.RTMPSubscriberEventTypes = (0, _freeze2.default)({ + EMBED_SUCCESS: 'FlashPlayer.Embed.Success', + EMBED_FAILURE: 'FlashPlayer.Embed.Failure', + // Stream Manager + ABR Specific + ABR_LEVEL_CHANGE: 'RTMP.AdaptiveBitrate.Level' +}); + +/***/ }), +/* 84 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _stringify = __webpack_require__(12); + +var _stringify2 = _interopRequireDefault(_stringify); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _browser = __webpack_require__(4); + +var _browser2 = _interopRequireDefault(_browser); + +var _log = __webpack_require__(2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var NAME = 'R5ProRTMPSharedObjectHandler'; + +/** + * Flash-based SharedObject handler. + * + * @private + */ + +var RTMPSharedObjectHandler = function () { + function RTMPSharedObjectHandler() { + (0, _classCallCheck3.default)(this, RTMPSharedObjectHandler); + + this._element = undefined; + this._responseHandlers = []; + } + + /** + * Adds a response handler for SharedObject events. + * + * @param {Object} handler + */ + + + (0, _createClass3.default)(RTMPSharedObjectHandler, [{ + key: 'addResponseHandler', + value: function addResponseHandler(handler) { + this._responseHandlers.push(handler); + } + + /** + * Removes a response handler from SharedObject events. + * + * @param {Object} handler + */ + + }, { + key: 'removeResponseHandler', + value: function removeResponseHandler(handler) { + var i = this._responseHandlers.length; + var rHandler = void 0; + while (--i > -1) { + rHandler = this._responseHandlers[i]; + if (rHandler === handler) { + this._responseHandlers.splice(i, 1); + return; + } + } + } + + /** + * Handles an event from a SharedObject. + * + * @param {Object} event + */ + + }, { + key: 'handleSharedObjectEvent', + value: function handleSharedObjectEvent(event) { + (0, _log.debug)(NAME, '[sharedobject:event]'); + var i = void 0; + var length = this._responseHandlers.length; + var handler = void 0; + for (i = 0; i < length; i++) { + handler = this._responseHandlers[i]; + if (handler.respond(JSON.parse(event))) { + break; + } + } + } + + /** + * Assigns a global response handler for SharedObject communication through Flash object over ExternalInterface. + * + * @param {String} name + * @param {Element} el + * The object embed element. + */ + + }, { + key: 'assignSharedObjectResponder', + value: function assignSharedObjectResponder(name, el) { + var _handleSharedObjectEvent = this.handleSharedObjectEvent.bind(this); + var elId = el.id.split('-').join('_'); + var handlerName = ['handleSharedObjectEvent', elId].join('_'); + (0, _log.debug)(NAME, '[assign:sharedobject:responder] :: ' + elId); + (0, _log.debug)(NAME, '[sharedoject:responder] :: ' + handlerName); + el.setSharedObjectResponder(name, handlerName); + _browser2.default.setGlobal(handlerName, _handleSharedObjectEvent); + } + + /** + * Request to connect to SharedObject. + */ + + }, { + key: 'connect', + value: function connect(swfId) { + this._element = _browser2.default.getEmbedObject(swfId); + if (!this._element) { + (0, _log.warn)('Could not locate embedded Flash object for id: ' + swfId); + } + } + + /** + * Request to disconnect to SharedObject. + */ + + }, { + key: 'disconnect', + value: function disconnect() { + while (this._responseHandlers.length > 0) { + this._responseHandlers.shift(); + } + } + + /** + * Attempt to send method update to SharedObject. + * + * @param {String} name + * @param {String} callName + * @param {Object} message + * String or Object that will be serialized to a JSON string. + */ + + }, { + key: 'sendToSharedObject', + value: function sendToSharedObject(name, callName, message) { + (0, _log.debug)(NAME, '[sendToSharedObject]'); + try { + this._element.sharedObjectSend(name, callName, typeof message === 'string' ? message : (0, _stringify2.default)(message)); + } catch (e) { + (0, _log.warn)('Could not send to shared object (' + name + '). Error: ' + e.message); + } + } + + /** + * Attempt to update property on SharedObject. + * + * @param {String} name + * @param {String} key + * @param {Object} value + */ + + }, { + key: 'sendPropertyToSharedObject', + value: function sendPropertyToSharedObject(name, key, value) { + (0, _log.debug)(NAME, '[sendPropertyToSharedObject]'); + try { + this._element.sharedObjectSendProperty(name, key, value); + } catch (e) { + (0, _log.warn)('Could not send to shared object (' + name + '). Error: ' + e.message); + } + } + + /** + * Request to get remote ShareObject by name. + * + * @param {String} sharedObjectName + */ + + }, { + key: 'getRemoteSharedObject', + value: function getRemoteSharedObject(sharedObjectName) { + (0, _log.debug)(NAME, '[getRemoteSharedObject]'); + try { + this.assignSharedObjectResponder(sharedObjectName, this._element); + this._element.getRemoteSharedObject(sharedObjectName); + } catch (e) { + (0, _log.warn)('Could not get remote shared object (' + name + '). Error: ' + e.message); + } + } + + /** + * Request to connect to SharedObject by name. + * + * @param {String} sharedObjectName + */ + + }, { + key: 'connectToSharedObject', + value: function connectToSharedObject(sharedObjectName) { + (0, _log.debug)(NAME, '[connectToSharedObject]'); + try { + this._element.connectToSharedObject(sharedObjectName); + } catch (e) { + (0, _log.warn)('Could not connect to shared object (' + name + '). Error: ' + e.message); + } + } + + /** + * Request to close SharedObject connection by name. + * + * @param {String} sharedObjectName + */ + + }, { + key: 'closeSharedObject', + value: function closeSharedObject(sharedObjectName) { + (0, _log.debug)(NAME, '[disconnectToSharedObject]'); + try { + this._element.disconnectFromSharedObject(sharedObjectName); + } catch (e) { + (0, _log.warn)('Could not disconnect to shared object (' + name + '). Error: ' + e.message); + } + } + }]); + return RTMPSharedObjectHandler; +}(); + +exports.default = RTMPSharedObjectHandler; + +/***/ }), +/* 85 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/** + * Easy decorator for setting a mutable, iteratable property on an object. + * + * @private + */ + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.RTMPMediaConstraint = exports.RTCMediaConstraint = undefined; + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _defineProperty = __webpack_require__(91); + +var _defineProperty2 = _interopRequireDefault(_defineProperty); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var inflate = function inflate(obj, prop, value) { + (0, _defineProperty2.default)(obj, prop, { + value: value, + writable: true, + enumerable: true + }); +}; + +/** + * Default `exact` setting for `video` on `MediaConstraint` for WebRTC broadcast. + * + * @private + */ + +var RTCMediaVideoConstraint = function RTCMediaVideoConstraint() { + (0, _classCallCheck3.default)(this, RTCMediaVideoConstraint); + + inflate(this, 'width', { + exact: 640 + }); + inflate(this, 'height', { + exact: 480 + }); +}; + +/** + * Default RTMP video settings for braodcast. + * + * @private + */ + + +var RTMPMediaVideoConstraint = function RTMPMediaVideoConstraint() { + (0, _classCallCheck3.default)(this, RTMPMediaVideoConstraint); + + inflate(this, 'width', 640); + inflate(this, 'height', 480); + inflate(this, 'force', false); + inflate(this, 'framerate', 15); + inflate(this, 'bandwidth', 50000); + inflate(this, 'quality', 80); + inflate(this, 'profile', 'baseline'); + inflate(this, 'level', 3.1); +}; + +/** + * Default WebRTC media settings for broadcast. + * + * @private + */ + + +var RTCMediaConstraint = function RTCMediaConstraint() { + var audio = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + var video = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + (0, _classCallCheck3.default)(this, RTCMediaConstraint); + + inflate(this, 'audio', audio); + inflate(this, 'video', video || new RTCMediaVideoConstraint()); +}; + +/** + * Default RTMP media settings for broadcast. + * + * @private + */ + + +var RTMPMediaConstraint = function RTMPMediaConstraint() { + var audio = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + var video = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + (0, _classCallCheck3.default)(this, RTMPMediaConstraint); + + inflate(this, 'audio', audio); + inflate(this, 'video', video || new RTMPMediaVideoConstraint()); +}; + +exports.RTCMediaConstraint = RTCMediaConstraint; +exports.RTMPMediaConstraint = RTMPMediaConstraint; + +/***/ }), +/* 86 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.SliderEventTypes = exports.SliderEvent = undefined; + +var _freeze = __webpack_require__(18); + +var _freeze2 = _interopRequireDefault(_freeze); + +var _getPrototypeOf = __webpack_require__(6); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = __webpack_require__(8); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = __webpack_require__(7); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _event = __webpack_require__(15); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Events for Slider Control. + * + * @see {SliderControl} + * + * @private + */ +var SliderEvent = function (_Event) { + (0, _inherits3.default)(SliderEvent, _Event); + + function SliderEvent(type, control, data) { + (0, _classCallCheck3.default)(this, SliderEvent); + + var _this = (0, _possibleConstructorReturn3.default)(this, (SliderEvent.__proto__ || (0, _getPrototypeOf2.default)(SliderEvent)).call(this, type, data)); + + _this._control = control; + return _this; + } + + (0, _createClass3.default)(SliderEvent, [{ + key: 'control', + get: function get() { + return this._control; + } + }]); + return SliderEvent; +}(_event.Event); + +/** + * Enumeration of Slider Event types. + * + * @private + */ + + +var SliderEventTypes = (0, _freeze2.default)({ + CHANGE_START: 'changestart', + CHANGE: 'change', + CHANGE_COMPLETE: 'changecomplete' +}); + +exports.SliderEvent = SliderEvent; +exports.SliderEventTypes = SliderEventTypes; + +/***/ }), +/* 87 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ImplFactoryOrder = undefined; + +var _slicedToArray2 = __webpack_require__(143); + +var _slicedToArray3 = _interopRequireDefault(_slicedToArray2); + +var _regenerator = __webpack_require__(144); + +var _regenerator2 = _interopRequireDefault(_regenerator); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _weakMap = __webpack_require__(142); + +var _weakMap2 = _interopRequireDefault(_weakMap); + +var _promise = __webpack_require__(5); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var map = new _weakMap2.default(); + +var pvt = function pvt(ctx) { + if (!map.has(ctx)) { + map.set(ctx, {}); + } + + return map.get(ctx); +}; + +/** + * Implementation Factory. + * + * This is used by the fail-over for Publisher and Subscriber to determine browser support of order list of implementations. + * + * @private + */ + +var ImplFactoryOrder = exports.ImplFactoryOrder = function () { + function ImplFactoryOrder() { + var _this = this; + + (0, _classCallCheck3.default)(this, ImplFactoryOrder); + + this.listorder = function () { + return (/*#__PURE__*/_regenerator2.default.mark(function listorder(list) { + return _regenerator2.default.wrap(function listorder$(_context) { + while (1) { + switch (_context.prev = _context.next) { + case 0: + if (!(list.length > 0)) { + _context.next = 5; + break; + } + + _context.next = 3; + return list.shift(); + + case 3: + _context.next = 0; + break; + + case 5: + case 'end': + return _context.stop(); + } + } + }, listorder, this); + }) + ); + }(); + + /** + * Attempt to check support and initialize Class instance within the order. Optionally, can invoke an initialization with configuration object. + * + * @param {Object} iterator + * Iterator used in accessing possible Class instance next in linked list of order. + * @param {Object} map + * Map of order type to Class. + * @param {Object} options + * Map of initialization configurations to types. + * @param {Promise} promise + * The `Promise` instance to use in resolve or reject once either a valid instance is created or order has been exhausted, respectively. + * @param {Function} initFn + * Optional function to invoke upon instantiation attempt. + * @param {String} lastError + * Optional - and compounded - last string error that caused a failure in establishing a supported instance. This error is delivered on the rejection of the `Promise`. + * + * @private + */ + pvt(this).find = function (iterator, map, options, promise) { + var initFn = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; + var lastError = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null; + + var _pvt$next = pvt(_this).next(iterator, map), + _pvt$next2 = (0, _slicedToArray3.default)(_pvt$next, 2), + type = _pvt$next2[0], + Impl = _pvt$next2[1]; + + if (!Impl) { + promise.reject(lastError); + } else { + var p = void 0; + var src = options[type]; + src = src || options; + if (initFn) { + p = new Impl()[initFn](src); + } else { + p = new Impl(src); + } + p.then(function (concrete) { + promise.resolve(concrete); + }).catch(function (error) { + // eslint-disable-line no-unused-vars + lastError = error; + pvt(_this).find(iterator, map, options, promise, initFn, lastError); + }); + } + }; + + /** + * Iterate next in order. + * + * @private + */ + pvt(this).next = function (order, map) { + var Impl = void 0; + var key = void 0; + var next = order.next(); + if (!next.done) { + key = next.value; + Impl = map.get(key); + } + return [key, Impl]; + }; + } + + /** + * Request to locate supported implementation and initialize it, resolving the `Promise` with the instance. + * + * @param {Array} order + * @param {Object} map + * Map of Class to order type. + * @param {Object} options + * Initialization object to pass to constructor of Class in browser test of support. + * @param {Function} initFn + * Optional initialization function to invoke with the `options` config. + * + * @private + */ + + + (0, _createClass3.default)(ImplFactoryOrder, [{ + key: 'create', + value: function create(order, map, options) { + var initFn = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + + var promise = new _promise.DeferredPromise(); + pvt(this).find(this.listorder(order.slice()), map, options, promise, initFn); + return promise.promise; + } + }]); + return ImplFactoryOrder; +}(); + +exports.default = ImplFactoryOrder; + +/***/ }), +/* 88 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +// http://blog.carbonfive.com/2015/01/14/gettin-freaky-functional-wcurried-javascript/ +/** + * Basic curry implementation. + * + * @private + */ + +Object.defineProperty(exports, "__esModule", { + value: true +}); +var curry = exports.curry = function curry(fx) { + var arity = fx.length; + return function f1() { + var args = Array.prototype.slice.call(arguments, 0); + if (args.length >= arity) { + return fx.apply(null, args); + } else { + return function f2() { + var args2 = Array.prototype.slice.call(arguments, 0); + return f1.apply(null, args.concat(args2)); + }; + } + }; +}; + +/** + * Basic filter implementation. + * + * @private + */ +var filter = exports.filter = curry(function (fn, list) { + var idx = 0; + var len = list.length; + var result = []; + + while (idx < len) { + if (fn(list[idx])) { + result[result.length] = list[idx]; + } + idx += 1; + } + return result; +}); + +/** + * Converts a value to integer. + * + * @param {Object} value + * @returns {Number} + * + * @private + */ +var toInt = exports.toInt = function toInt(value) { + if (typeof value === 'string') { + return parseInt(value, 10); + } else { + return Math.round(value); + } +}; + +/** + * Checks truthy-ness of `value` and returns default if false. + * + * @param {Object} value + * @param {Object} defaultValue + * + * @private + */ +var getOrElse = exports.getOrElse = function getOrElse(value, defaultValue) { + return value || defaultValue; +}; + +/** + * Checks truthy-ness of `value` as a Number and returns default if false. + * + * @param {Object} value + * @param {Object} defaultValue + * + * @private + */ +var getIntOrElse = exports.getIntOrElse = function getIntOrElse(value, defaultValue) { + return !isNaN(toInt(value)) ? toInt(value) : defaultValue; +}; + +/***/ }), +/* 89 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = { "default": __webpack_require__(149), __esModule: true }; + +/***/ }), +/* 90 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = { "default": __webpack_require__(150), __esModule: true }; + +/***/ }), +/* 91 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = { "default": __webpack_require__(154), __esModule: true }; + +/***/ }), +/* 92 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = { "default": __webpack_require__(161), __esModule: true }; + +/***/ }), +/* 93 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +exports.__esModule = true; + +var _getPrototypeOf = __webpack_require__(6); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _getOwnPropertyDescriptor = __webpack_require__(138); + +var _getOwnPropertyDescriptor2 = _interopRequireDefault(_getOwnPropertyDescriptor); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = function get(object, property, receiver) { + if (object === null) object = Function.prototype; + var desc = (0, _getOwnPropertyDescriptor2.default)(object, property); + + if (desc === undefined) { + var parent = (0, _getPrototypeOf2.default)(object); + + if (parent === null) { + return undefined; + } else { + return get(parent, property, receiver); + } + } else if ("value" in desc) { + return desc.value; + } else { + var getter = desc.get; + + if (getter === undefined) { + return undefined; + } + + return getter.call(receiver); + } +}; + +/***/ }), +/* 94 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +exports.__esModule = true; + +var _from = __webpack_require__(132); + +var _from2 = _interopRequireDefault(_from); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = function (arr) { + if (Array.isArray(arr)) { + for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { + arr2[i] = arr[i]; + } + + return arr2; + } else { + return (0, _from2.default)(arr); + } +}; + +/***/ }), +/* 95 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * !This is a stripped down version of Bunyan targeted specifically for the browser + * + * ------------------------------------------------------------------------------- + * + * Copyright (c) 2014 Trent Mick. All rights reserved. + * Copyright (c) 2014 Joyent Inc. All rights reserved. + * + * The bunyan logging library for node.js. + * + * -*- mode: js -*- + * vim: expandtab:ts=4:sw=4 + */ + + + +var VERSION = '0.2.3'; + +// Bunyan log format version. This becomes the 'v' field on all log records. +// `0` is until I release a version '1.0.0' of node-bunyan. Thereafter, +// starting with `1`, this will be incremented if there is any backward +// incompatible change to the log record format. Details will be in +// 'CHANGES.md' (the change log). +var LOG_VERSION = 0; + +//---- Internal support stuff + +/** + * A shallow copy of an object. Bunyan logging attempts to never cause + * exceptions, so this function attempts to handle non-objects gracefully. + */ +function objCopy(obj) { + if (typeof obj === 'undefined' || obj === null) { // null or undefined + return obj; + } else if (Array.isArray(obj)) { + return obj.slice(); + } else if (typeof (obj) === 'object') { + var copy = {}; + Object.keys(obj).forEach(function (k) { + copy[k] = obj[k]; + }); + return copy; + } else { + return obj; + } +} + +var format = function(f) { + + if(f === null) { + return 'null'; + } + + if(typeof f !== 'string') { + return f.toString(); + } + var formatRegExp = /%[sdj%]/g; + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%%') { + return '%'; + } + if (i >= len) { + return x; + } + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + break; + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + str += ' ' + x; + } + return str; +}; + +/** + * Gather some caller info 3 stack levels up. + * See . + */ +function getCaller3Info() { + var obj = {}; + var saveLimit = Error.stackTraceLimit; + var savePrepare = Error.prepareStackTrace; + Error.stackTraceLimit = 3; + //Error.captureStackTrace(this, getCaller3Info); + + Error.prepareStackTrace = function (_, stack) { + var caller = stack[2]; + obj.file = caller.getFileName(); + obj.line = caller.getLineNumber(); + var func = caller.getFunctionName(); + if (func) { + obj.func = func; + } + }; + Error.stackTraceLimit = saveLimit; + Error.prepareStackTrace = savePrepare; + return obj; +} + + +function _indent(s, indent) { + if (!indent) { + indent = ' '; + } + var lines = s.split(/\r?\n/g); + return indent + lines.join('\n' + indent); +} + + +/** + * Warn about an bunyan processing error. + * + * @param msg {String} Message with which to warn. + * @param dedupKey {String} Optional. A short string key for this warning to + * have its warning only printed once. + */ +function _warn(msg, dedupKey) { + if (dedupKey) { + if (_warned[dedupKey]) { + return; + } + _warned[dedupKey] = true; + } + console.error(msg + '\n'); +} +function _haveWarned(dedupKey) { + return _warned[dedupKey]; +} +var _warned = {}; + + +function ConsoleRawStream() { +} +ConsoleRawStream.prototype.write = function (rec) { + if (rec.level < INFO) { + console.log(rec); + } else if (rec.level < WARN) { + console.info(rec); + } else if (rec.level < ERROR) { + console.warn(rec); + } else { + console.error(rec); + } + + if(rec.err && rec.err.stack) { + console.error(rec.err.stack); + } +}; + +function ConsoleFormattedStream() {} +ConsoleFormattedStream.prototype.write = function (rec) { + + var levelCss, defaultCss = 'color: DimGray', msgCss = 'color: SteelBlue'; + + if (rec.level < DEBUG) { + levelCss = 'color: DeepPink'; + } else if (rec.level < INFO) { + levelCss = 'color: GoldenRod'; + } else if (rec.level < WARN) { + levelCss = 'color: DarkTurquoise'; + } else if (rec.level < ERROR) { + levelCss = 'color: Purple'; + } else if (rec.level < FATAL) { + levelCss = 'color: Crimson'; + } else { + levelCss = 'color: Black'; + } + + var loggerName = rec.childName ? rec.name + '/' + rec.childName : rec.name; + + //get level name and pad start with spacs + var levelName = nameFromLevel[rec.level].toUpperCase(); + levelName = Array(6 - levelName.length).join(' ') + levelName; + + function padZeros(number, len) { + return Array((len + 1) - (number + '').length).join('0') + number; + } + + console.log('[%s:%s:%s:%s] %c%s%c: %s: %c%s', + padZeros(rec.time.getHours(), 2), padZeros(rec.time.getMinutes(), 2), + padZeros(rec.time.getSeconds(), 2), padZeros(rec.time.getMilliseconds(), 4), + levelCss, levelName, + defaultCss, loggerName, + msgCss, rec.msg); + if(rec.err && rec.err.stack) { + console.log('%c%s,', levelCss, rec.err.stack); + } +}; + +//---- Levels + +var TRACE = 10; +var DEBUG = 20; +var INFO = 30; +var WARN = 40; +var ERROR = 50; +var FATAL = 60; + +var levelFromName = { + 'trace': TRACE, + 'debug': DEBUG, + 'info': INFO, + 'warn': WARN, + 'error': ERROR, + 'fatal': FATAL +}; +var nameFromLevel = {}; +Object.keys(levelFromName).forEach(function (name) { + nameFromLevel[levelFromName[name]] = name; +}); + + +/** + * Resolve a level number, name (upper or lowercase) to a level number value. + * + * @api public + */ +function resolveLevel(nameOrNum) { + var level = (typeof (nameOrNum) === 'string' ? levelFromName[nameOrNum.toLowerCase()] : nameOrNum); + return level; +} + + +//---- Logger class + +/** + * Create a Logger instance. + * + * @param options {Object} See documentation for full details. At minimum + * this must include a 'name' string key. Configuration keys: + * - `streams`: specify the logger output streams. This is an array of + * objects with these fields: + * - `type`: The stream type. See README.md for full details. + * Often this is implied by the other fields. Examples are + * 'file', 'stream' and "raw". + * - `level`: Defaults to 'info'. + * - `path` or `stream`: The specify the file path or writeable + * stream to which log records are written. E.g. + * `stream: process.stdout`. + * - `closeOnExit` (boolean): Optional. Default is true for a + * 'file' stream when `path` is given, false otherwise. + * See README.md for full details. + * - `level`: set the level for a single output stream (cannot be used + * with `streams`) + * - `stream`: the output stream for a logger with just one, e.g. + * `process.stdout` (cannot be used with `streams`) + * - `serializers`: object mapping log record field names to + * serializing functions. See README.md for details. + * - `src`: Boolean (default false). Set true to enable 'src' automatic + * field with log call source info. + * All other keys are log record fields. + * + * An alternative *internal* call signature is used for creating a child: + * new Logger(, [, ]); + * + * @param _childSimple (Boolean) An assertion that the given `_childOptions` + * (a) only add fields (no config) and (b) no serialization handling is + * required for them. IOW, this is a fast path for frequent child + * creation. + */ +function Logger(options, _childOptions, _childSimple) { + if (!(this instanceof Logger)) { + return new Logger(options, _childOptions); + } + + // Input arg validation. + var parent; + if (_childOptions !== undefined) { + parent = options; + options = _childOptions; + if (!(parent instanceof Logger)) { + throw new TypeError( + 'invalid Logger creation: do not pass a second arg'); + } + } + if (!options) { + throw new TypeError('options (object) is required'); + } + if (!parent) { + if (!options.name) { + throw new TypeError('options.name (string) is required'); + } + } else { + if (options.name) { + throw new TypeError( + 'invalid options.name: child cannot set logger name'); + } + } + if (options.stream && options.streams) { + throw new TypeError('cannot mix "streams" and "stream" options'); + } + if (options.streams && !Array.isArray(options.streams)) { + throw new TypeError('invalid options.streams: must be an array'); + } + if (options.serializers && (typeof (options.serializers) !== 'object' || Array.isArray(options.serializers))) { + throw new TypeError('invalid options.serializers: must be an object'); + } + + var fields, name, i; + + // Fast path for simple child creation. + if (parent && _childSimple) { + // `_isSimpleChild` is a signal to stream close handling that this child + // owns none of its streams. + this._isSimpleChild = true; + + this._level = parent._level; + this.streams = parent.streams; + this.serializers = parent.serializers; + this.src = parent.src; + fields = this.fields = {}; + var parentFieldNames = Object.keys(parent.fields); + for (i = 0; i < parentFieldNames.length; i++) { + name = parentFieldNames[i]; + fields[name] = parent.fields[name]; + } + var names = Object.keys(options); + for (i = 0; i < names.length; i++) { + name = names[i]; + fields[name] = options[name]; + } + return; + } + + // Null values. + var self = this; + if (parent) { + this._level = parent._level; + this.streams = []; + for (i = 0; i < parent.streams.length; i++) { + var s = objCopy(parent.streams[i]); + s.closeOnExit = false; // Don't own parent stream. + this.streams.push(s); + } + this.serializers = objCopy(parent.serializers); + this.src = parent.src; + this.fields = objCopy(parent.fields); + if (options.level) { + this.level(options.level); + } + } else { + this._level = Number.POSITIVE_INFINITY; + this.streams = []; + this.serializers = null; + this.src = false; + this.fields = {}; + } + + // Handle *config* options (i.e. options that are not just plain data + // for log records). + if (options.stream) { + self.addStream({ + type: 'stream', + stream: options.stream, + closeOnExit: false, + level: options.level + }); + } else if (options.streams) { + options.streams.forEach(function (s) { + self.addStream(s, options.level); + }); + } else if (parent && options.level) { + this.level(options.level); + } else if (!parent) { + + /* + * In the browser we'll be emitting to console.log by default. + * Any console.log worth its salt these days can nicely render + * and introspect objects (e.g. the Firefox and Chrome console) + * so let's emit the raw log record. Are there browsers for which + * that breaks things? + */ + self.addStream({ + type: 'raw', + stream: new ConsoleRawStream(), + closeOnExit: false, + level: options.level + }); + + } + if (options.serializers) { + self.addSerializers(options.serializers); + } + if (options.src) { + this.src = true; + } + + // Fields. + // These are the default fields for log records (minus the attributes + // removed in this constructor). To allow storing raw log records + // (unrendered), `this.fields` must never be mutated. Create a copy for + // any changes. + fields = objCopy(options); + delete fields.stream; + delete fields.level; + delete fields.streams; + delete fields.serializers; + delete fields.src; + if (this.serializers) { + this._applySerializers(fields); + } + Object.keys(fields).forEach(function (k) { + self.fields[k] = fields[k]; + }); +} + +/** + * Add a stream + * + * @param stream {Object}. Object with these fields: + * - `type`: The stream type. See README.md for full details. + * Often this is implied by the other fields. Examples are + * 'file', 'stream' and "raw". + * - `path` or `stream`: The specify the file path or writeable + * stream to which log records are written. E.g. + * `stream: process.stdout`. + * - `level`: Optional. Falls back to `defaultLevel`. + * - `closeOnExit` (boolean): Optional. Default is true for a + * 'file' stream when `path` is given, false otherwise. + * See README.md for full details. + * @param defaultLevel {Number|String} Optional. A level to use if + * `stream.level` is not set. If neither is given, this defaults to INFO. + */ +Logger.prototype.addStream = function addStream(s, defaultLevel) { + var self = this; + if (defaultLevel === null || defaultLevel === undefined) { + defaultLevel = INFO; + } + + s = objCopy(s); + + // Implicit 'type' from other args. + if (!s.type && s.stream) { + s.type = 'raw'; + } + s.raw = (s.type === 'raw'); // PERF: Allow for faster check in `_emit`. + + if (s.level) { + s.level = resolveLevel(s.level); + } else { + s.level = resolveLevel(defaultLevel); + } + if (s.level < self._level) { + self._level = s.level; + } + + switch (s.type) { + case 'stream': + if (!s.closeOnExit) { + s.closeOnExit = false; + } + break; + case 'raw': + if (!s.closeOnExit) { + s.closeOnExit = false; + } + break; + default: + throw new TypeError('unknown stream type "' + s.type + '"'); + } + + self.streams.push(s); + delete self.haveNonRawStreams; // reset +}; + + +/** + * Add serializers + * + * @param serializers {Object} Optional. Object mapping log record field names + * to serializing functions. See README.md for details. + */ +Logger.prototype.addSerializers = function addSerializers(serializers) { + var self = this; + + if (!self.serializers) { + self.serializers = {}; + } + Object.keys(serializers).forEach(function (field) { + var serializer = serializers[field]; + if (typeof (serializer) !== 'function') { + throw new TypeError(format( + 'invalid serializer for "%s" field: must be a function', + field)); + } else { + self.serializers[field] = serializer; + } + }); +}; + + +/** + * Create a child logger, typically to add a few log record fields. + * + * This can be useful when passing a logger to a sub-component, e.g. a + * 'wuzzle' component of your service: + * + * var wuzzleLog = log.child({component: 'wuzzle'}) + * var wuzzle = new Wuzzle({..., log: wuzzleLog}) + * + * Then log records from the wuzzle code will have the same structure as + * the app log, *plus the component='wuzzle' field*. + * + * @param options {Object} Optional. Set of options to apply to the child. + * All of the same options for a new Logger apply here. Notes: + * - The parent's streams are inherited and cannot be removed in this + * call. Any given `streams` are *added* to the set inherited from + * the parent. + * - The parent's serializers are inherited, though can effectively be + * overwritten by using duplicate keys. + * - Can use `level` to set the level of the streams inherited from + * the parent. The level for the parent is NOT affected. + * @param simple {Boolean} Optional. Set to true to assert that `options` + * (a) only add fields (no config) and (b) no serialization handling is + * required for them. IOW, this is a fast path for frequent child + * creation. See 'tools/timechild.js' for numbers. + */ +Logger.prototype.child = function (options, simple) { + return new (this.constructor)(this, options || {}, simple); +}; + +/** + * Get/set the level of all streams on this logger. + * + * Get Usage: + * // Returns the current log level (lowest level of all its streams). + * log.level() -> INFO + * + * Set Usage: + * log.level(INFO) // set all streams to level INFO + * log.level('info') // can use 'info' et al aliases + */ +Logger.prototype.level = function level(value) { + if (value === undefined) { + return this._level; + } + var newLevel = resolveLevel(value); + var len = this.streams.length; + for (var i = 0; i < len; i++) { + this.streams[i].level = newLevel; + } + this._level = newLevel; +}; + + +/** + * Get/set the level of a particular stream on this logger. + * + * Get Usage: + * // Returns an array of the levels of each stream. + * log.levels() -> [TRACE, INFO] + * + * // Returns a level of the identified stream. + * log.levels(0) -> TRACE // level of stream at index 0 + * log.levels('foo') // level of stream with name 'foo' + * + * Set Usage: + * log.levels(0, INFO) // set level of stream 0 to INFO + * log.levels(0, 'info') // can use 'info' et al aliases + * log.levels('foo', WARN) // set stream named 'foo' to WARN + * + * Stream names: When streams are defined, they can optionally be given + * a name. For example, + * log = new Logger({ + * streams: [ + * { + * name: 'foo', + * path: '/var/log/my-service/foo.log' + * level: 'trace' + * }, + * ... + * + * @param name {String|Number} The stream index or name. + * @param value {Number|String} The level value (INFO) or alias ('info'). + * If not given, this is a 'get' operation. + * @throws {Error} If there is no stream with the given name. + */ +Logger.prototype.levels = function levels(name, value) { + if (name === undefined) { + return this.streams.map( + function (s) { + return s.level; + }); + } + var stream; + if (typeof (name) === 'number') { + stream = this.streams[name]; + if (stream === undefined) { + throw new Error('invalid stream index: ' + name); + } + } else { + var len = this.streams.length; + for (var i = 0; i < len; i++) { + var s = this.streams[i]; + if (s.name === name) { + stream = s; + break; + } + } + if (!stream) { + throw new Error(format('no stream with name "%s"', name)); + } + } + if (value === undefined) { + return stream.level; + } else { + var newLevel = resolveLevel(value); + stream.level = newLevel; + if (newLevel < this._level) { + this._level = newLevel; + } + } +}; + + +/** + * Apply registered serializers to the appropriate keys in the given fields. + * + * Pre-condition: This is only called if there is at least one serializer. + * + * @param fields (Object) The log record fields. + * @param excludeFields (Object) Optional mapping of keys to `true` for + * keys to NOT apply a serializer. + */ +Logger.prototype._applySerializers = function (fields, excludeFields) { + var self = this; + + // Check each serializer against these (presuming number of serializers + // is typically less than number of fields). + Object.keys(this.serializers).forEach(function (name) { + if (fields[name] === undefined || + (excludeFields && excludeFields[name])) { + return; + } + try { + fields[name] = self.serializers[name](fields[name]); + } catch (err) { + _warn(format('bunyan: ERROR: Exception thrown from the "%s" ' + + 'Bunyan serializer. This should never happen. This is a bug' + + 'in that serializer function.\n%s', + name, err.stack || err)); + fields[name] = format('(Error in Bunyan log "%s" serializer broke field. See stderr for details.)', name); + } + }); +}; + + +/** + * Emit a log record. + * + * @param rec {log record} + * @param noemit {Boolean} Optional. Set to true to skip emission + * and just return the JSON string. + */ +Logger.prototype._emit = function (rec, noemit) { + var i; + + // Lazily determine if this Logger has non-'raw' streams. If there are + // any, then we need to stringify the log record. + if (this.haveNonRawStreams === undefined) { + this.haveNonRawStreams = false; + for (i = 0; i < this.streams.length; i++) { + if (!this.streams[i].raw) { + this.haveNonRawStreams = true; + break; + } + } + } + + // Stringify the object. Attempt to warn/recover on error. + var str; + if (noemit || this.haveNonRawStreams) { + try { + str = JSON.stringify(rec, safeCycles()) + '\n'; + } catch (e) { + var dedupKey = e.stack.split(/\n/g, 2).join('\n'); + _warn('bunyan: ERROR: Exception in ' + + '`JSON.stringify(rec)`. You can install the ' + + '"safe-json-stringify" module to have Bunyan fallback ' + + 'to safer stringification. Record:\n' + + _indent(format('%s\n%s', rec, e.stack)), + dedupKey); + str = format('(Exception in JSON.stringify(rec): %j. See stderr for details.)\n', e.message); + + } + } + + if (noemit) { + return str; + } + + + var level = rec.level; + for (i = 0; i < this.streams.length; i++) { + var s = this.streams[i]; + if (s.level <= level) { + s.stream.write(s.raw ? rec : str); + } + } + + return str; +}; + + +/** + * Build a log emitter function for level minLevel. I.e. this is the + * creator of `log.info`, `log.error`, etc. + */ +function mkLogEmitter(minLevel) { + return function () { + var log = this; + + function mkRecord(args) { + var excludeFields; + if (args[0] instanceof Error) { + // `log.(err, ...)` + fields = { + // Use this Logger's err serializer, if defined. + err: (log.serializers && log.serializers.err ? log.serializers.err(args[0]) : Logger.stdSerializers.err(args[0])) + }; + excludeFields = {err: true}; + if (args.length === 1) { + msgArgs = [fields.err.message]; + } else { + msgArgs = Array.prototype.slice.call(args, 1); + } + } else if (typeof (args[0]) !== 'object' && args[0] !== null || + Array.isArray(args[0])) { + // `log.(msg, ...)` + fields = null; + msgArgs = Array.prototype.slice.call(args); + } else { // `log.(fields, msg, ...)` + fields = args[0]; + msgArgs = Array.prototype.slice.call(args, 1); + } + + // Build up the record object. + var rec = objCopy(log.fields); + rec.level = minLevel; + var recFields = (fields ? objCopy(fields) : null); + if (recFields) { + if (log.serializers) { + log._applySerializers(recFields, excludeFields); + } + Object.keys(recFields).forEach(function (k) { + rec[k] = recFields[k]; + }); + } + rec.levelName = nameFromLevel[minLevel]; + rec.msg = format.apply(log, msgArgs); + if (!rec.time) { + rec.time = (new Date()); + } + // Get call source info + if (log.src && !rec.src) { + rec.src = getCaller3Info(); + } + rec.v = LOG_VERSION; + + return rec; + } + + var fields = null; + var msgArgs = arguments; + var rec = null; + if (!this._emit) { + /* + * Show this invalid Bunyan usage warning *once*. + * + * See for + * an example of how this can happen. + */ + var dedupKey = 'unbound'; + if (!_haveWarned[dedupKey]) { + var caller = getCaller3Info(); + _warn(format('bunyan usage error: %s:%s: attempt to log with an unbound log method: `this` is: %s', + caller.file, caller.line, this.toString()), + dedupKey); + } + return; + } else if (arguments.length === 0) { // `log.()` + return (this._level <= minLevel); + } else if (this._level > minLevel) { + /* pass through */ + } else { + rec = mkRecord(msgArgs); + this._emit(rec); + } + }; +} + + +/** + * The functions below log a record at a specific level. + * + * Usages: + * log.() -> boolean is-trace-enabled + * log.( err, [ msg, ...]) + * log.( msg, ...) + * log.( fields, msg, ...) + * + * where is the lowercase version of the log level. E.g.: + * + * log.info() + * + * @params fields {Object} Optional set of additional fields to log. + * @params msg {String} Log message. This can be followed by additional + * arguments that are handled like + * [util.format](http://nodejs.org/docs/latest/api/all.html#util.format). + */ +Logger.prototype.trace = mkLogEmitter(TRACE); +Logger.prototype.debug = mkLogEmitter(DEBUG); +Logger.prototype.info = mkLogEmitter(INFO); +Logger.prototype.warn = mkLogEmitter(WARN); +Logger.prototype.error = mkLogEmitter(ERROR); +Logger.prototype.fatal = mkLogEmitter(FATAL); + + +//---- Standard serializers +// A serializer is a function that serializes a JavaScript object to a +// JSON representation for logging. There is a standard set of presumed +// interesting objects in node.js-land. + +Logger.stdSerializers = {}; + +/* + * This function dumps long stack traces for exceptions having a cause() + * method. The error classes from + * [verror](https://github.com/davepacheco/node-verror) and + * [restify v2.0](https://github.com/mcavage/node-restify) are examples. + * + * Based on `dumpException` in + * https://github.com/davepacheco/node-extsprintf/blob/master/lib/extsprintf.js + */ +function getFullErrorStack(ex) { + var ret = ex.stack || ex.toString(); + if (ex.cause && typeof (ex.cause) === 'function') { + var cex = ex.cause(); + if (cex) { + ret += '\nCaused by: ' + getFullErrorStack(cex); + } + } + return (ret); +} + +// Serialize an Error object +// (Core error properties are enumerable in node 0.4, not in 0.6). +Logger.stdSerializers.err = function(err) { + if (!err || !err.stack) { + return err; + } + + var obj = { + message: err.message, + name: err.name, + stack: getFullErrorStack(err), + code: err.code, + signal: err.signal + }; + return obj; +}; + + +// A JSON stringifier that handles cycles safely. +// Usage: JSON.stringify(obj, safeCycles()) +function safeCycles() { + var seen = []; + return function (key, val) { + if (!val || typeof (val) !== 'object') { + return val; + } + if (seen.indexOf(val) !== -1) { + return '[Circular]'; + } + seen.push(val); + return val; + }; +} + +//---- Exports + +module.exports = Logger; + +module.exports.TRACE = TRACE; +module.exports.DEBUG = DEBUG; +module.exports.INFO = INFO; +module.exports.WARN = WARN; +module.exports.ERROR = ERROR; +module.exports.FATAL = FATAL; +module.exports.resolveLevel = resolveLevel; +module.exports.levelFromName = levelFromName; +module.exports.nameFromLevel = nameFromLevel; + +module.exports.VERSION = VERSION; +module.exports.LOG_VERSION = LOG_VERSION; + +module.exports.createLogger = function createLogger(options) { + return new Logger(options); +}; + +// Useful for custom `type == 'raw'` streams that may do JSON stringification +// of log records themselves. Usage: +// var str = JSON.stringify(rec, bunyan.safeCycles()); +module.exports.safeCycles = safeCycles; + +//streams +module.exports.ConsoleFormattedStream = ConsoleFormattedStream; +module.exports.ConsoleRawStream = ConsoleRawStream; + +/***/ }), +/* 96 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var dP = __webpack_require__(14).f + , create = __webpack_require__(48) + , redefineAll = __webpack_require__(51) + , ctx = __webpack_require__(19) + , anInstance = __webpack_require__(44) + , defined = __webpack_require__(46) + , forOf = __webpack_require__(37) + , $iterDefine = __webpack_require__(69) + , step = __webpack_require__(104) + , setSpecies = __webpack_require__(109) + , DESCRIPTORS = __webpack_require__(17) + , fastKey = __webpack_require__(31).fastKey + , SIZE = DESCRIPTORS ? '_s' : 'size'; + +var getEntry = function(that, key){ + // fast case + var index = fastKey(key), entry; + if(index !== 'F')return that._i[index]; + // frozen object case + for(entry = that._f; entry; entry = entry.n){ + if(entry.k == key)return entry; + } +}; + +module.exports = { + getConstructor: function(wrapper, NAME, IS_MAP, ADDER){ + var C = wrapper(function(that, iterable){ + anInstance(that, C, NAME, '_i'); + that._i = create(null); // index + that._f = undefined; // first entry + that._l = undefined; // last entry + that[SIZE] = 0; // size + if(iterable != undefined)forOf(iterable, IS_MAP, that[ADDER], that); + }); + redefineAll(C.prototype, { + // 23.1.3.1 Map.prototype.clear() + // 23.2.3.2 Set.prototype.clear() + clear: function clear(){ + for(var that = this, data = that._i, entry = that._f; entry; entry = entry.n){ + entry.r = true; + if(entry.p)entry.p = entry.p.n = undefined; + delete data[entry.i]; + } + that._f = that._l = undefined; + that[SIZE] = 0; + }, + // 23.1.3.3 Map.prototype.delete(key) + // 23.2.3.4 Set.prototype.delete(value) + 'delete': function(key){ + var that = this + , entry = getEntry(that, key); + if(entry){ + var next = entry.n + , prev = entry.p; + delete that._i[entry.i]; + entry.r = true; + if(prev)prev.n = next; + if(next)next.p = prev; + if(that._f == entry)that._f = next; + if(that._l == entry)that._l = prev; + that[SIZE]--; + } return !!entry; + }, + // 23.2.3.6 Set.prototype.forEach(callbackfn, thisArg = undefined) + // 23.1.3.5 Map.prototype.forEach(callbackfn, thisArg = undefined) + forEach: function forEach(callbackfn /*, that = undefined */){ + anInstance(this, C, 'forEach'); + var f = ctx(callbackfn, arguments.length > 1 ? arguments[1] : undefined, 3) + , entry; + while(entry = entry ? entry.n : this._f){ + f(entry.v, entry.k, this); + // revert to the last existing entry + while(entry && entry.r)entry = entry.p; + } + }, + // 23.1.3.7 Map.prototype.has(key) + // 23.2.3.7 Set.prototype.has(value) + has: function has(key){ + return !!getEntry(this, key); + } + }); + if(DESCRIPTORS)dP(C.prototype, 'size', { + get: function(){ + return defined(this[SIZE]); + } + }); + return C; + }, + def: function(that, key, value){ + var entry = getEntry(that, key) + , prev, index; + // change existing entry + if(entry){ + entry.v = value; + // create new entry + } else { + that._l = entry = { + i: index = fastKey(key, true), // <- index + k: key, // <- key + v: value, // <- value + p: prev = that._l, // <- previous entry + n: undefined, // <- next entry + r: false // <- removed + }; + if(!that._f)that._f = entry; + if(prev)prev.n = entry; + that[SIZE]++; + // add to index + if(index !== 'F')that._i[index] = entry; + } return that; + }, + getEntry: getEntry, + setStrong: function(C, NAME, IS_MAP){ + // add .keys, .values, .entries, [@@iterator] + // 23.1.3.4, 23.1.3.8, 23.1.3.11, 23.1.3.12, 23.2.3.5, 23.2.3.8, 23.2.3.10, 23.2.3.11 + $iterDefine(C, NAME, function(iterated, kind){ + this._t = iterated; // target + this._k = kind; // kind + this._l = undefined; // previous + }, function(){ + var that = this + , kind = that._k + , entry = that._l; + // revert to the last existing entry + while(entry && entry.r)entry = entry.p; + // get next entry + if(!that._t || !(that._l = entry = entry ? entry.n : that._t._f)){ + // or finish the iteration + that._t = undefined; + return step(1); + } + // return step by kind + if(kind == 'keys' )return step(0, entry.k); + if(kind == 'values')return step(0, entry.v); + return step(0, [entry.k, entry.v]); + }, IS_MAP ? 'entries' : 'values' , !IS_MAP, true); + + // add [@@species], 23.1.2.2, 23.2.2.2 + setSpecies(NAME); + } +}; + +/***/ }), +/* 97 */ +/***/ (function(module, exports, __webpack_require__) { + +// https://github.com/DavidBruant/Map-Set.prototype.toJSON +var classof = __webpack_require__(45) + , from = __webpack_require__(166); +module.exports = function(NAME){ + return function toJSON(){ + if(classof(this) != NAME)throw TypeError(NAME + "#toJSON isn't generic"); + return from(this); + }; +}; + +/***/ }), +/* 98 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = __webpack_require__(11).document && document.documentElement; + +/***/ }), +/* 99 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = !__webpack_require__(17) && !__webpack_require__(25)(function(){ + return Object.defineProperty(__webpack_require__(66)('div'), 'a', {get: function(){ return 7; }}).a != 7; +}); + +/***/ }), +/* 100 */ +/***/ (function(module, exports, __webpack_require__) { + +// check on default Array iterator +var Iterators = __webpack_require__(30) + , ITERATOR = __webpack_require__(9)('iterator') + , ArrayProto = Array.prototype; + +module.exports = function(it){ + return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it); +}; + +/***/ }), +/* 101 */ +/***/ (function(module, exports, __webpack_require__) { + +// 7.2.2 IsArray(argument) +var cof = __webpack_require__(36); +module.exports = Array.isArray || function isArray(arg){ + return cof(arg) == 'Array'; +}; + +/***/ }), +/* 102 */ +/***/ (function(module, exports, __webpack_require__) { + +// call something on iterator step with safe closing on error +var anObject = __webpack_require__(16); +module.exports = function(iterator, fn, value, entries){ + try { + return entries ? fn(anObject(value)[0], value[1]) : fn(value); + // 7.4.6 IteratorClose(iterator, completion) + } catch(e){ + var ret = iterator['return']; + if(ret !== undefined)anObject(ret.call(iterator)); + throw e; + } +}; + +/***/ }), +/* 103 */ +/***/ (function(module, exports, __webpack_require__) { + +var ITERATOR = __webpack_require__(9)('iterator') + , SAFE_CLOSING = false; + +try { + var riter = [7][ITERATOR](); + riter['return'] = function(){ SAFE_CLOSING = true; }; + Array.from(riter, function(){ throw 2; }); +} catch(e){ /* empty */ } + +module.exports = function(exec, skipClosing){ + if(!skipClosing && !SAFE_CLOSING)return false; + var safe = false; + try { + var arr = [7] + , iter = arr[ITERATOR](); + iter.next = function(){ return {done: safe = true}; }; + arr[ITERATOR] = function(){ return iter; }; + exec(arr); + } catch(e){ /* empty */ } + return safe; +}; + +/***/ }), +/* 104 */ +/***/ (function(module, exports) { + +module.exports = function(done, value){ + return {value: value, done: !!done}; +}; + +/***/ }), +/* 105 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +// 19.1.2.1 Object.assign(target, source, ...) +var getKeys = __webpack_require__(32) + , gOPS = __webpack_require__(71) + , pIE = __webpack_require__(49) + , toObject = __webpack_require__(33) + , IObject = __webpack_require__(68) + , $assign = Object.assign; + +// should work with symbols and should have deterministic property order (V8 bug) +module.exports = !$assign || __webpack_require__(25)(function(){ + var A = {} + , B = {} + , S = Symbol() + , K = 'abcdefghijklmnopqrst'; + A[S] = 7; + K.split('').forEach(function(k){ B[k] = k; }); + return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K; +}) ? function assign(target, source){ // eslint-disable-line no-unused-vars + var T = toObject(target) + , aLen = arguments.length + , index = 1 + , getSymbols = gOPS.f + , isEnum = pIE.f; + while(aLen > index){ + var S = IObject(arguments[index++]) + , keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S) + , length = keys.length + , j = 0 + , key; + while(length > j)if(isEnum.call(S, key = keys[j++]))T[key] = S[key]; + } return T; +} : $assign; + +/***/ }), +/* 106 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.7 / 15.2.3.4 Object.getOwnPropertyNames(O) +var $keys = __webpack_require__(108) + , hiddenKeys = __webpack_require__(67).concat('length', 'prototype'); + +exports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O){ + return $keys(O, hiddenKeys); +}; + +/***/ }), +/* 107 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O) +var has = __webpack_require__(20) + , toObject = __webpack_require__(33) + , IE_PROTO = __webpack_require__(73)('IE_PROTO') + , ObjectProto = Object.prototype; + +module.exports = Object.getPrototypeOf || function(O){ + O = toObject(O); + if(has(O, IE_PROTO))return O[IE_PROTO]; + if(typeof O.constructor == 'function' && O instanceof O.constructor){ + return O.constructor.prototype; + } return O instanceof Object ? ObjectProto : null; +}; + +/***/ }), +/* 108 */ +/***/ (function(module, exports, __webpack_require__) { + +var has = __webpack_require__(20) + , toIObject = __webpack_require__(22) + , arrayIndexOf = __webpack_require__(167)(false) + , IE_PROTO = __webpack_require__(73)('IE_PROTO'); + +module.exports = function(object, names){ + var O = toIObject(object) + , i = 0 + , result = [] + , key; + for(key in O)if(key != IE_PROTO)has(O, key) && result.push(key); + // Don't enum bug & hidden keys + while(names.length > i)if(has(O, key = names[i++])){ + ~arrayIndexOf(result, key) || result.push(key); + } + return result; +}; + +/***/ }), +/* 109 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var global = __webpack_require__(11) + , core = __webpack_require__(3) + , dP = __webpack_require__(14) + , DESCRIPTORS = __webpack_require__(17) + , SPECIES = __webpack_require__(9)('species'); + +module.exports = function(KEY){ + var C = typeof core[KEY] == 'function' ? core[KEY] : global[KEY]; + if(DESCRIPTORS && C && !C[SPECIES])dP.f(C, SPECIES, { + configurable: true, + get: function(){ return this; } + }); +}; + +/***/ }), +/* 110 */ +/***/ (function(module, exports, __webpack_require__) { + +var ctx = __webpack_require__(19) + , invoke = __webpack_require__(173) + , html = __webpack_require__(98) + , cel = __webpack_require__(66) + , global = __webpack_require__(11) + , process = global.process + , setTask = global.setImmediate + , clearTask = global.clearImmediate + , MessageChannel = global.MessageChannel + , counter = 0 + , queue = {} + , ONREADYSTATECHANGE = 'onreadystatechange' + , defer, channel, port; +var run = function(){ + var id = +this; + if(queue.hasOwnProperty(id)){ + var fn = queue[id]; + delete queue[id]; + fn(); + } +}; +var listener = function(event){ + run.call(event.data); +}; +// Node.js 0.9+ & IE10+ has setImmediate, otherwise: +if(!setTask || !clearTask){ + setTask = function setImmediate(fn){ + var args = [], i = 1; + while(arguments.length > i)args.push(arguments[i++]); + queue[++counter] = function(){ + invoke(typeof fn == 'function' ? fn : Function(fn), args); + }; + defer(counter); + return counter; + }; + clearTask = function clearImmediate(id){ + delete queue[id]; + }; + // Node.js 0.8- + if(__webpack_require__(36)(process) == 'process'){ + defer = function(id){ + process.nextTick(ctx(run, id, 1)); + }; + // Browsers with MessageChannel, includes WebWorkers + } else if(MessageChannel){ + channel = new MessageChannel; + port = channel.port2; + channel.port1.onmessage = listener; + defer = ctx(port.postMessage, port, 1); + // Browsers with postMessage, skip WebWorkers + // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' + } else if(global.addEventListener && typeof postMessage == 'function' && !global.importScripts){ + defer = function(id){ + global.postMessage(id + '', '*'); + }; + global.addEventListener('message', listener, false); + // IE8- + } else if(ONREADYSTATECHANGE in cel('script')){ + defer = function(id){ + html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function(){ + html.removeChild(this); + run.call(id); + }; + }; + // Rest old browsers + } else { + defer = function(id){ + setTimeout(ctx(run, id, 1), 0); + }; + } +} +module.exports = { + set: setTask, + clear: clearTask +}; + +/***/ }), +/* 111 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getLogger = exports.LOG_LEVELS = exports.setLogLevel = exports.IceTransportTypes = exports.PlaybackVideoEncoder = exports.PlaybackAudioEncoder = exports.SharedObjectEventTypes = exports.FailoverSubscriberEventTypes = exports.RTMPSubscriberEventTypes = exports.RTCSubscriberEventTypes = exports.SubscriberEventTypes = exports.FailoverPublisherEventTypes = exports.RTCPublisherEventTypes = exports.PublisherEventTypes = exports.Red5ProSharedObject = exports.PlaybackControls = exports.PublisherView = exports.RTMPPublisher = exports.RTCPublisher = exports.Red5ProPublisher = exports.PlaybackView = exports.HLSSubscriber = exports.RTMPSubscriber = exports.RTCSubscriber = exports.Red5ProSubscriber = undefined; + +var _index = __webpack_require__(24); + +Object.defineProperty(exports, 'PlaybackControls', { + enumerable: true, + get: function get() { + return _index.PlaybackControls; + } +}); + +var _log = __webpack_require__(2); + +var _index2 = __webpack_require__(125); + +var subscriberLib = _interopRequireWildcard(_index2); + +var _index3 = __webpack_require__(119); + +var publisherLib = _interopRequireWildcard(_index3); + +var _index4 = __webpack_require__(123); + +var sharedObjectLib = _interopRequireWildcard(_index4); + +var _playback = __webpack_require__(34); + +var playbackEnum = _interopRequireWildcard(_playback); + +var _webrtc = __webpack_require__(55); + +var webrtcEnum = _interopRequireWildcard(_webrtc); + +var _publisherEvent = __webpack_require__(82); + +var publisherEvent = _interopRequireWildcard(_publisherEvent); + +var _subscriberEvent = __webpack_require__(83); + +var subscriberEvent = _interopRequireWildcard(_subscriberEvent); + +var _sharedobjectEvent = __webpack_require__(56); + +var sharedobjectEvent = _interopRequireWildcard(_sharedobjectEvent); + +var _playback2 = __webpack_require__(43); + +var _playback3 = _interopRequireDefault(_playback2); + +var _publish = __webpack_require__(59); + +var _publish2 = _interopRequireDefault(_publish); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +/* ---------------------------- */ +/* Subscription related references. */ +/* ---------------------------- */ + +/** + * The fail-over enabled Subscriber Factory. + * @see Red5ProSubscriber + */ +/** + * Main entry of SDK, accessible on the `window` global at `red5prosdk`. + * + * @file red5pro.min.js + * @module red5prosdk + * + * + */ + +// SDK_VERSION, LOG_LEVEL injected from webpack build. +var Red5ProSubscriber = exports.Red5ProSubscriber = subscriberLib.Red5ProSubscriber; +/** + * The WebRTC based Subscriber. + * + * An instance of `RTCSubscriber` can be created explicitly using this class, or by the `Red5ProSubscriber` fail-over factory. + * @see RTCSubscriber + */ +var RTCSubscriber = exports.RTCSubscriber = subscriberLib.RTCSubscriber; +/** + * The Flash (utilizing RTMP protocol) based Subscriber. + * + * An instance of `RTMPSubscriber` can be created explicitly using this class, or by the `Red5ProSubscriber` fail-over factory. + * @see RTMPSubscriber + */ +var RTMPSubscriber = exports.RTMPSubscriber = subscriberLib.RTMPSubscriber; +/** + * The HLS (HTTP Live Stream) based Subscriber. + * + * An instance of `HLSSubscriber` can be created explicitly using this class, or by the `Red5ProSubscriber` fail-over factory. + * @see HLSSubscriber + */ +var HLSSubscriber = exports.HLSSubscriber = subscriberLib.HLSSubscriber; +/** + * Still used, but API-deprecated View instance for playback. Has default setup in version 4.0.0. + * @private + */ +exports.PlaybackView = _playback3.default; + +/* ---------------------------- */ +/* Broadcast related references. */ +/* ---------------------------- */ + +/** + * The fail-over enabled Publisher Factory. + * @see Red5ProPublisher + */ + +var Red5ProPublisher = exports.Red5ProPublisher = publisherLib.Red5ProPublisher; +/** + * The WebRTC based Publisher.
    An instance of `RTCPublisher` can be created explicitly using this class, or by the `Red5ProPublisher` fail-over factory. + * @see RTCPublisher + */ +var RTCPublisher = exports.RTCPublisher = publisherLib.RTCPublisher; +/** + * The Flash (utilizing RTMP protocol) based Publisher. + * + * An instance of `RTMPPublisher` can be created explicitly using this class, or by the `Red5ProPublisher` fail-over factory. + * @see RTMPPublisher + */ +var RTMPPublisher = exports.RTMPPublisher = publisherLib.RTMPPublisher; +/** + * Still used, but API-deprecated View instance for broadcast/preview. Has default setup in version 4.0.0. + * @private + */ +exports.PublisherView = _publish2.default; + +/* Playback controls interface. */ + +/* Shared Object references. */ +/** + * The ShardObject class. + * @see Red5ProSharedObject + */ +var Red5ProSharedObject = exports.Red5ProSharedObject = sharedObjectLib.Red5ProSharedObject; + +/* Events */ +/** + * Enumeration of common Publisher Events. + */ +var PublisherEventTypes = exports.PublisherEventTypes = publisherEvent.PublisherEventTypes; +/** + * Enueration of events specific to WebRTC-based Publishers. + */ +var RTCPublisherEventTypes = exports.RTCPublisherEventTypes = publisherEvent.RTCPublisherEventTypes; +/** + * Enumeration of events specific to fail-over Publisher factory. + */ +var FailoverPublisherEventTypes = exports.FailoverPublisherEventTypes = publisherEvent.FailoverPublisherEventTypes; +/** + * Enumeraiton of common Subscriber Events. + */ +var SubscriberEventTypes = exports.SubscriberEventTypes = subscriberEvent.SubscriberEventTypes; +/** + * Enumeration of events specific to WebRTC-based Subscribers. + */ +var RTCSubscriberEventTypes = exports.RTCSubscriberEventTypes = subscriberEvent.RTCSubscriberEventTypes; +/** + * Enumeration of events specific to RTMP-based Subscribers. + */ +var RTMPSubscriberEventTypes = exports.RTMPSubscriberEventTypes = subscriberEvent.RTCSubscriberEventTypes; +/** + * Enumeration of events specific to fail-over Subscriber factory. + */ +var FailoverSubscriberEventTypes = exports.FailoverSubscriberEventTypes = subscriberEvent.FailoverSubscriberEventTypes; +/** + * Enumeration of events for Shared Objects. + */ +var SharedObjectEventTypes = exports.SharedObjectEventTypes = sharedobjectEvent.SharedObjectEventTypes; + +/* Enums */ +/** + * Enumerate Audio Encoder options for Subscribers. + * * `OPUS` + * * `PCMU` + * * `PCMA` + * * `SPEEX` + * * `NONE` + */ +var PlaybackAudioEncoder = exports.PlaybackAudioEncoder = playbackEnum.PlaybackAudioEncoder; +/** + * Enumerated Video Encoder options for Subscribers. + * * `VP8` + * * `H264` + * * `NONE` + */ +var PlaybackVideoEncoder = exports.PlaybackVideoEncoder = playbackEnum.PlaybackVideoEncoder; + +/** + * Enumerate ICE Transport options for Publishers and Subscribers. + * * `UDP` + * * `TCP` + */ +var IceTransportTypes = exports.IceTransportTypes = webrtcEnum.IceTransportTypes; + +(0, _log.establishLogger)('' + "debug" || _log.LEVELS.DEBUG); // eslint-disable-line no-undef + +/** + * Sets the log level for logs from the SDK + * @param {string} level + * The specified log level. + * @see LOG_LEVELS + */ +var setLogLevel = exports.setLogLevel = function setLogLevel(level) { + if (_log.LEVELS.hasOwnProperty(level.toUpperCase())) { + (0, _log.establishLogger)(level); + if (console) { + console.log('Red5 Pro SDK Version ' + "5.2.1"); // eslint-disable-line no-undef,no-console + } + } +}; + +/** + * The enumerated log level Strings. + * * `TRACE` + * * `INFO` + * * `DEBUG` + * * `WARN` + * * `ERROR` + * * `FATAL` + */ +var LOG_LEVELS = exports.LOG_LEVELS = _log.LEVELS; +/** + * Retrieves the Logger instance used by the SDK. + * + * @returns {Logger} + * The logger. + */ +var getLogger = exports.getLogger = _log.getLogger; + +/***/ }), +/* 112 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +var jsonAttr = /['"](.*?)['"]:/gi; +var jsonVal = /:['"](.*?)['"]/gi; + +/** + * Reads the UTF string of the data passed in. + * + * @param {String} data + * @param {Number} start + * @param {Number} len + * + * @return {String} + * The Parsed information. + * + * @private + */ +function readUTF(data, start, len) { + var result = '', + offset = start, + end = start + len; + do { + result += String.fromCharCode(data[offset++]); + } while (offset < end); + return result; +} + +/** + * Parses and interprets the orientation data from passed in JSON string. + * + * @param {String} text + * + * @return {Object} + * The parsed object with an `orientation` property if parsed properly. + * + * @private + */ +function parseJSONForOrientation(text) { + try { + var value = JSON.parse(text); + if (value.hasOwnProperty('orientation')) { + return { + orientation: parseInt(value.orientation) + }; + } + return undefined; + } catch (e) { + var match = jsonAttr.exec(text); + var match2 = void 0; + if (match && match.length > 1) { + match2 = jsonVal.exec(text); + if (match[1] === 'orientation' && match2 && match2.length > 1) { + return { + orientation: parseInt(match2[1]) + }; + } + } + return undefined; + } +} + +/** + * Event handler for metadata related to orientation information. + * + * @param {Element} player + * The media element related to the metadata. + * @param {Function} callback + * The callback to invoke with the parsed orientation information. + * + * @private + */ +var onOrientationMetadata = exports.onOrientationMetadata = function onOrientationMetadata(player, callback) { + + var textTracks = typeof player.textTracks === 'function' ? player.textTracks() : player.textTracks; + + if (textTracks) { + + player.addTextTrack('metadata'); + + textTracks.addEventListener('addtrack', function (addTrackEvent) { + + var track = addTrackEvent.track; + track.mode = 'hidden'; + track.addEventListener('cuechange', function (cueChangeEvent) { + var cues = void 0; + var i = void 0; + // Mostly Chrome. + if (cueChangeEvent && cueChangeEvent.currentTarget) { + cues = cueChangeEvent.currentTarget.cues; + } else if (undefined === undefined) { + cues = track.cues; + cues = cues && cues.length > 0 ? cues : track.activeCues; + } else if (undefined !== undefined) { + // Mostly Firefox & Safari. + cues = cues && cues.length > 0 ? cues : undefined.activeCues; + } + // Mostly failure. + cues = cues || []; + for (i = 0; i < cues.length; i++) { + var data = cues[i]; + if (data.value) { + var text = typeof data.value.data === 'string' ? data.value.data : readUTF(data.value.data, 0, data.size); + var orientation = parseJSONForOrientation(text); + if (typeof orientation !== 'undefined') { + callback(orientation); + break; + } + } + } + }); + }); + } +}; + +/***/ }), +/* 113 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/** + * Exception for missing element when assigning Presentation Controllers for Publishers and Subscribers. + */ + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.NoSupportedCameraResolutionsError = exports.NoElementFoundError = undefined; + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var NoElementFoundError = exports.NoElementFoundError = function NoElementFoundError(message) { + (0, _classCallCheck3.default)(this, NoElementFoundError); + + this.name = 'NoElementFound'; + this.message = message; +}; + +/** + * Exception when requesting media with a `MediaConstraint` that the browser cannot support. + * WebRTC Only. + */ + + +var NoSupportedCameraResolutionsError = exports.NoSupportedCameraResolutionsError = function NoSupportedCameraResolutionsError(message) { + (0, _classCallCheck3.default)(this, NoSupportedCameraResolutionsError); + + this.name = 'NoSupportedCameraResolutionsError'; + this.message = message; +}; + +/***/ }), +/* 114 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = __webpack_require__(6); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = __webpack_require__(8); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _get2 = __webpack_require__(93); + +var _get3 = _interopRequireDefault(_get2); + +var _inherits2 = __webpack_require__(7); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _socketHelper = __webpack_require__(57); + +var _socketHelper2 = _interopRequireDefault(_socketHelper); + +var _object = __webpack_require__(28); + +var _log = __webpack_require__(2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var NAME = 'R5ProPublisherSocket'; + +/** + * Publisher-based extension of `SocketHelper`. + * + * @extends {SocketHelper} + * + * @private + */ + +var PublisherSocketHelper = function (_SocketHelper) { + (0, _inherits3.default)(PublisherSocketHelper, _SocketHelper); + + function PublisherSocketHelper(responder) { + (0, _classCallCheck3.default)(this, PublisherSocketHelper); + return (0, _possibleConstructorReturn3.default)(this, (PublisherSocketHelper.__proto__ || (0, _getPrototypeOf2.default)(PublisherSocketHelper)).call(this, responder, NAME)); + } + + /** + * Override to respond to messages coming over WebSocket. + */ + + + (0, _createClass3.default)(PublisherSocketHelper, [{ + key: 'respond', + value: function respond(message) { + if (message.data) { + var json = this.getJsonFromSocketMessage(message); + try { + if (!(0, _get3.default)(PublisherSocketHelper.prototype.__proto__ || (0, _getPrototypeOf2.default)(PublisherSocketHelper.prototype), 'respond', this).call(this, message)) { + if (json.data !== undefined) { + if (json.data.sdp !== undefined) { + if (json.data.sdp.type === 'answer') { + this._responder.onSDPAnswer(json.data); + } + } + if (json.data.candidate !== undefined) { + if ((0, _object.isObjectEmpty)(json.data.candidate)) { + this._responder.onEmptyCandidate(); + } else { + this._responder.onAddIceCandidate(json.data.candidate); + } + } + if (json.data.type === 'status') { + if (json.data.code === 'NetConnection.ICE.TricleCompleted' || json.data.code === 'NetConnection.ICE.TrickleCompleted') { + this._responder.onSocketIceCandidateEnd(); + } else { + this._responder.onPublisherStatus(json.data); + } + } + } + } + } catch (e) { + (0, _log.error)(NAME, '[ws.onmessage] - Error in accessing message data as JSON. ' + e.message); + this._responder.onSocketMessageError('[ws.onmessage] - Error in accessing message data as JSON. ' + e.message); + } + } else { + (0, _log.warn)(NAME, '[ws.onmessage] - No Message Data.'); + } + } + }]); + return PublisherSocketHelper; +}(_socketHelper2.default); + +exports.default = PublisherSocketHelper; + +/***/ }), +/* 115 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = __webpack_require__(6); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = __webpack_require__(8); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _get2 = __webpack_require__(93); + +var _get3 = _interopRequireDefault(_get2); + +var _inherits2 = __webpack_require__(7); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _socketHelper = __webpack_require__(57); + +var _socketHelper2 = _interopRequireDefault(_socketHelper); + +var _object = __webpack_require__(28); + +var _log = __webpack_require__(2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var NAME = 'R5ProSubscriptionSocket'; + +/** + * Subscriber-based extension of `SocketHelper`. + * + * @extends {SocketHelper} + * + * @private + */ + +var SubscriptionSocketHelper = function (_SocketHelper) { + (0, _inherits3.default)(SubscriptionSocketHelper, _SocketHelper); + + function SubscriptionSocketHelper(responder) { + (0, _classCallCheck3.default)(this, SubscriptionSocketHelper); + return (0, _possibleConstructorReturn3.default)(this, (SubscriptionSocketHelper.__proto__ || (0, _getPrototypeOf2.default)(SubscriptionSocketHelper)).call(this, responder, NAME)); + } + + /** + * Override to respond to messages coming over WebSocket. + */ + + + (0, _createClass3.default)(SubscriptionSocketHelper, [{ + key: 'respond', + value: function respond(message) { + if (message.data) { + var json = this.getJsonFromSocketMessage(message); + try { + if (!(0, _get3.default)(SubscriptionSocketHelper.prototype.__proto__ || (0, _getPrototypeOf2.default)(SubscriptionSocketHelper.prototype), 'respond', this).call(this, message)) { + if (json.data !== undefined) { + if (json.data.sdp !== undefined) { + if (json.data.sdp.type === 'offer') { + this._responder.onSDPOffer(json.data); + } + } + if (json.data.candidate !== undefined) { + if ((0, _object.isObjectEmpty)(json.data.candidate)) { + this._responder.onEmptyCandidate(); + } else { + this._responder.onAddIceCandidate(json.data.candidate); + } + } + if (json.data.type === 'status') { + if (json.data.code === 'NetConnection.ICE.TricleCompleted' || json.data.code === 'NetConnection.ICE.TrickleCompleted') { + this._responder.onSocketIceCandidateEnd(); + } else if (json.data.code === 'NetStream.Play.UnpublishNotify') { + this._responder.onUnpublish(); + } else if (json.data.code === 'NetConnection.Connect.Closed') { + this._responder.onConnectionClosed(); + } else { + this._responder.onSubscriberStatus(json.data); + } + } + if (json.data.hasOwnProperty('status')) { + if (json.data.status === 'NetStream.Play.UnpublishNotify') { + this._responder.onUnpublish(); + } + } + if (json.type !== undefined) { + if (json.type === 'metadata') { + // It is a `send` API invocation. + if (json.method !== undefined) { + this._responder.onSendReceived(json.method, json.data); + } + // Else it is normal metadata. + else { + this._responder.onMetaData(json.data); + } + } + } + } else if (json.type !== undefined) { + if (json.type === 'metadata') { + this._responder.onMetaData(json.metadata); + } + } + } + } catch (e) { + (0, _log.error)(NAME, '[ws.onmessage] - Error in accessing message data as JSON. ' + e.message); + this._responder.onSocketMessageError('[ws.onmessage] - Error in accessing message data as JSON. ' + e.message); + } + } else { + (0, _log.warn)(NAME, '[ws.onmessage] - No Message Data.'); + } + } + }]); + return SubscriptionSocketHelper; +}(_socketHelper2.default); + +exports.default = SubscriptionSocketHelper; + +/***/ }), +/* 116 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _stringify = __webpack_require__(12); + +var _stringify2 = _interopRequireDefault(_stringify); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _webrtc = __webpack_require__(41); + +var webrtc = _interopRequireWildcard(_webrtc); + +var _promise = __webpack_require__(5); + +var _log = __webpack_require__(2); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var NAME = 'R5ProPublishPeer'; + +/** + * Proxy to Peer Connection for Publishers. + * + * @private + */ + +var PublisherPeerHelper = function () { + function PublisherPeerHelper(responder) { + (0, _classCallCheck3.default)(this, PublisherPeerHelper); + + this._responder = responder; + this._peerConnection = undefined; + } + + /** + * Removes handlers assigned to the peer connection instance. + * + * @param {RTCPeerConnection} connection + */ + + + (0, _createClass3.default)(PublisherPeerHelper, [{ + key: '_removeConnectionHandlers', + value: function _removeConnectionHandlers(connection) { + connection.onconnectionstatechange = undefined; + connection.oniceconnectionstatechange = undefined; + connection.onicecandidate = undefined; + } + + /** + * Assigns handlers to events on the peer connection instance. + * + * @param {RTCPeerConnection} connection + * @param {Promise} promise + * The `Promise` to resolve or reject on success of connection. + */ + + }, { + key: '_addConnectionHandlers', + value: function _addConnectionHandlers(connection, promise) { + var _this = this; + + var reconnectTimeout = void 0; + var timeoutLimit = 5000; + + connection.onconnectionstatechange = function () { + (0, _log.debug)(NAME, '[peer.onconnectionstatechange] - State: ' + connection.connectionState); + if (connection.connectionState === 'connected') { + (0, _log.debug)(NAME, '[peerconnection:open]'); + if (promise) { + promise.resolve(_this); + } + } else if (connection.connectionState === 'failed' || connection.connectionState === 'disconnected') { + (0, _log.warn)(NAME, '[peerconnection:error]'); + if (promise) { + promise.reject(); + } + } else { + (0, _log.debug)(NAME, '[peerconnection:' + connection.connectionState + ']'); + } + }; + + connection.onicecandidate = function (event) { + (0, _log.debug)(NAME, '[peer.onicecandidate] - Peer Candidate: ' + event.candidate); + if (event.candidate) { + _this._responder.onIceCandidate(event.candidate); + } else if (event.candidate === null) { + // null means they have finished sending candidates back and forth? + // Moved to notification from server on trickle end event. + // this._responder.onIceCandidateTrickleEnd() + } + }; + + connection.oniceconnectionstatechange = function (event) { + var state = connection.iceConnectionState; + (0, _log.debug)(NAME, '[peer.oniceconnectionstatechange] - State: ' + state); + if (state === 'failed') { + if (reconnectTimeout) { + clearTimeout(reconnectTimeout); + } + _this._responder.onPeerConnectionClose(event); + } else if (state === 'disconnected') { + // may receive a disconnect temporarily that will then return to a connection. + reconnectTimeout = setTimeout(function () { + (0, _log.debug)(NAME, '[peer.oniceconnectionstatechange] - Reconnect timeout reached. Closing PeerConnection.'); + clearTimeout(reconnectTimeout); + _this._responder.onPeerConnectionClose(event); + }, timeoutLimit); + } else { + if (reconnectTimeout) { + (0, _log.debug)(NAME, '[peer.oniceconnectionstatechange] - Clearing timeout for reconnect.'); + clearTimeout(reconnectTimeout); + } + } + }; + + connection.onsignalingstatechange = function (event) { + // eslint-disable-line no-unused-vars + var state = connection.signalingState; + (0, _log.debug)(NAME, '[peer.onsignalingstatechange] - State: ' + state); + }; + + connection.onicegatheringstatechange = function () { + var state = connection.iceGatheringState; + (0, _log.debug)(NAME, '[peer.onicegatheringstatechange] - State: ' + state); + if (state === 'complete') { + _this._responder.onPeerGatheringComplete(); + } + }; + + connection.onremovestream = function () { + (0, _log.debug)(NAME, '[peer.onremovestream]'); + }; + } + + /** + * Request to `getUserMedia` on browser. + * + * @param {Object} contraints + * The `MediaConstraints` object. + * @return {Promise} + */ + + }, { + key: 'getUserMedia', + value: function getUserMedia(constraints) { + return webrtc.getUserMedia(constraints); + } + + /** + * Request to force `getUserMedia` request using the provided constraints. + * + * @param {Object} constraints + * The `MediaConstraints` to force in request on `getUserMedia`. + * @return {Promise} + */ + + }, { + key: 'forceUserMedia', + value: function forceUserMedia(constraints) { + return webrtc.forceUserMedia(constraints); + } + + /** + * Request to create an Offer through the Peer Connection. + * + * @param {Object} bandwidth + * The optional bandwidth configuration to use in munging SDP before sending offer. + * @param {Promise} promise + * The `Promise` to resolve or reject on success of sending offer on Peer Connection. + * @return {Promise} + */ + + }, { + key: 'createOffer', + value: function createOffer() { + var _this2 = this; + + var bandwidth = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var offerPromise = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + + (0, _log.debug)(NAME, '[createoffer]'); + var p = offerPromise || new _promise.DeferredPromise(); + this._peerConnection.createOffer().then(function (sessionDescription) { + _this2.setLocalDescription(sessionDescription, bandwidth).then(function () { + if (bandwidth) { + sessionDescription.sdp = webrtc.updateBandwidth(bandwidth, sessionDescription.sdp); + } + _this2._responder.onSDPSuccess(); + p.resolve(sessionDescription); + }).catch(function (err) { + _this2._responder.onSDPError(err); + p.reject(err); + }); + }).catch(function (err) { + (0, _log.debug)(NAME, '[createoffer:error]'); + p.reject(err); + }); + return p.hasOwnProperty('promise') ? p.promise : p; + } + + /** + * Request to set local description on the Peer Connection. + * + * @param {Object} sessionDescription + * @return {Promise} + */ + + }, { + key: 'setLocalDescription', + value: function setLocalDescription(sessionDescription) { + (0, _log.debug)(NAME, '[setlocaldescription]'); + return this._peerConnection.setLocalDescription(sessionDescription); + } + + /** + * Request to set remote description. + * + * @param {Object} sdp + * The Session Description tot set on the Peer Connection. + * @return {Promise} + */ + + }, { + key: 'setRemoteDescription', + value: function setRemoteDescription(sdp) { + (0, _log.debug)(NAME, '[setremotedescription]'); + return this._peerConnection.setRemoteDescription(new webrtc.RTCSessionDescription(sdp)); + } + + /** + * Request to add ICE candidate to Peer Connection. + * + * @param {Object} candidate + * @return {Promise} + */ + + }, { + key: 'addIceCandidate', + value: function addIceCandidate(candidate) { + (0, _log.debug)(NAME, '[addcandidate]'); + return this._peerConnection.addIceCandidate(candidate); + } + + /** + * Request to setup the proxied Peer Connection instance. + * + * @param {Array} iceServers + * List of ICE servers to use in the connection. + * @param {Promise} setUpPromise + * The `Promise` to resolve or reject on in success in setting up the Peer Connection. + * @param {String} rtcpMuxPolicy + * The type of mux policy to use. + * @return {Promise} + */ + + }, { + key: 'setUp', + value: function setUp(iceServers) { + var setUpPromise = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + var rtcpMuxPolicy = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined; + + this.tearDown(); + var p = setUpPromise || new _promise.DeferredPromise(); + try { + var peerConfig = { + iceServers: iceServers, + iceCandidatePoolSize: 2, + bundlePolicy: 'max-bundle' + }; + if (typeof rtcpMuxPolicy !== 'undefined') { + peerConfig.rtcpMuxPolicy = rtcpMuxPolicy; + } + (0, _log.debug)(NAME, '[peerconnection:setup]: ' + (0, _stringify2.default)(peerConfig, null, 2)); + var peer = new webrtc.RTCPeerConnection(peerConfig, { + optional: [{ RtpDataChannels: false }, { googCpuOveruseDetection: true }] + }); + this._addConnectionHandlers(peer); + this._peerConnection = peer; + p.resolve(peer); + } catch (e) { + (0, _log.warn)(NAME, 'Could not establish a PeerConnection. ' + e.message); + p.reject(e.message); + } + return p.hasOwnProperty('promise') ? p.promise : p; + } + + /** + * Request to tear down proxied Peer Connection instance. + */ + + }, { + key: 'tearDown', + value: function tearDown() { + if (this._peerConnection) { + (0, _log.debug)(NAME, '[teardown]'); + this._removeConnectionHandlers(this._peerConnection); + try { + this._peerConnection.close(); + } catch (e) { + (0, _log.warn)(NAME, '[peerconnection.close] error: ' + e.message); + } finally { + this._peerConnection = undefined; + } + } + } + + /** + * Accessor for the proxied RTCPeerConnection instance. + * + * @return {RTCPeerConnection} + */ + + }, { + key: 'connection', + get: function get() { + return this._peerConnection; + } + }]); + return PublisherPeerHelper; +}(); + +exports.default = PublisherPeerHelper; + +/***/ }), +/* 117 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _stringify = __webpack_require__(12); + +var _stringify2 = _interopRequireDefault(_stringify); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _webrtc = __webpack_require__(41); + +var webrtc = _interopRequireWildcard(_webrtc); + +var _promise = __webpack_require__(5); + +var _log = __webpack_require__(2); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var NAME = 'R5ProSubscriptionPeer'; + +/** + * Utility to check if candidate is empty, and considered the end of the trickle negotiation for a subscriber. + * + * @param {Object} candidate + * + * @private + */ +var isEmptyCandidate = function isEmptyCandidate(candidate) { + return typeof candidate === 'undefined' || typeof candidate === 'string' && candidate.length === 0; +}; + +/** + * Proxy to Peer Connection for Subscribers. + * + * @private + */ + +var SubscriptionPeerHelper = function () { + function SubscriptionPeerHelper(responder) { + (0, _classCallCheck3.default)(this, SubscriptionPeerHelper); + + this._responder = responder; + this._peerConnection = undefined; + this._pendingMediaStream = undefined; + } + + /** + * Removes handlers assigned to the peer connection instance. + * + * @param {RTCPeerConnection} connection + */ + + + (0, _createClass3.default)(SubscriptionPeerHelper, [{ + key: '_removeConnectionHandlers', + value: function _removeConnectionHandlers(connection) { + connection.onconnectionstatechange = undefined; + connection.oniceconnectionstatechange = undefined; + connection.onicecandidate = undefined; + // connection.onaddstream = undefined + connection.ontrack = undefined; + } + + /** + * Assigns handlers to events on the peer connection instance. + * + * @param {RTCPeerConnection} connection + * @param {Promise} promise + * The `Promise` to resolve or reject on success of connection. + */ + + }, { + key: '_addConnectionHandlers', + value: function _addConnectionHandlers(connection, promise) { + var _this = this; + + var reconnectTimeout = void 0; + var timeoutLimit = 5000; + + connection.onconnectionstatechange = function () { + if (connection.connectionState === 'connected') { + (0, _log.debug)(NAME, '[peerconnection:open]'); + if (promise) { + promise.resolve(_this); + } + } else if (connection.connectionState === 'failed' || connection.connectionState === 'disconnected') { + (0, _log.warn)(NAME, '[peerconnection:error]'); + if (promise) { + promise.reject(); + } + } + }; + + connection.onicecandidate = function (event) { + (0, _log.debug)(NAME, '[peer.onicecandidate] - Peer Candidate: ' + event.candidate); + if (event.candidate) { + _this._responder.onIceCandidate(event.candidate); + } else if (event.candidate === null) { + // null means they have finished sending candidates back and forth? + _this._responder.onIceCandidateTrickleEnd(_this._pendingMediaStream); + _this._pendingMediaStream = undefined; + } + }; + + /* + connection.onaddstream = (event) => { + debug(NAME, `(onaddstream) Peer Add Stream: ${event.stream}`) + if (event.stream && this._pendingMediaStream === undefined) { + this._pendingMediaStream = event.stream + this._responder.onAnswerMediaStream(event.stream) + } + } + */ + + // Picked up by Firefox, all others use `onaddstream`, but adapter.js will call both, so we limit. + connection.ontrack = function (event) { + (0, _log.debug)(NAME, '(ontrack) Peer Add Stream: ' + event.streams); + if (event.streams && event.streams.length > 0 && _this._pendingMediaStream === undefined) { + _this._pendingMediaStream = event.streams[0]; + _this._responder.onAnswerMediaStream(event.streams[0]); + } + }; + + connection.oniceconnectionstatechange = function (event) { + var state = connection.iceConnectionState; + (0, _log.debug)(NAME, '[peer.oniceconnectionstatechange] - State: ' + state); + if (state === 'failed') { + if (reconnectTimeout) { + clearTimeout(reconnectTimeout); + } + _this._responder.onPeerConnectionClose(event); + } else if (state === 'disconnected') { + // may receive a disconnect temporarily that will then return to a connection. + reconnectTimeout = setTimeout(function () { + (0, _log.debug)(NAME, '[peer.oniceconnectionstatechange] - Reconnect timeout reached. Closing PeerConnection.'); + clearTimeout(reconnectTimeout); + _this._responder.onPeerConnectionClose(event); + }, timeoutLimit); + } else { + if (reconnectTimeout) { + (0, _log.debug)(NAME, '[peer.oniceconnectionstatechange] - Clearing timeout for reconnect.'); + clearTimeout(reconnectTimeout); + } + } + }; + + connection.onicegatheringstatechange = function () { + var state = connection.iceGatheringState; + (0, _log.debug)(NAME, '[peer.onicegatheringstatechange] - State: ' + state); + if (state === 'complete') { + _this._responder.onPeerGatheringComplete(); + } + }; + + connection.onremovestream = function () { + (0, _log.debug)(NAME, '[peer.onremovestream]'); + }; + } + + /** + * Request to create answer on Peer Connection. + * + * @param {Object} sdp + * The Session Description to set as remote description. + * @return {Promise} + */ + + }, { + key: 'createAnswer', + value: function createAnswer(sdp) { + var _this2 = this; + + (0, _log.debug)(NAME, '[createanswer]'); + var deferred = new _promise.DeferredPromise(); + + this._peerConnection.setRemoteDescription(sdp).then(this._responder.onSDPSuccess).catch(function (err) { + _this2._responder.onSDPError(err); + }); + + this._peerConnection.createAnswer().then(function (sessionDescription) { + _this2._peerConnection.setLocalDescription(sessionDescription).then(_this2._responder.onSDPSuccess).catch(function (err) { + _this2._responder.onSDPError(err); + }); + deferred.resolve(sessionDescription); + }).catch(deferred.reject); + + return deferred.promise; + } + + /** + * Request to add ICE candidate to Peer Connection. + * + * @param {Object} candidate + * @return {Promise} + */ + + }, { + key: 'addIceCandidate', + value: function addIceCandidate(candidate) { + (0, _log.debug)(NAME, 'checking if empty...'); + if (isEmptyCandidate(candidate)) { + (0, _log.debug)(NAME, '[addicecandidate]:: empty'); + } else if (candidate !== null) { + (0, _log.debug)(NAME, '[addicecandidate] :: non-empty'); + var iceCandidate = new webrtc.RTCIceCandidate({ + sdpMLineIndex: candidate.sdpMLineIndex, + candidate: candidate.candidate + }); + this._peerConnection.addIceCandidate(iceCandidate).then(function () { + // nada + }).catch(function (err) { + (0, _log.error)(NAME, 'Error in add of ICE Candidiate + ' + err); + }); + } else { + (0, _log.debug)(NAME, '[addicecandidate] :: null'); + this._peerConnection.addIceCandidate(candidate).then(function () { + // nada + }).catch(function (err) { + (0, _log.error)(NAME, 'Error in add of ICE Candidiate + ' + err); + }); + } + } + + /** + * Request to setup the proxied Peer Connection instance. + * + * @param {Array} iceServers + * List of ICE servers to use in the connection. + * @param {Promise} setUpPromise + * The `Promise` to resolve or reject on in success in setting up the Peer Connection. + * @param {String} rtcpMuxPolicy + * The type of mux policy to use. + * @return {Promise} + */ + + }, { + key: 'setUp', + value: function setUp(iceServers) { + var setUpPromise = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + var rtcpMuxPolicy = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined; + + this.tearDown(); + var p = setUpPromise || new _promise.DeferredPromise(); + try { + var peerConfig = { + iceServers: iceServers, + iceCandidatePoolSize: 2, + bundlePolicy: "max-bundle" + }; + if (typeof rtcpMuxPolicy !== 'undefined') { + peerConfig.rtcpMuxPolicy = rtcpMuxPolicy; + } + (0, _log.debug)(NAME, '[peerconnection:setup]: ' + (0, _stringify2.default)(peerConfig, null, 2)); + var peer = new webrtc.RTCPeerConnection(peerConfig, { + optional: [{ RtpDataChannels: false }, { googCpuOveruseDetection: true }] + }); + this._peerConnection = peer; + this._addConnectionHandlers(peer); + p.resolve(); + } catch (e) { + (0, _log.warn)(NAME, 'Could not create a RTCPeerConnection. Error: ' + e.message); + p.reject(e.message); + } + return p.hasOwnProperty('promise') ? p.promise : p; + } + + /** + * Request to tear down proxied Peer Connection instance. + */ + + }, { + key: 'tearDown', + value: function tearDown() { + if (this._peerConnection) { + (0, _log.debug)(NAME, '[teardown]'); + this._removeConnectionHandlers(this._peerConnection); + try { + this._peerConnection.close(); + } catch (e) { + (0, _log.warn)(NAME, '[peerconnection.close] error: ' + e.message); + } + } + this._pendingMediaStream = undefined; + this._peerConnection = undefined; + } + + /** + * Accessor for the proxied RTCPeerConnection instance. + * + * @return {RTCPeerConnection} + */ + + }, { + key: 'connection', + get: function get() { + return this._peerConnection; + } + }]); + return SubscriptionPeerHelper; +}(); + +exports.default = SubscriptionPeerHelper; + +/***/ }), +/* 118 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.RawStream = undefined; + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _browserBunyan = __webpack_require__(95); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Custom logger for bunyon. + * + * @private + */ +var RawStream = exports.RawStream = function () { + function RawStream() { + (0, _classCallCheck3.default)(this, RawStream); + } + + (0, _createClass3.default)(RawStream, [{ + key: 'write', + value: function write(rec) { + console.log('%s - [%s] %s: %s', // eslint-disable-line no-console + rec.time.toISOString(), rec.name, _browserBunyan.nameFromLevel[rec.level], rec.msg); + } + }]); + return RawStream; +}(); + +/***/ }), +/* 119 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.RTCPublisher = exports.RTMPPublisher = exports.Red5ProPublisher = undefined; + +var _set = __webpack_require__(92); + +var _set2 = _interopRequireDefault(_set); + +var _toConsumableArray2 = __webpack_require__(94); + +var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2); + +var _getPrototypeOf = __webpack_require__(6); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = __webpack_require__(8); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = __webpack_require__(7); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _map = __webpack_require__(89); + +var _map2 = _interopRequireDefault(_map); + +var _implFactoryOrder = __webpack_require__(87); + +var _implFactoryOrder2 = _interopRequireDefault(_implFactoryOrder); + +var _eventEmitter = __webpack_require__(23); + +var _eventEmitter2 = _interopRequireDefault(_eventEmitter); + +var _red5proRtmp = __webpack_require__(122); + +var _red5proRtmp2 = _interopRequireDefault(_red5proRtmp); + +var _red5proRtc = __webpack_require__(121); + +var _red5proRtc2 = _interopRequireDefault(_red5proRtc); + +var _promise = __webpack_require__(5); + +var _publish = __webpack_require__(54); + +var _log = __webpack_require__(2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var NAME = 'Red5ProPublisher'; +var publishFactory = new _implFactoryOrder2.default(); +var publisherImpl = function () { + var map = new _map2.default(); + map.set(_publish.PublishTypes.RTC, _red5proRtc2.default); + map.set(_publish.PublishTypes.RTMP, _red5proRtmp2.default); + return map; +}(); + +/** + * Main entry for failover support of all publisher implementations. + * + * @extends EventEmitter + */ + +var Red5ProPublisher = function (_EventEmitter) { + (0, _inherits3.default)(Red5ProPublisher, _EventEmitter); + + function Red5ProPublisher() { + (0, _classCallCheck3.default)(this, Red5ProPublisher); + + var _this = (0, _possibleConstructorReturn3.default)(this, (Red5ProPublisher.__proto__ || (0, _getPrototypeOf2.default)(Red5ProPublisher)).call(this)); + + _this._options = undefined; + _this._order = [_publish.PublishTypes.RTC, _publish.PublishTypes.RTMP]; + return _this; + } + + /** + * Utilizes Failover Publisher Factory to attempt in determining browser support for Publisher from defined order. + * + * @return {Promise} + * + * @private + */ + + + (0, _createClass3.default)(Red5ProPublisher, [{ + key: '_getPublisherFromOrder', + value: function _getPublisherFromOrder(order, options) { + return publishFactory.create(order, publisherImpl, options, 'init'); + } + + /** + * Returns the specified order for auto-failover. + * + * @return {Array} + * Default: `['rtc', 'rtmp']`. + */ + + }, { + key: 'getPublishOrder', + value: function getPublishOrder() { + return this._order; + } + + /** + * Defines the desired auto-failover order. + * + * @param {Array} order + * The desired order. e.g, `['rtc', 'rtmp']`. + * + * @return {Red5ProPublisher} + * This instance. + */ + + }, { + key: 'setPublishOrder', + value: function setPublishOrder(order) { + // Allow for string value to define single item in order. + order = typeof order === 'string' ? [order] : order; + + // Filter out values not available in enumeration of playback types. + var t = order.filter(function (entry) { + var key = void 0; + for (key in _publish.PublishTypes) { + if (_publish.PublishTypes[key].toLowerCase() === entry.toLowerCase()) { + return true; + } + } + return false; + }).map(function (entry) { + return entry.toLowerCase(); + }); + + // Define new order. + this._order = [].concat((0, _toConsumableArray3.default)(new _set2.default(t))); + (0, _log.debug)(NAME, '[orderupdate]: ' + this._order); + return this; + } + + /** + * Request to initialize and determine the proper Publisher implementation based on configuration. + * The returned `Promise` will either resolve with the determined Publisher instance or reject with an error String in failure to determine Publisher type. + * + * @param {Object} options + * The initialization configuration map for each desired failover tech. + * @return {Promise} + */ + + }, { + key: 'init', + value: function init(options) { + var deferred = new _promise.DeferredPromise(); + (0, _log.debug)(NAME, '[publish]'); + this._options = options; + this._getPublisherFromOrder(this._order, this._options).then(function (publisher) { + deferred.resolve(publisher); + }).catch(function (err) { + (0, _log.warn)(NAME, '[publisherror]: Could not implement a publisher: ' + err); + deferred.reject(err); + }); + return deferred.promise; + } + + /** + * Return enumerated value Publisher types used in failover order. + * @type {Object} + */ + + }, { + key: 'publishTypes', + get: function get() { + return _publish.PublishTypes; + } + }]); + return Red5ProPublisher; +}(_eventEmitter2.default); + +exports.Red5ProPublisher = Red5ProPublisher; +exports.RTMPPublisher = _red5proRtmp2.default; +exports.RTCPublisher = _red5proRtc2.default; + +/***/ }), +/* 120 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _isNan = __webpack_require__(135); + +var _isNan2 = _interopRequireDefault(_isNan); + +var _stringify = __webpack_require__(12); + +var _stringify2 = _interopRequireDefault(_stringify); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _embed = __webpack_require__(80); + +var embed = _interopRequireWildcard(_embed); + +var _browser = __webpack_require__(4); + +var _browser2 = _interopRequireDefault(_browser); + +var _sharedobjectHelperRtmp = __webpack_require__(84); + +var _sharedobjectHelperRtmp2 = _interopRequireDefault(_sharedobjectHelperRtmp); + +var _util = __webpack_require__(88); + +var _object = __webpack_require__(28); + +var _promise = __webpack_require__(5); + +var _log = __webpack_require__(2); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var NAME = 'R5ProPublisherSourceHandler'; + +/** + * Determine the video dimensions setting value based on possible definition using `MediaConstraint`. + * @private + */ +var convertDimensionOptions = function convertDimensionOptions(vo) { + return vo.exact || vo.ideal || vo.max || vo.min || vo; +}; + +/** + * Define the audio and video settings for Flash. + * The `width` and `height` attributes relate to video. The `audio` attribute is a boolean flag. + * @private + */ +var mediaConstraintsToFlashvars = function mediaConstraintsToFlashvars(constraints, flashvars) { + var fv = (0, _object.deepCopy)(flashvars); + if (typeof constraints.video === 'boolean') { + fv.video = constraints.video; + } else { + var key = void 0; + for (key in constraints.video) { + fv[key] = convertDimensionOptions(constraints.video[key]); + } + fv.video = true; + } + fv.audio = typeof constraints.audio === 'boolean' ? constraints.audio : true; + return fv; +}; + +/** + * The internal Publish Source Handler for an RTMPPublisher. + * @private + */ + +var PublisherSourceHandler = function () { + + /** + * @param {Element} video + * The video DOM Element. + * @param {String} type + * The publisher type: most likely, `RTMP`. + * @param {Object} soResponder + * Optional responder to SharedObject API. If not provided, will generate a `RTMPSharedObjectHandler` instance internally. + * @private + */ + function PublisherSourceHandler(video, type) { + var soResponder = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined; + (0, _classCallCheck3.default)(this, PublisherSourceHandler); + + this.video = video; + this.clone = this.video.cloneNode(true); + this.holder = this.video.parentNode; + this._publisherType = type; + this._swfId = null; + this._embedFuture = undefined; + this._soResponder = soResponder || new _sharedobjectHelperRtmp2.default(); + } + + /** + * Requested and used by RTMPPublisher instance in recognizing completion of embed. + * + * @return {Promise} + * @private + */ + + + (0, _createClass3.default)(PublisherSourceHandler, [{ + key: 'getEmbedOperation', + value: function getEmbedOperation() { + this._embedFuture = _promise.Future.createIfNotExist(this._embedFuture); + return this._embedFuture.promise; + } + + /** + * Clean up of references and modified display. + * @private + */ + + }, { + key: 'cleanUp', + value: function cleanUp() { + // Return to prior DOM manipulation. + this.video.remove(); + this.video = this.clone.cloneNode(true); + this.holder.appendChild(this.video); + this._embedFuture = undefined; + } + + /** + * Request to define the embedding options for a RTMPPublisher. + * + * @param {String} swfId + * The unique id to use in embedding element. + * @param {Object} options + * The initialization configuration to determine flashvars from. + * @param {String} swfUrl + * Optional location of the SWF file to embed. Default is relative path to `red5pro-subscriber.swf`. + * @param {String} minFlashVersion + * Optional semver of minimum Flash version to determine support. Default is `10.0.0`. + * @return {Promise} + * The `Promise` either resolves or rejects the success of embed on page using SWFObject. + * @private + */ + + }, { + key: 'addSource', + value: function addSource(swfId, options) { + var swfUrl = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + var minFlashVersion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + + (0, _log.debug)(NAME, '[addsource]'); + var self = this; + this._swfId = swfId; + this._embedFuture = _promise.Future.createIfNotExist(this._embedFuture); + var deferred = this._embedFuture; + options.swf = swfUrl || options.swf; + options.minFlashVersion = minFlashVersion || options.minFlashVersion; + embed.defineEmbedElement(this.video, this.holder).then(function (elementId) { + (0, _log.debug)(NAME, '[element:complete]'); + var flashvars = { + buffer: options.buffer != null ? options.buffer : 1, + streamMode: options.streamMode, + streamName: options.streamName, + appName: options.app, + host: options.host + }; + if (options.backgroundColor) { + flashvars.backgroundColor = options.backgroundColor; + } + if (options.context) { + flashvars.roomName = options.context; + } + if (options.embedWidth === '100%' || options.embedHeight === '100%') { + flashvars.autosize = true; + } + if (typeof options.connectionParams !== 'undefined') { + flashvars.connectionParams = encodeURIComponent((0, _stringify2.default)(options.connectionParams)); + } + flashvars = mediaConstraintsToFlashvars(options.mediaConstraints, flashvars); + return embed.embedSwfObject(swfId, options, flashvars, _browser2.default.getSwfObject(), elementId); + }).then(function () { + (0, _log.debug)(NAME, '[embed:complete]'); + deferred.resolve(self); + }).catch(function (err) { + return deferred.reject(err); + }); + return deferred.promise; + } + + /** + * Request to connect to server for a broadcast session. + * + * @param {Object} publishOptions + * @private + */ + + }, { + key: 'connect', + value: function connect(publishOptions) { + (0, _log.debug)(NAME, '[connect]'); + var el = _browser2.default.getEmbedObject(this._swfId); + if (el) { + el.connect(publishOptions); + this._soResponder.connect(this._swfId); + } else { + (0, _log.warn)(NAME, 'Could not determine embedded element with swf id: ' + this._swfId + '.'); + } + } + + /** + * Request to disconnect from server. + * + * @private + */ + + }, { + key: 'disconnect', + value: function disconnect() { + (0, _log.debug)(NAME, '[disconnect]'); + try { + var el = _browser2.default.getEmbedObject(this._swfId); + if (el) { + el.disconnect(); + } + } catch (e) { + // nada. + } + this.cleanUp(); + this._soResponder.disconnect(); + } + + /** + * Request to send a message to all subscribers. + * + * @param {String} methodName + * The method name associated with the message to be accepted by all subscribers. + * @param {Object} data + * The data object to send associated with the method name. + * @private + */ + + }, { + key: 'send', + value: function send(methodName, data) { + var el = _browser2.default.getEmbedObject(this._swfId); + if (el) { + el.send(methodName, data); + } + } + + /** + * Adds a response handler on SharedObject channel responder. + * @private + */ + + }, { + key: 'addSharedObjectResponseHandler', + value: function addSharedObjectResponseHandler(handler) { + this._soResponder.addResponseHandler(handler); + } + + /** + * Removes a response handler on SharedObject channel responder. + * @private + */ + + }, { + key: 'removeSharedObjectResponseHandler', + value: function removeSharedObjectResponseHandler(handler) { + this._soResponder.removeResponseHandler(handler); + } + + /** + * Sends message on SharedObject channel responder. + * + * @param {String} name + * The SharedObject name. + * @param {String} callName + * The method name to be invoked. + * @param {String} message + * The structured value to send. + * @private + */ + + }, { + key: 'sendToSharedObject', + value: function sendToSharedObject(name, callName, message) { + this._soResponder.sendToSharedObject(name, callName, message); + } + + /** + * Sends property update on SharedObject channel responder. + * + * @param {String} name + * The SharedObject name. + * @param {String} key + * The property name on the SharedObject. + * @param {String} value + * The structured property value. + * @private + */ + + }, { + key: 'sendPropertyToSharedObject', + value: function sendPropertyToSharedObject(name, key, value) { + this._soResponder.sendPropertyToSharedObject(name, key, value); + } + + /** + * Requests to get SharedObject instance from the SharedObject channel responder. + * @private + */ + + }, { + key: 'getRemoteSharedObject', + value: function getRemoteSharedObject(sharedObjectName) { + this._soResponder.getRemoteSharedObject(sharedObjectName); + } + + /** + * Request to connect to a shared object. + * + * @param {String} sharedObjectName + * The name of the SharedObject. + * @private + */ + + }, { + key: 'connectToSharedObject', + value: function connectToSharedObject(sharedObjectName) { + this._soResponder.connectToSharedObject(sharedObjectName); + } + + /** + * Request to close connection to a shared object. + * + * @param {String} sharedObjectName + * The name of the SharedObject. + * @private + */ + + }, { + key: 'closeSharedObject', + value: function closeSharedObject(sharedObjectName) { + this._soResponder.closeSharedObject(sharedObjectName); + } + + /** + * Deprecated. Request to update broadcast dimensions before a broadcast. + * + * @param {Object} quality + * Expects object with following structur: `{video: {width:Int, heightInt}} + * @private + */ + + }, { + key: 'setMediaQuality', + value: function setMediaQuality(quality) { + var el = _browser2.default.getEmbedObject(this._swfId); + if (el) { + if (quality.video && typeof quality.video !== 'boolean') { + var w = !isNaN(quality.video.width) ? (0, _util.toInt)(quality.video.width) : _isNan2.default; + var h = !isNaN(quality.video.height) ? (0, _util.toInt)(quality.video.height) : _isNan2.default; + el.updateResolution(w, h); + } + } + } + + /** + * Returns the type of implementation: `RTMP`. + * + * @return {String} + * @private + */ + + }, { + key: 'getType', + value: function getType() { + return this._publisherType; + } + }]); + return PublisherSourceHandler; +}(); + +exports.default = PublisherSourceHandler; + +/***/ }), +/* 121 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _promise = __webpack_require__(61); + +var _promise2 = _interopRequireDefault(_promise); + +var _extends2 = __webpack_require__(29); + +var _extends3 = _interopRequireDefault(_extends2); + +var _stringify = __webpack_require__(12); + +var _stringify2 = _interopRequireDefault(_stringify); + +var _getPrototypeOf = __webpack_require__(6); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = __webpack_require__(8); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = __webpack_require__(7); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _eventEmitter = __webpack_require__(23); + +var _eventEmitter2 = _interopRequireDefault(_eventEmitter); + +var _webrtc = __webpack_require__(41); + +var webrtc = _interopRequireWildcard(_webrtc); + +var _websocket = __webpack_require__(42); + +var websocket = _interopRequireWildcard(_websocket); + +var _browser = __webpack_require__(4); + +var _browser2 = _interopRequireDefault(_browser); + +var _socketHelperPub = __webpack_require__(114); + +var _socketHelperPub2 = _interopRequireDefault(_socketHelperPub); + +var _webrtcHelperPub = __webpack_require__(116); + +var _webrtcHelperPub2 = _interopRequireDefault(_webrtcHelperPub); + +var _publish = __webpack_require__(59); + +var _publish2 = _interopRequireDefault(_publish); + +var _event = __webpack_require__(15); + +var _publish3 = __webpack_require__(54); + +var _webrtc2 = __webpack_require__(55); + +var _promise3 = __webpack_require__(5); + +var _constraint = __webpack_require__(85); + +var _urlEndpoint = __webpack_require__(58); + +var _log = __webpack_require__(2); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var pubStartRegex = /(.*) starting/i; +var pubStopRegex = /(.*) stopping/i; +var NAME = 'RTCPublisher'; +var debug = function debug(message) { + (0, _log.debug)(NAME, message); +}; +var warn = function warn(message) { + (0, _log.warn)(NAME, message); +}; +var error = function error(message) { + (0, _log.error)(NAME, message); +}; + +// Default to secure settings. +var defaultOptions = { + protocol: 'wss', + port: 8083, + app: 'live', + streamMode: _publish3.PublishModeTypes.LIVE, + mediaElementId: 'red5pro-publisher', + iceServers: [{ urls: 'stun:stun2.l.google.com:19302' }], + iceTransport: _webrtc2.IceTransportTypes.UDP, + bandwidth: { + audio: 56, + video: 512 + }, + mediaConstraints: new _constraint.RTCMediaConstraint(), + onGetUserMedia: undefined + + /** + * Main entry for WebRTC-based Publisher. + * + * @extends EventEmitter + */ +}; +var RTCPublisher = function (_EventEmitter) { + (0, _inherits3.default)(RTCPublisher, _EventEmitter); + + function RTCPublisher() { + (0, _classCallCheck3.default)(this, RTCPublisher); + + var _this = (0, _possibleConstructorReturn3.default)(this, (RTCPublisher.__proto__ || (0, _getPrototypeOf2.default)(RTCPublisher)).call(this)); + + _this._options = undefined; + _this._view = undefined; + _this._peerHelper = undefined; + _this._socketHelper = undefined; + _this._mediaStream = undefined; + + _this._streamFuture = undefined; + _this._availableFuture = undefined; + _this._peerFuture = undefined; + _this._offerFuture = undefined; + _this._sendOfferFuture = undefined; + _this._trickleEndFuture = undefined; + _this._publishFuture = undefined; + _this._unpublishFuture = undefined; + + _this._onOrientationChange = _this._onOrientationChange.bind(_this); + return _this; + } + + (0, _createClass3.default)(RTCPublisher, [{ + key: '_getMediaStream', + value: function _getMediaStream() { + this._streamFuture = _promise3.Future.createIfNotExist(this._streamFuture); + return this._streamFuture.promise; + } + }, { + key: '_getTrickleEnd', + value: function _getTrickleEnd() { + return _promise3.Future.createIfNotExist(this._trickleEndFuture); + } + + /** + * Runs internal `getUserMedia` logic to determine broadcast constraints. + * + * @param {Object} options + * The initialization options provided in `init()`. + * + * @private + */ + + }, { + key: '_gum', + value: function _gum(options) { + var _this2 = this; + + if (options.onGetUserMedia !== undefined) { + debug('Requesting gUM from user-defined configuration:onGetUserMedia.'); + options.onGetUserMedia().then(function (media) { + _this2._streamFuture.resolve(media); + }).catch(function (err) { + error('Could not resolve MediaAsset from provided gUM. Error - ' + err); + _this2._streamFuture.reject(err); + }); + } else { + debug('Requesting gUM using mediaConstraints: ' + (0, _stringify2.default)(options.mediaConstraints, null, 2)); + this._peerHelper.getUserMedia(options.mediaConstraints).then(function (res) { + debug('Found valid constraints: ' + (0, _stringify2.default)(res.constraints, null, 2)); + _this2.trigger(new _event.PublisherEvent(_event.PublisherEventTypes.DIMENSION_CHANGE, _this2, res.constraints)); + _this2._streamFuture.resolve(res.media); + }).catch(function (rej) { + debug('Could not find valid constraint resolutions from: ' + (0, _stringify2.default)(rej.constraints, null, 2)); + error('Could not resolve MediaAsset from provided mediaConstraints. Error - ' + rej.error); + debug('Attempting to find resolutions from original provided constraints: ' + (0, _stringify2.default)(rej.constraints, null, 2)); + // allowing to try original constraint requested. + options.onGetUserMedia = function () { + return _this2._peerHelper.forceUserMedia(rej.constraints); + }; + _this2._gum(options); + }); + } + } + + /** + * Invoked upon `onorientationchange` of the browser. Mobile browsers only. + * + * @param {int} orientation + * The orientation value of the device browser. + * + * @private + */ + + }, { + key: '_onOrientationChange', + value: function _onOrientationChange(orientation) { + if (this._socketHelper) { + this._socketHelper.post({ + send: { + method: 'onMetaData', + data: { + deviceOrientation: orientation + } + } + }); + } + } + + /** + * Invoked upon receipt from `_gum` with MediaStream instance returned from browser. + * + * @param {MediaStream} mediaStream + * The `MediaStream` object. + * + * @private + */ + + }, { + key: '_onMediaStreamReceived', + value: function _onMediaStreamReceived(mediaStream) { + // if (this._socketHelper && !this._socketHelper.isTerminated) { + this._mediaStream = mediaStream; + this.trigger(new _event.PublisherEvent(_event.RTCPublisherEventTypes.MEDIA_STREAM_AVAILABLE, this, mediaStream)); + if (this._view) { + this._view.preview(this._mediaStream); + } + // } + } + + /** + * Still in use, but hold-over of previous 3.x SDK versions designed to pair views and publishers. In 4.0.0 it has been internalized. + * API deprecated. + * + * @private + */ + + }, { + key: '_setViewIfNotExist', + value: function _setViewIfNotExist(currentView) { + var mediaElementId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + + if (typeof currentView === 'undefined' && mediaElementId !== undefined) { + var view = new _publish2.default(mediaElementId); + view.attachPublisher(this); + } + } + + /** + * Request availability based on unique `streamName`. + * The return from the WebSocket request will either invoke `onStreamAvailable` or `onStreamUnavailable`. + * + * @param {String} streamName + * The unique stream name to check if it is _unavailable_ - meaning free to publish against. + * @return {Promise} + * The promise will resolve/reject the `_availableFuture`. + * + * @private + */ + + }, { + key: '_requestAvailability', + value: function _requestAvailability(streamName) { + debug('[requestavailability]'); + this._availableFuture = undefined; + this._availableFuture = _promise3.Future.createIfNotExist(this._availableFuture); + this._socketHelper.post({ + isAvailable: streamName, + bundle: false + }); + return this._availableFuture.promise; + } + + /** + * Request to setup RTCPeerConnection instance for exchange of SDP locally and remotely. + * + * @param {Array} iceServers + * List of ICE servers + * @return {Promise} + * The promise will resolve/reject the `_peerFuture`. + * + * @private + */ + + }, { + key: '_createPeerConnection', + value: function _createPeerConnection(iceServers) { + debug('[createpeeer]'); + this._peerFuture = undefined; + this._peerFuture = _promise3.Future.createIfNotExist(this._peerFuture); + this._peerHelper.setUp(iceServers, this._peerFuture, this._options.rtcpMuxPolicy); + return this._peerFuture.promise; + } + + /** + * Request to generate offer on Peer Connection instance. + * + * @param {Object} bandwidth + * Optional bandwidth configuration object to munge SDP. + * @return {Promise} + * The promise will resolve/reject a success in creation of the offer through the Peer Connection. + * + * @private + */ + + }, { + key: '_createOffer', + value: function _createOffer() { + var bandwidth = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + + debug('[createoffer]'); + this._offerFuture = undefined; + this._offerFuture = _promise3.Future.createIfNotExist(this._offerFuture); + this._peerHelper.createOffer(bandwidth, this._offerFuture); + return this._offerFuture.promise; + } + + /** + * Request to set a remote description on Peer Connection instance. + * + * @param {Object} sdp + * Object describing the Session Description. + * @return {Promise} + * The promise will resolve/reject in a success in setting the remote SDP on the Peer Connection. + * + * @private + */ + + }, { + key: '_setRemoteDescription', + value: function _setRemoteDescription(sdp) { + debug('[setremotedescription]'); + return this._peerHelper.setRemoteDescription(sdp); + } + + /** + * Request to send offer on WebSocket instance. + * + * @param {Object} sdp + * Object describing the Session Description. + * @param {string} streamName + * The unique stream name of the broadcast. + * @return {Promise} + * The promise will resolve/reject on the success of delivering an offer over the WebSocket. + * + * @private + */ + + }, { + key: '_sendOffer', + value: function _sendOffer(sdp, streamName, transport) { + debug('[sendoffer]'); + this._sendOfferFuture = undefined; + this._sendOfferFuture = _promise3.Future.createIfNotExist(this._sendOffFuture); + this._socketHelper.post({ + handleOffer: streamName, + transport: transport, + data: { + sdp: sdp + } + }); + return this._sendOfferFuture.promise; + } + + /** + * Request to send ICE candidate over the WebSocket. + * This can happen several times in the ICE negotiation process. + * + * @param {Object} candidate + * The Candidate to send. + * @param {string} streamName + * The associated unique stream name of the broadcast. + * + * @private + */ + + }, { + key: '_sendCandidate', + value: function _sendCandidate(candidate, streamName) { + debug('[sendcandidate]'); + this._socketHelper.post({ + handleCandidate: streamName, + data: { + candidate: candidate + } + }); + } + + /** + * Request on WebSocket to begin publishing. + * + * @param {string} streamName + * The unique stream name of the broadcast. + * @param {string} mode + * The broadcast mode: `live`, `record` or `append`. + * @return {Promise} + * The promise will resolve/reject in the request to being a broadcast. + * + * @private + */ + + }, { + key: '_requestPublish', + value: function _requestPublish(streamName, streamMode) { + debug('[requestpublish]'); + this._publishFuture = undefined; + this._publishFuture = _promise3.Future.createIfNotExist(this._publishFuture); + this._socketHelper.post({ + publish: streamName, + mode: streamMode + }); + return this._publishFuture.promise; + } + + /** + * Request to stop a current broadcast. + * + * @param {String} streamName + * The unique stream name being broadcast on. + * @return {Promise} + * The promise will resolve/reject on success of properly stopping a broadcast. + * + * @private + */ + + }, { + key: '_requestUnpublish', + value: function _requestUnpublish(streamName) { + this._unpublishFuture = undefined; + this._unpublishFuture = _promise3.Future.createIfNotExist(this._unpublishFuture); + // If we get a false response from trying to send a close POST, + // it means that the socket has already been closed by another impetus - + // most likley loss of network or server failure. + if (!this._socketHelper.post({ + unpublish: streamName + })) { + this._unpublishFuture.resolve(); + } + return this._unpublishFuture.promise; + } + + /** + * Request to initialize the WebRTC-based Publisher based on configuration. + * The returned `Promise` will either resolve with a reference to this instance or reject with an error `String` in failure. + * + * @param {Object} options + * The initialization configuration map. + * @return {Promise} + */ + + }, { + key: 'init', + value: function init(options) { + var deferred = new _promise3.DeferredPromise(); + if (!webrtc.isSupported() || !websocket.isSupported()) { + deferred.reject('Cannot create WebRTC playback instance. Your environment does not support WebRTC and/or WebSockets.'); + } else { + this._options = (0, _extends3.default)({}, defaultOptions, options); + this._peerHelper = new _webrtcHelperPub2.default(this); + this._socketHelper = new _socketHelperPub2.default(this); + this._getMediaStream().then(this._onMediaStreamReceived.bind(this)); + this._gum(this._options); + // auto preview. + this._setViewIfNotExist(this._view, this._options.mediaElementId); + deferred.resolve(this); + } + return deferred.promise; + } + + /** + * Still in use for assigning document element view management to this instance. + * API deprecated in 4.0.0. + * + * @private + */ + + }, { + key: 'setView', + value: function setView(view) { + this._view = view; + if (this._mediaStream && this._view) { + this._view.preview(this._mediaStream); + } + return this; + } + + /** + * Still in use for assigning document element view management to this instance. + * API deprecated in 4.0.0. + * + * @private + */ + + }, { + key: 'preview', + value: function preview() { + var _this3 = this; + + debug('[preview]'); + var p = new _promise2.default(function (res) { + res(_this3); + }); + this._setViewIfNotExist(this._view, this._options.mediaElementId); + return p; + } + + /** + * Request to begin a broadcast session after initilization has occured. + * + * @param {String} streamName + * Optional stream name to broadcast on, otherwise defaulting to the `streamName` provided in `init()` configuration. + * @param {Promise} promise + * Optional `Promise` object to resolve/reject on based on sequence of events in establishing a broadcast, otherwise defaulting to `Promise` created internally and returned. + * @return {Promise} + * The returned `Promise` will resolve or reject on successful start of a broadcast.
    + * There are several processes that occur in order to establish a WebRTC broadcast that involve - but are not limited to - ICE communication and assigning of local and remote SDPs on peer connections. + */ + + }, { + key: 'publish', + value: function publish() { + var _this4 = this; + + var streamName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var promise = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + + debug('[publish]'); + this._options.streamName = streamName || this._options.streamName; + var p = promise || new _promise3.DeferredPromise(); + var socketPromise = new _promise3.DeferredPromise(); + var socketurl = (0, _urlEndpoint.rtcSocketEndpointFromOptions)(this._options, { + id: this._options.streamName + }); + this._trickleEndFuture = this._getTrickleEnd(); + this._socketHelper.clearRetry(); + this._socketHelper.setUp(socketurl, socketPromise); + + // 0. Establish socket connection. + socketPromise.promise + // 1. Wait for stream attach + .then(function () { + _this4.trigger(new _event.PublisherEvent(_event.PublisherEventTypes.CONNECT_SUCCESS, _this4)); + return _this4._getMediaStream(); + }) + // 2. Request available stream to publish on + .then(function () { + return _this4._requestAvailability(_this4._options.streamName, _this4._options.streamType); + }) + // 3. Create Peer Connection + .then(function () { + return _this4._createPeerConnection(_this4._options.iceServers); + }) + // 4. Make Offer on Peer Connection + .then(function (connection) { + connection.addStream(_this4._mediaStream); + _this4.trigger(new _event.PublisherEvent(_event.RTCPublisherEventTypes.PEER_CONNECTION_AVAILABLE, _this4, connection)); + return _this4._createOffer(_this4._options.bandwidth); + }) + // 5. Send Offer + .then(function (sessionDescription) { + _this4.trigger(new _event.PublisherEvent(_event.RTCPublisherEventTypes.OFFER_START, _this4, sessionDescription)); + return _this4._sendOffer(sessionDescription, _this4._options.streamName, _this4._options.iceTransport); + }) + // 6. Set the session description remotely + .then(function (sdp) { + return _this4._setRemoteDescription(sdp.sdp); + }) + // 7. Wait until ice trickle end + .then(function (sdp) { + _this4.trigger(new _event.PublisherEvent(_event.RTCPublisherEventTypes.OFFER_END, _this4, sdp)); + return _this4._getTrickleEnd().promise; + }) + // 8. Request to publish stream + .then(function () { + _this4.trigger(new _event.PublisherEvent(_event.RTCPublisherEventTypes.ICE_TRICKLE_COMPLETE, _this4)); + return _this4._requestPublish(_this4._options.streamName, _this4._options.streamMode); + }) + // 9. Results in socket message of publish (see :onPublishStatus) + .then(function () { + _browser2.default.addOrientationChangeHandler(_this4._onOrientationChange); + p.resolve(_this4); + _this4.trigger(new _event.PublisherEvent(_event.PublisherEventTypes.PUBLISH_START, _this4)); + }).catch(function (error) { + _browser2.default.removeOrientationChangeHandler(_this4._onOrientationChange); + p.reject(error); + _this4.trigger(new _event.PublisherEvent(_event.PublisherEventTypes.CONNECT_FAILURE, _this4, error)); + }); + return p.hasOwnProperty('promise') ? p.promise : p; + } + + /** + * Request to stop a broadcast. + * The returned `Promise` will either resolve or reject on successful stop of broadcast. + * + * @return {Promise} + */ + + }, { + key: 'unpublish', + value: function unpublish() { + var _this5 = this; + + debug(NAME, '[unpublish]'); + var clearHelpers = function clearHelpers() { + if (_this5._socketHelper) { + debug(NAME, '[unpublish:teardown]'); + _this5._socketHelper.tearDown(); + } + if (_this5._peerHelper) { + _this5._peerHelper.tearDown(); + } + }; + this._availableFuture = undefined; + this._peerFuture = undefined; + this._offerFuture = undefined; + this._sendOfferFuture = undefined; + this._trickleEndFuture = undefined; + this._publishFuture = undefined; + var f = this._requestUnpublish(this._options.streamName); + f.then(function () { + _this5._unpublishFuture = undefined; + // this._mediaStream = undefined + clearHelpers(); + _this5.trigger(new _event.PublisherEvent(_event.PublisherEventTypes.UNPUBLISH_SUCCESS, _this5)); + }); + _browser2.default.removeOrientationChangeHandler(this._onOrientationChange); + return f; + } + + /** + * Deprecated. Use `muteAudio`. + * + * @private + */ + + }, { + key: 'mute', + value: function mute() { + // backward comatibility - to be deprecated. + this.muteAudio(); + } + + /** + * Deprecated. Use `unmuteAudio`. + * + * @private + */ + + }, { + key: 'unmute', + value: function unmute() { + // backward comatibility - to be deprecated. + this.unmuteAudio(); + } + + /** + * Request to mute the audio of the broadcast. + * Can only be called once the broadcast has begun. + */ + + }, { + key: 'muteAudio', + value: function muteAudio() { + this._socketHelper.post({ + mute: { + muteAudio: true + } + }); + } + + /** + * Request to unmute the audio of a broadcast that has been previously muted. + */ + + }, { + key: 'unmuteAudio', + value: function unmuteAudio() { + this._socketHelper.post({ + mute: { + muteAudio: false + } + }); + } + + /** Request to mute (not send) the video of the broadcast. + * Can only be called once the broadcast has begun. + */ + + }, { + key: 'muteVideo', + value: function muteVideo() { + this._socketHelper.post({ + mute: { + muteVideo: true + } + }); + } + + /** + * Request to unmute (resume sending) the video of a previously video-muted broadcast. + */ + + }, { + key: 'unmuteVideo', + value: function unmuteVideo() { + this._socketHelper.post({ + mute: { + muteVideo: false + } + }); + } + + /** + * Request to send a message to all subscribers. + * + * @param {String} methodName + * The method name associated with the message to be accepted by all subscribers. + * @param {Object} data + * The data object to send associated with the method name. + */ + + }, { + key: 'send', + value: function send(methodName, data) { + this._socketHelper.post({ + send: { + method: methodName, + data: typeof data === 'string' ? JSON.parse(data) : data + } + }); + } + + /** + * Request to invoke a method on the Application Adapter related to the `app` config setting. + * + * @param {String} methodName + * The name of the method to invoke on thw Application Adapter + * @param {Array} args + * The ordered list of arguments to invoke on the method. Do not provide anything if the method takes no arguments. + * @return {Promise} + */ + + }, { + key: 'callServer', + value: function callServer(methodName, args) { + return this._socketHelper.postAsync({ + callAdapter: { + method: methodName, + arguments: args + } + }); + } + + /** + * Event handler for availability of stream on request over the socket. + * + * @private + */ + + }, { + key: 'onStreamAvailable', + value: function onStreamAvailable(receipt) { + debug('[onstreamavailable]: ' + (0, _stringify2.default)(receipt, null, 2)); + this._availableFuture = _promise3.Future.createIfNotExist(this._availableFuture); + this._availableFuture.reject('Stream with name ' + this._options.streamName + ' already has a broadcast session.'); + this.trigger(new _event.PublisherEvent(_event.PublisherEventTypes.PUBLISH_INVALID_NAME, this)); + } + + /** + * Event handler for unavailability of stream on request over the socket. + * + * @private + */ + + }, { + key: 'onStreamUnavailable', + value: function onStreamUnavailable(receipt) { + // Being unavailable, is a good thing for allowing to publish using `options.streamName` + debug('Stream ' + this._options.streamName + ' does not exist.'); + debug('[onstreamunavailable]: ' + (0, _stringify2.default)(receipt, null, 2)); + this._availableFuture = _promise3.Future.createIfNotExist(this._availableFuture); + this._availableFuture.resolve(true); + } + + /** + * Event handler for WebSocket errors. + * + * @private + */ + + }, { + key: 'onSocketMessageError', + value: function onSocketMessageError(message) { + var detail = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + + error('Error in stream publish: ' + message + '.\n[Optional detail]: ' + detail); + if (this._publishFuture) { + this.trigger(new _event.PublisherEvent(_event.PublisherEventTypes.PUBLISH_FAIL, this)); + this._publishFuture.reject(message); + } + } + + /** + * Event handler for close of WebSocket. + * + * @private + */ + + }, { + key: 'onSocketClose', + value: function onSocketClose(closeEvent) { + debug(NAME, '[onsocketclose]'); + if (this._peerHelper) { + this._peerHelper.tearDown(); + } + this.trigger(new _event.PublisherEvent(_event.PublisherEventTypes.CONNECTION_CLOSED, this, closeEvent)); + } + + /** + * Event handler for close of Peer Connection. + * + * @private + */ + + }, { + key: 'onPeerConnectionClose', + value: function onPeerConnectionClose(event) { + debug(NAME, '[onpeerconnectionclose]'); + if (this._socketHelper) { + debug(NAME, '[onpeerconnectionclose:teardown]'); + this._socketHelper.tearDown(); + } + this.onSocketClose(event); + } + + /** + * Event handler for success of SDP offer over WebSocket. + * + * @private + */ + + }, { + key: 'onSDPSuccess', + value: function onSDPSuccess(receipt) { + var info = receipt ? ': ' + (0, _stringify2.default)(receipt, null, 2) : ''; + debug('[onsdpsuccess]' + info); + } + + /** + * Event handler for error in SDP offer over WebSocket. + * + * @private + */ + + }, { + key: 'onSDPError', + value: function onSDPError(receipt) { + this.trigger(new _event.PublisherEvent(_event.PublisherEventTypes.PUBLISH_FAIL, this)); + var error = receipt ? ': ' + (0, _stringify2.default)(receipt, null, 2) : ''; + error('[onsdperror]' + error); + } + + /** + * Event handler for success in SDP answer over WebSocket. + * + * @private + */ + + }, { + key: 'onSDPAnswer', + value: function onSDPAnswer(sdp) { + debug('[sdpanswer]:: ' + (0, _stringify2.default)(sdp, null, 2)); + this._sendOfferFuture = _promise3.Future.createIfNotExist(this._sendOfferFuture); + this._sendOfferFuture.resolve(sdp); + } + + /** + * Event handler for request to add ICE candidate on Peer Connection instance. + * + * @private + */ + + }, { + key: 'onAddIceCandidate', + value: function onAddIceCandidate(candidate) { + debug('[addicecandidate]'); + this._peerHelper.addIceCandidate(candidate).then(function () { + debug('[addicecandidate:success]'); + }).catch(function (err) { + warn('[addicecandidate:error] - ' + err); + }); + } + + /** + * Event handler for receipt and request to send ICE candidate. + * + * @private + */ + + }, { + key: 'onIceCandidate', + value: function onIceCandidate(candidate) { + debug('[icecandidatetrickle]'); + this._sendCandidate(candidate, this._options.streamName); + } + + /** + * Event handler for end of ICE trickle negotiation. + * + * @private + */ + + }, { + key: 'onIceCandidateTrickleEnd', + value: function onIceCandidateTrickleEnd() { + debug('[icecandidatetrickle:end]'); + } + + /** + * Event handler for receipt of empty candidate during ICE negotiation. + * + * @private + */ + + }, { + key: 'onEmptyCandidate', + value: function onEmptyCandidate() { + debug('[icecandidatetrickle:empty]'); + this.trigger(new _event.PublisherEvent(_event.RTCPublisherEventTypes.PEER_CANDIDATE_END)); + } + + /** + * Event handler for completion of peer ice candidate gathering. + * + * @private + */ + + }, { + key: 'onPeerGatheringComplete', + value: function onPeerGatheringComplete() { + debug('[icecandidategathering:end]'); + if (this._socketHelper) { + this._socketHelper.postEndOfCandidates(this._options.streamName); + } + } + + /** + * Event handler for end of ICE candidate notification over WebSocket. + * + * @private + */ + + }, { + key: 'onSocketIceCandidateEnd', + value: function onSocketIceCandidateEnd() { + debug('[socketicecandidate:end]'); + this._getTrickleEnd().resolve(); + // this._trickleEndFuture = undefined + } + + /** + * Publisher status event handler for start and stop of this Publisher instance. + * + * @private + */ + + }, { + key: 'onPublisherStatus', + value: function onPublisherStatus(status) { + debug('[publisherstatus] - ' + (0, _stringify2.default)(status, null, 2)); + var stopResult = pubStopRegex.exec(status.message); + var startResult = pubStartRegex.exec(status.message); + if (stopResult && stopResult[1] === this._options.streamName) { + this._unpublishFuture.resolve(); + } else if (startResult && startResult[1] === this._options.streamName) { + this._publishFuture.resolve(); + } else { + warn('Publisher status received, but could not handle.'); + } + } + + /** + * Helper method to overlay options over current configuration. + * + * @private + */ + + }, { + key: 'overlayOptions', + value: function overlayOptions(newOptions) { + this._options = (0, _extends3.default)(this._options, newOptions); + } + + /** + * Returns the current WebSocket connection helper if established. + * Used in SharedObject communication. + * + * @return {PublisherSocketHelper} + * + * @private + */ + + }, { + key: 'getConnection', + value: function getConnection() { + return this._socketHelper; + } + + /** + * Returns the current RTCPeerConnection helper if established. + * + * @return {RTCPeerConnection} + */ + + }, { + key: 'getPeerConnection', + value: function getPeerConnection() { + return this._peerHelper ? this._peerHelper.connection : undefined; + } + + /** + * Returns the `MediaStream` instance if generated through `getUserMedia` and exists for broadcast. + * + * @return {MediaStream} + */ + + }, { + key: 'getMediaStream', + value: function getMediaStream() { + return this._mediaStream; + } + + /** + * Returns the initialization configuration used in `init()`. + * + * @return {Object} + */ + + }, { + key: 'getOptions', + value: function getOptions() { + return this._options; + } + + /** + * Returns the type of implementation: `RTC`. + * + * @return {String} + */ + + }, { + key: 'getType', + value: function getType() { + return _publish3.PublishTypes.RTC.toUpperCase(); + } + }]); + return RTCPublisher; +}(_eventEmitter2.default); + +exports.default = RTCPublisher; + +/***/ }), +/* 122 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _stringify = __webpack_require__(12); + +var _stringify2 = _interopRequireDefault(_stringify); + +var _extends2 = __webpack_require__(29); + +var _extends3 = _interopRequireDefault(_extends2); + +var _getPrototypeOf = __webpack_require__(6); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = __webpack_require__(8); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = __webpack_require__(7); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _eventEmitter = __webpack_require__(23); + +var _eventEmitter2 = _interopRequireDefault(_eventEmitter); + +var _browser = __webpack_require__(4); + +var _browser2 = _interopRequireDefault(_browser); + +var _pubSourceHandler = __webpack_require__(120); + +var _pubSourceHandler2 = _interopRequireDefault(_pubSourceHandler); + +var _publish = __webpack_require__(59); + +var _publish2 = _interopRequireDefault(_publish); + +var _event = __webpack_require__(15); + +var _promise = __webpack_require__(5); + +var _publish3 = __webpack_require__(54); + +var _constraint = __webpack_require__(85); + +var _log = __webpack_require__(2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var NAME = 'RTMPPublisher'; +var defaultOptions = { + protocol: 'rtmp', + port: 1935, + streamMode: 'live', + mediaElementId: 'red5pro-publisher', + embedWidth: '100%', // DOM display style + embedHeight: '100%', // DOM display style + minFlashVersion: '10.0.0', + swf: 'lib/red5pro/red5pro-publisher.swf', + swfobjectURL: 'lib/swfobject/swfobject.js', + productInstallURL: 'lib/swfobject/playerProductInstall.swf', + mediaConstraints: new _constraint.RTMPMediaConstraint() + + /** + * Main entry for Flash-based Publisher. + * + * @extends EventEmitter + */ +}; +var RTMPPublisher = function (_EventEmitter) { + (0, _inherits3.default)(RTMPPublisher, _EventEmitter); + + function RTMPPublisher() { + (0, _classCallCheck3.default)(this, RTMPPublisher); + + var _this = (0, _possibleConstructorReturn3.default)(this, (RTMPPublisher.__proto__ || (0, _getPrototypeOf2.default)(RTMPPublisher)).call(this)); + + _this._options = undefined; + _this._view = undefined; + _this._sourceHandler = undefined; + _this._elementId = undefined; + _this._connectFuture = undefined; + return _this; + } + + /** + * Still in use for assigning document element view management to this instance. + * + * @private + */ + + + (0, _createClass3.default)(RTMPPublisher, [{ + key: '_setViewIfNotExist', + value: function _setViewIfNotExist(currentView) { + var mediaElementId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + + if (typeof currentView === 'undefined' && mediaElementId !== undefined) { + var view = new _publish2.default(mediaElementId); + view.attachPublisher(this); + } + } + + /** + * Still in use for assigning document element view management to this instance. + * API deprecated in 4.0.0. + * + * @private + */ + + }, { + key: 'setView', + value: function setView(view, elementId) { + var _this2 = this; + + this._view = view; + this._elementId = elementId; + if (this._sourceHandler !== undefined) { + this._sourceHandler.disconnect(); + this._sourceHandler = undefined; + } + if (this._view) { + this._sourceHandler = new _pubSourceHandler2.default(this._view.view, this.getType()); + } + if (this._options && this._sourceHandler) { + this._sourceHandler.addSource(this._elementId, this._options).catch(function (err) { + (0, _log.error)(NAME, 'Could not establish proper RTMP publisher: ' + err); + _this2.trigger(new _event.PublisherEvent(_event.RTMPPublisherEventTypes.EMBED_FAILURE, _this2)); + }); + } + return this; + } + + /** + * Define a window global callback used by Flash publisher to recognize embed complete. + * + * @private + */ + + }, { + key: '_setUpConnectCallback', + value: function _setUpConnectCallback(promise) { + var _this3 = this; + + window.setActiveId = function (successId) { + // successId === _options.streamName + (0, _log.debug)(NAME, 'Embed and connect() complete for publisher swf. successId(' + successId + ').'); + promise.resolve(_this3); + _this3.trigger(new _event.PublisherEvent(_event.RTMPPublisherEventTypes.EMBED_SUCCESS, _this3)); + _this3._tearDownConnectCallback(); + }; + // TODO: Setup timeout to reject? + } + + /** + * Tear down global callback used in Flash publisher recognize of embed. + * + * @private + */ + + }, { + key: '_tearDownConnectCallback', + value: function _tearDownConnectCallback() { + window.setActiveId = undefined; + } + + /** + * Define global function handlers for ExternalInterface to invoke for API communication. + * + * @private + */ + + }, { + key: '_establishExtIntHandlers', + value: function _establishExtIntHandlers() { + var _this4 = this; + + var id = this._options.streamName; + var invokeFn = function invokeFn(label) { + return ['publisher', label, id.split('-').join('_')].join('_'); + }; + window[invokeFn('r5proConnectClosed')] = function () { + _this4.trigger(new _event.PublisherEvent(_event.PublisherEventTypes.CONNECTION_CLOSED, _this4)); + }; + window[invokeFn('r5proConnectSuccess')] = function () { + return _this4.trigger(new _event.PublisherEvent(_event.PublisherEventTypes.CONNECT_SUCCESS, _this4)); + }; + window[invokeFn('r5proUnpublishSuccess')] = function () { + return _this4.trigger(new _event.PublisherEvent(_event.PublisherEventTypes.UNPUBLISH_SUCCESS, _this4)); + }; + window[invokeFn('r5proPublishStart')] = function () { + _this4._connectFuture.resolve(_this4); + _this4.trigger(new _event.PublisherEvent(_event.PublisherEventTypes.PUBLISH_START, _this4)); + }; + window[invokeFn('r5proPublishMetadata')] = function (metadata) { + return _this4.trigger(new _event.PublisherEvent(_event.PublisherEventTypes.PUBLISH_METADATA, _this4, metadata)); + }; + window[invokeFn('r5proConnectFailure')] = function () { + _this4._connectFuture.reject(_event.PublisherEventTypes.CONNECT_FAILURE); + _this4.trigger(new _event.PublisherEvent(_event.PublisherEventTypes.CONNECT_FAILURE, _this4)); + }; + window[invokeFn('r5proPublishFail')] = function () { + _this4._connectFuture.reject(_event.PublisherEventTypes.PUBLISH_FAIL); + _this4.trigger(new _event.PublisherEvent(_event.PublisherEventTypes.PUBLISH_FAIL, _this4)); + }; + window[invokeFn('r5proPublishInvalidName')] = function () { + _this4._connectFuture.reject(_event.PublisherEventTypes.PUBLISH_INVALID_NAME); + _this4.trigger(new _event.PublisherEvent(_event.PublisherEventTypes.PUBLISH_INVALID_NAME, _this4)); + }; + } + + /** + * Request to initialize the Flash-based Publisher based on configuration. + * The returned `Promise` will either resolve with a reference to this instance or reject with an error `String` in failure. + * + * @param {Object} options + * The initialization configuration map. + * @return {Promise} + */ + + }, { + key: 'init', + value: function init(options) { + var self = this; + var deferred = new _promise.DeferredPromise(); + var version = options.minFlashVersion || defaultOptions.minFlashVersion; + if (!_browser2.default.supportsFlashVersion(version)) { + deferred.reject('Could not resolve RTMPPublisher instance. Requires minimum Flash Player install of ' + version); + } else { + this._options = (0, _extends3.default)({}, defaultOptions, options); + try { + _browser2.default.injectScript(this._options.swfobjectURL).then(function () { + (0, _log.debug)(NAME, 'SWFObject embedded.'); + if (self._sourceHandler) { + (0, _log.debug)(NAME, 'Publish handler established.'); + return self._sourceHandler.addSource(self._elementId, self._options); + } else { + (0, _log.debug)(NAME, 'Publish handler not established.'); + return true; + } + }).then(function () { + self._setViewIfNotExist(self._view, self._options.mediaElementId); + deferred.resolve(self); + }).catch(function (err) { + (0, _log.error)(NAME, 'Could not embed Flash-based RTMP Publisher. Reason: ' + err); + if (self._sourceHandler) { + self._sourceHandler.disconnect(); + } + deferred.reject(err); + self.trigger(new _event.PublisherEvent(_event.RTMPPublisherEventTypes.EMBED_FAILURE, self)); + }); + } catch (e) { + deferred.reject('Could not inject Flash-based Publisher into the page. Reason: ' + e.message); + self.trigger(new _event.PublisherEvent(_event.RTMPPublisherEventTypes.EMBED_FAILURE, self)); + } + } + return deferred.promise; + } + + /** + * Request to being a broadcast session after initilization has occured. + * + * @param {String} streamName + * Optional stream name to broadcast on, otherwise defaulting to the `streamName` provided in `init()` configuration. + * @param {Promise} promise + * Optional `Promise` object to resolve/reject on based on sequence of events in establishing a broadcast, otherwise defaulting to `Promise` created internally and returned. + * @return {Promise} + * The returned `Promise` will resolve or reject on successful start of a broadcast.
    + * There are several processes that occur in order to establish a Flash-based broadcast that involve - but are not limited to - proper embed of Flash object on page with flashvars used in establishing RTMP-based NetConnection. + */ + + }, { + key: 'publish', + value: function publish() { + var _this5 = this; + + var streamName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined; + var promise = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + // eslint-disable-line no-unused-vars + var dfd = promise || new _promise.DeferredPromise(); + this._setUpConnectCallback(dfd); + this._options.streamName = streamName || this._options.streamName; + var publishOptions = this._options; + try { + var srcHandler = this._sourceHandler; + this._sourceHandler.getEmbedOperation().then(function () { + (0, _log.debug)(NAME, '[handler:embed:complete]'); + var el = _browser2.default.getEmbedObject(_this5._elementId); + if (el) { + _this5._establishExtIntHandlers(); + } + var count = 0; + var limit = 100; + var tryConnect = function tryConnect() { + var timeout = void 0; + timeout = setTimeout(function () { + try { + clearTimeout(timeout); + srcHandler.connect((0, _stringify2.default)(publishOptions)); + } catch (e) { + if (count++ > limit) { + throw e; + } else { + tryConnect(); + } + } + }, 300); + }; + tryConnect(); + }).catch(function (err) { + dfd.reject(err); + _this5.trigger(new _event.PublisherEvent(_event.PublisherEventTypes.CONNECT_FAILURE, _this5)); + }); + } catch (e) { + (0, _log.error)(NAME, '[handler:embed:error]'); + dfd.reject('Could not initiate connection sequence. Reason: ' + e.message); + this.trigger(new _event.PublisherEvent(_event.PublisherEventTypes.CONNECT_FAILURE, this)); + this._tearDownConnectCallback(); + } + this._connectFuture = dfd; + return dfd.promise; + } + + /** + * Request to stop a broadcast. + * The returned `Promise` will either resolve or reject on successful stop of broadcast. + * + * @return {Promise} + */ + + }, { + key: 'unpublish', + value: function unpublish() { + var deferred = new _promise.DeferredPromise(); + try { + _browser2.default.getEmbedObject(this._elementId).unpublish(); + deferred.resolve(); + } catch (e) { + (0, _log.error)(NAME, 'Could not initiate publish sequence. Reason: ' + e.message); + deferred.reject(e.message); + } + this._connectFuture = undefined; + return deferred.promise; + } + + /** + * Request to send a message to all subscribers. + * + * @param {String} methodName + * The method name associated with the message to be accepted by all subscribers. + * @param {Object} data + * The data object to send associated with the method name. + */ + + }, { + key: 'send', + value: function send(methodName, data) { + this._sourceHandler.send(methodName, typeof data === 'string' ? data : (0, _stringify2.default)(data)); + } + + /** + * Deprecated. Request to update broadcast dimensions before a broadcast. + * + * @param {Object} quality + * Expects object with following structur: `{video: {width:Int, heightInt}} + * + * @private + */ + + }, { + key: 'setMediaQuality', + value: function setMediaQuality(quality) { + if (this._sourceHandler) { + this._sourceHandler.setMediaQuality(quality); + } + } + + /** + * Helper method to overlay options over current configuration. + * + * @param {Object} newOptions + * The options to overlay. + * + * @private + */ + + }, { + key: 'overlayOptions', + value: function overlayOptions(newOptions) { + this._options = (0, _extends3.default)(this._options, newOptions); + } + + /** + * Returns the current Flash/RTMP connection helper if established. + * Used in SharedObject communication. + * + * @return {PublisherSourceHandler} + * + * @private + */ + + }, { + key: 'getConnection', + value: function getConnection() { + return this._sourceHandler; + } + + /** + * Returns the initialization configuration used in `init()`. + * + * @return {Object} + */ + + }, { + key: 'getOptions', + value: function getOptions() { + return this._options; + } + + /** + * Returns the type of implementation: `RTMP`. + * + * @return {String} + */ + + }, { + key: 'getType', + value: function getType() { + return _publish3.PublishTypes.RTMP.toUpperCase(); + } + }]); + return RTMPPublisher; +}(_eventEmitter2.default); + +exports.default = RTMPPublisher; + +/***/ }), +/* 123 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Red5ProSharedObject = undefined; + +var _stringify = __webpack_require__(12); + +var _stringify2 = _interopRequireDefault(_stringify); + +var _keys = __webpack_require__(60); + +var _keys2 = _interopRequireDefault(_keys); + +var _getPrototypeOf = __webpack_require__(6); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _possibleConstructorReturn2 = __webpack_require__(8); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = __webpack_require__(7); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _eventEmitter = __webpack_require__(23); + +var _eventEmitter2 = _interopRequireDefault(_eventEmitter); + +var _browser = __webpack_require__(4); + +var _browser2 = _interopRequireDefault(_browser); + +var _index = __webpack_require__(15); + +var _sharedobjectEvent = __webpack_require__(56); + +var _log = __webpack_require__(2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var NAME = 'Red5ProSharedObject'; +var SO_SUBTYPE_PROPERTY = 4; +var SO_SUBTYPE_METHOD = 6; + +var debug = function debug(soName, message) { + (0, _log.debug)([NAME, soName].join(':'), message); +}; +var warn = function warn(soName, message) { + (0, _log.warn)([NAME, soName].join(':'), message); +}; +var error = function error(soName, message) { + (0, _log.error)([NAME, soName].join(':'), message); +}; + +var decodeMessageIfJSONString = function decodeMessageIfJSONString(message) { + return typeof message === 'string' ? JSON.parse(message) : message; +}; + +/** + * Defines the structure of a Property Data notification object. + * + * @private + */ + +var PropertyData = function () { + function PropertyData(key, value) { + (0, _classCallCheck3.default)(this, PropertyData); + + this.key = key; + this.value = value; + } + + (0, _createClass3.default)(PropertyData, [{ + key: 'toObject', + value: function toObject() { + var obj = {}; + obj[this.key] = this.value; + return obj; + } + }]); + return PropertyData; +}(); + +/** + * Defines the structure of a Method Data notification object. + * + * @private + */ + + +var MethodData = function () { + function MethodData(methodName, message) { + (0, _classCallCheck3.default)(this, MethodData); + + this.methodName = methodName; + var messageList = void 0; + if (Object.prototype.toString.call(message) === '[object Array]') { + var i = void 0; + var msg = void 0; + var length = message.length; + messageList = []; + for (i = 0; i < length; i++) { + msg = decodeMessageIfJSONString(message[i]); + if (Object.prototype.toString.call(message) === '[object Array]') { + messageList = messageList.concat(msg); + } else { + messageList.push(msg); + } + } + } else { + messageList = [decodeMessageIfJSONString(message)]; + } + this.message = messageList.length === 1 ? messageList[0] : messageList; + } + + (0, _createClass3.default)(MethodData, [{ + key: 'toObject', + value: function toObject() { + return { + methodName: this.methodName, + message: this.message + }; + } + }]); + return MethodData; +}(); + +/** + * Main entry for Shared Object associated with Publishers and Subscribers. + * + * @extends EventEmitter + */ + + +var Red5ProSharedObject = function (_EventEmitter) { + (0, _inherits3.default)(Red5ProSharedObject, _EventEmitter); + + /** + * The API on this object is limited as it communicates along with message channel connection of a previously established Publisher or Subscriber, of which you provide in the constuctor. + * + * Event handlers should be assigned to new `Red5ProSharedObject` instances in order to handle notifications over the communication channel. + * + * @param {String} name + * The name of the Shared Object to connect to. + * @param {Object} connection + * The connection delegate to send and receive Shared Object notifications on. + * This will either be a previously established Publisher or Subscriber instance. + */ + function Red5ProSharedObject(name, connection) { + (0, _classCallCheck3.default)(this, Red5ProSharedObject); + + var _this = (0, _possibleConstructorReturn3.default)(this, (Red5ProSharedObject.__proto__ || (0, _getPrototypeOf2.default)(Red5ProSharedObject)).call(this)); + + _this._name = name; + _this._socket = connection.getConnection(); + _this._socket.addSharedObjectResponseHandler(_this); + _this._onclose = _this.close.bind(_this); + try { + debug(_this._name, '[sharedobject:connect:attempt]'); + // Immediately invoke request on shared object through the `getConnection()` + // instance of a Publisher or Subscriber (whomever invoked this constructor). + _this._socket.getRemoteSharedObject(_this._name); + _browser2.default.addCloseHandler(_this._onclose, 0); + } catch (e) { + error(_this._name, '[sharedobject:connect:error]: ' + e.message); + } + return _this; + } + + /** + * Attempt to parse message into a Object. + * + * @param {Object} message + * Either a JSON string or object. + * + * @private + */ + + + (0, _createClass3.default)(Red5ProSharedObject, [{ + key: '_getJsonFromSocketMessage', + value: function _getJsonFromSocketMessage(message) { + try { + return typeof message.data === 'string' ? JSON.parse(message.data) : message.data; + } catch (e) { + warn(this._name, 'Could not parse message as JSON. Message= ' + message.data + '. Error= ' + e.message); + } + return null; + } + + /** + * Dispatch of PROPERTY_UPDATE with information. + * + * @param {Object} valueObject + * Optional value object to send in notification. + * + * @private + */ + + }, { + key: '_notifyOfPropertyValues', + value: function _notifyOfPropertyValues(valueObject) { + if ((0, _keys2.default)(valueObject).length === 0) { + this.trigger(new _index.SharedObjectEvent(_sharedobjectEvent.SharedObjectEventTypes.PROPERTY_UPDATE, this._name, {})); + } else { + var key = void 0; + for (key in valueObject) { + this.trigger(new _index.SharedObjectEvent(_sharedobjectEvent.SharedObjectEventTypes.PROPERTY_UPDATE, this._name, new PropertyData(key, valueObject[key]).toObject())); + } + } + } + + /** + * Dispatch of PROPERTY_UPDATE or METHOD_UPDATE based on event(s). + * + * @param {Array} events + * A list of events to iterate through and dispatch notifications from. + * + * @private + */ + + }, { + key: '_notifyOfEvents', + value: function _notifyOfEvents(events) { + var i = void 0, + event = void 0; + var handled = false; + var length = events.length; + for (i = 0; i < length; i++) { + event = events[i]; + switch (event.subtype) { + case SO_SUBTYPE_PROPERTY: + this.trigger(new _index.SharedObjectEvent(_sharedobjectEvent.SharedObjectEventTypes.PROPERTY_UPDATE, this._name, new PropertyData(event.attribute, event.value).toObject())); + handled = true; + break; + case SO_SUBTYPE_METHOD: + this.trigger(new _index.SharedObjectEvent(_sharedobjectEvent.SharedObjectEventTypes.METHOD_UPDATE, this._name, new MethodData(event.method, event.value).toObject())); + handled = true; + break; + } + } + return handled; + } + + /** + * Invoked by connection channel to handle message and dispatch appropriate notifications. + * + * @private + */ + + }, { + key: 'respond', + value: function respond(message) { + if (message.data) { + var json = this._getJsonFromSocketMessage(message); + if (json === null) { + warn(this._name, 'Determined websocket response not in correct format. Aborting message handle.'); + return true; + } + if (json.data !== undefined) { + if (json.data.name === this._name) { + debug(this._name, '[sharedobject-response]: ' + (0, _stringify2.default)(json, null, 2)); + if (json.data.status === 'SharedObject.Status.GetRemote' && json.data.message === 'Success') { + this._socket.connectToSharedObject(this._name); + return true; + } else if (json.data.status === 'SharedObject.Status.GetRemote' && json.data.message === 'Fail') { + this.trigger(new _index.SharedObjectEvent(_sharedobjectEvent.SharedObjectEventTypes.CONNECT_FAILURE, this._name)); + return true; + } else if (json.data.status === 'SharedObject.Status.Connect' && json.data.message === 'Success') { + this.trigger(new _index.SharedObjectEvent(_sharedobjectEvent.SharedObjectEventTypes.CONNECT_SUCCESS, this._name)); + return true; + } else if (json.data.status === 'SharedObject.Status.Connect' && json.data.message === 'Fail') { + this.trigger(new _index.SharedObjectEvent(_sharedobjectEvent.SharedObjectEventTypes.CONNECT_FAILURE, this._name)); + return true; + } else if (json.data.type === 'sharedobject') { + if (json.data.hasOwnProperty('events')) { + return this._notifyOfEvents(json.data.events); + } else if (json.data.hasOwnProperty('value')) { + return this._notifyOfPropertyValues(json.data.value); + } + } + } else { + debug('Unhandled Socket exchange: ' + (0, _stringify2.default)(json, null, 2)); + } + } + } + return false; + } + }, { + key: 'send', + value: function send(messageName, data) { + this._socket.sendToSharedObject(this._name, messageName, data); + } + }, { + key: 'setProperty', + value: function setProperty(key, value) { + this._socket.sendPropertyToSharedObject(this._name, key, value); + } + }, { + key: 'close', + value: function close() { + if (this._socket === undefined) { + warn('Socket no longer exist to close shared object properly.'); + } + this._socket.closeSharedObject(this._name); + if (this._socket) { + this._socket.removeSharedObjectResponseHandler(this); + } + this._socket = undefined; + this._name = undefined; + _browser2.default.removeCloseHandler(this._onclose); + } + }, { + key: 'getName', + value: function getName() { + return this._name; + } + }]); + return Red5ProSharedObject; +}(_eventEmitter2.default); + +exports.Red5ProSharedObject = Red5ProSharedObject; + +/***/ }), +/* 124 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = __webpack_require__(6); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = __webpack_require__(8); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = __webpack_require__(7); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _eventEmitter = __webpack_require__(23); + +var _eventEmitter2 = _interopRequireDefault(_eventEmitter); + +var _browser = __webpack_require__(4); + +var _browser2 = _interopRequireDefault(_browser); + +var _event = __webpack_require__(86); + +var _log = __webpack_require__(2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var NAME = 'ControlSlider'; + +/** + * Custom slider control for Playback Controls. + * + * @private + */ + +var ControlSlider = function (_EventEmitter) { + (0, _inherits3.default)(ControlSlider, _EventEmitter); + + function ControlSlider(type) { + (0, _classCallCheck3.default)(this, ControlSlider); + + var _this = (0, _possibleConstructorReturn3.default)(this, (ControlSlider.__proto__ || (0, _getPrototypeOf2.default)(ControlSlider)).call(this)); + + NAME = [NAME, type].join('::'); + (0, _log.debug)(NAME, '[init]'); + _this._container = _browser2.default.createElement('div'); + _this._button = _this.createButton(); + _this._track = _this.createTrack(); + _this._progressBar = _this.createProgressBar(); + _this._container.appendChild(_this._track); + _this._container.appendChild(_this._progressBar); + _this._container.appendChild(_this._button); + _this._value = 0; // 0 - 1 + _this._disabled = false; + _this._eventStartPosition = 0; + _this._layout(); + _this._mouseupHandler = _this._mouseup.bind(_this); + _this._mousedownHandler = _this._mousedown.bind(_this); + _this._mousemoveHandler = _this._mousemove.bind(_this); + _this._touchupHandler = _this._touchproxy.bind(_this); + _this._touchdownHandler = _this._touchproxy.bind(_this); + _this._touchmoveHandler = _this._touchproxy.bind(_this); + _this._updateHandlers(_this._disabled); + return _this; + } + + /** + * Touch event proxy to bubble out mouse events for handling interaction. + * + * @private + */ + + + (0, _createClass3.default)(ControlSlider, [{ + key: '_touchproxy', + value: function _touchproxy(event) { + event.preventDefault(); + if (event.touches.length > 1 || event.type == "touchend" && event.touches.length > 0) { + return; + } + var evt = _browser2.default.createEvent('MouseEvent'); + var type = void 0, + touch = void 0; + var t = event.originalTarget || event.target; + switch (event.type) { + case 'touchstart': + type = 'mousedown'; + touch = event.changedTouches[0]; + break; + case 'touchmove': + type = 'mousemove'; + touch = event.changedTouches[0]; + break; + case 'touchend': + type = 'mouseup'; + touch = event.changedTouches[0]; + break; + } + + evt.initMouseEvent(type, true, true, t.ownerDocument.defaultView, 0, touch.screenX, touch.screenY, touch.clientX, touch.clientY, event.ctrlKey, event.altKey, event.shiftKey, event.metaKey, 0, null); + t.dispatchEvent(evt); + } + + /** + * Event handler for mouse up. + * + * @private + */ + + }, { + key: '_mouseup', + value: function _mouseup() { + this._eventStartPosition = 0; + document.removeEventListener('mousemove', this._mousemoveHandler); + document.removeEventListener('mouseup', this._mouseupHandler); + document.removeEventListener('touchmove', this._touchmoveHandler); + document.removeEventListener('touchup', this._touchupHandler); + this.trigger(new _event.SliderEvent(_event.SliderEventTypes.CHANGE_COMPLETE, this)); + } + + /** + * Event handler for mouse move. + * + * @private + */ + + }, { + key: '_mousemove', + value: function _mousemove(event) { + var positionOffset = _browser2.default.getMouseXFromEvent(event) - this._eventStartPosition; + var rect = this._button.parentNode.getBoundingClientRect(); + var position = this._eventStartPosition + positionOffset - rect.left; // - environment.getScrollX() + position = Math.max(0, position); + position = Math.min(position, rect.width); + var percentage = position / rect.width; + this.trigger(new _event.SliderEvent(_event.SliderEventTypes.CHANGE, this, percentage)); + } + + /** + * Event handler for mouse down. + * + * @private + */ + + }, { + key: '_mousedown', + value: function _mousedown(event) { + this._eventStartPosition = _browser2.default.getMouseXFromEvent(event); + this.trigger(new _event.SliderEvent(_event.SliderEventTypes.CHANGE_START, this)); + document.addEventListener('mousemove', this._mousemoveHandler); + document.addEventListener('mouseup', this._mouseupHandler); + document.addEventListener('touchmove', this._touchmoveHandler); + document.addEventListener('touchup', this._touchupHandler); + } + + /** + * Adds or removes control hanlders based on flag of overall control being disabled. + * + * @param {Boolean} isDisabled + * + * @private + */ + + }, { + key: '_updateHandlers', + value: function _updateHandlers(isDisabled) { + this._eventStartPosition = 0; + if (isDisabled) { + this._track.removeEventListener('click', this._mousemoveHandler); + this._progressBar.removeEventListener('click', this._mousemoveHandler); + this._button.removeEventListener('mousedown', this._mousedownHandler); + document.removeEventListener('mousemove', this._mousemoveHandler); + document.removeEventListener('mouseup', this._mouseupHandler); + document.removeEventListener('touchmove', this._touchmoveHandler); + document.removeEventListener('touchup', this._touchupHandler); + this._track.classList.add('red5pro-media-slider-disabled'); + this._progressBar.classList.add('red5pro-media-slider-disabled'); + this._button.classList.add('red5pro-media-slider-disabled'); + } else { + this._track.addEventListener('click', this._mousemoveHandler); + this._progressBar.addEventListener('click', this._mousemoveHandler); + this._button.addEventListener('mousedown', this._mousedownHandler); + this._button.addEventListener('touchstart', this._touchdownHandler); + this._track.classList.remove('red5pro-media-slider-disabled'); + this._progressBar.classList.remove('red5pro-media-slider-disabled'); + this._button.classList.remove('red5pro-media-slider-disabled'); + } + } + + /** + * Re-layout sub controls. + * + * @private + */ + + }, { + key: '_layout', + value: function _layout() { + var position = this._progressBar.parentNode.clientWidth * this._value; + this._progressBar.style.width = position + 'px'; + this._button.style.left = position - this._button.clientWidth * 0.5 + 'px'; + } + + /** + * Creates the button element. + * + * @private + */ + + }, { + key: 'createButton', + value: function createButton() { + var span = _browser2.default.createElement('span'); + span.classList.add('red5pro-media-slider-button'); + return span; + } + + /** + * Creates the progress bar element. + * + * @private + */ + + }, { + key: 'createProgressBar', + value: function createProgressBar() { + var span = _browser2.default.createElement('span'); + span.classList.add('red5pro-media-slider-progress'); + return span; + } + + /** + * Creates the track element. + * + * @private + */ + + }, { + key: 'createTrack', + value: function createTrack() { + var span = _browser2.default.createElement('span'); + span.classList.add('red5pro-media-slider-track'); + return span; + } + + /** + * Returns the current value. + * + * @return {Number} + */ + + }, { + key: 'value', + get: function get() { + return this._value; + } + + /** + * Sets the current value. + * + * @param {Number} 0..1 + */ + , + set: function set(percentValue /* 0 - 1 */) { + this._value = percentValue; + this._layout(); + } + + /** + * Returns disabled flag. + * + * @return {Boolean} + */ + + }, { + key: 'disabled', + get: function get() { + return this._disabled; + } + + /** + * Sets the disabled flag. + * + * @param {Boolean} bool + */ + , + set: function set(bool) { + this._disabled = bool; + this._updateHandlers(bool); + } + + /** + * Returns the target container this control is assigned to in the DOM. + * + * @return {Element} + */ + + }, { + key: 'view', + get: function get() { + return this._container; + } + }]); + return ControlSlider; +}(_eventEmitter2.default); + +exports.default = ControlSlider; + +/***/ }), +/* 125 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.RTMPSubscriber = exports.HLSSubscriber = exports.RTCSubscriber = exports.Red5ProSubscriber = undefined; + +var _set = __webpack_require__(92); + +var _set2 = _interopRequireDefault(_set); + +var _toConsumableArray2 = __webpack_require__(94); + +var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2); + +var _getPrototypeOf = __webpack_require__(6); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = __webpack_require__(8); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = __webpack_require__(7); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _map = __webpack_require__(89); + +var _map2 = _interopRequireDefault(_map); + +var _implFactoryOrder = __webpack_require__(87); + +var _implFactoryOrder2 = _interopRequireDefault(_implFactoryOrder); + +var _eventEmitter = __webpack_require__(23); + +var _eventEmitter2 = _interopRequireDefault(_eventEmitter); + +var _red5proRtc = __webpack_require__(127); + +var _red5proRtc2 = _interopRequireDefault(_red5proRtc); + +var _red5proRtmp = __webpack_require__(128); + +var _red5proRtmp2 = _interopRequireDefault(_red5proRtmp); + +var _red5proHls = __webpack_require__(126); + +var _red5proHls2 = _interopRequireDefault(_red5proHls); + +var _promise = __webpack_require__(5); + +var _playback = __webpack_require__(34); + +var _log = __webpack_require__(2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var NAME = 'Red5ProSubscriber'; + +var playbackFactory = new _implFactoryOrder2.default(); +var playbackImpl = function () { + var map = new _map2.default(); + map.set(_playback.PlaybackTypes.RTC, _red5proRtc2.default); + map.set(_playback.PlaybackTypes.RTMP, _red5proRtmp2.default); + map.set(_playback.PlaybackTypes.HLS, _red5proHls2.default); + return map; +}(); + +/** + * Main entry for failover support of all subscriber implementations. + * + * @extends EventEmitter + */ + +var Red5ProSubscriber = function (_EventEmitter) { + (0, _inherits3.default)(Red5ProSubscriber, _EventEmitter); + + function Red5ProSubscriber() { + (0, _classCallCheck3.default)(this, Red5ProSubscriber); + + var _this = (0, _possibleConstructorReturn3.default)(this, (Red5ProSubscriber.__proto__ || (0, _getPrototypeOf2.default)(Red5ProSubscriber)).call(this)); + + _this._options = undefined; + _this._order = [_playback.PlaybackTypes.RTC, _playback.PlaybackTypes.RTMP, _playback.PlaybackTypes.HLS]; + return _this; + } + + /** + * Utilizes Failover Publisher Factory to attempt in determining browser support for Publisher from defined order. + * + * @return {Promise} + * + * @private + */ + + + (0, _createClass3.default)(Red5ProSubscriber, [{ + key: '_getPlaybackFromOrder', + value: function _getPlaybackFromOrder(order, options) { + return playbackFactory.create(order, playbackImpl, options, 'init'); + } + + /** + * Returns the specified order for auto-failover. + * + * @return {Array} + * Default: `['rtc', 'rtmp', 'hls']`. + */ + + }, { + key: 'getPlaybackOrder', + value: function getPlaybackOrder() { + return this._order; + } + + /** + * Defines the desired auto-failover order. + * + * @param {Array} order + * The desired order. e.g, `['rtc', 'rtmp', 'hls']`. + */ + + }, { + key: 'setPlaybackOrder', + value: function setPlaybackOrder(order) { + // Allow for string value to define single item in order. + order = typeof order === 'string' ? [order] : order; + + // Filter out values not available in enumeration of playback types. + var t = order.filter(function (entry) { + var key = void 0; + for (key in _playback.PlaybackTypes) { + if (_playback.PlaybackTypes[key].toLowerCase() === entry.toLowerCase()) { + return true; + } + } + return false; + }).map(function (entry) { + return entry.toLowerCase(); + }); + + // Define new order. + this._order = [].concat((0, _toConsumableArray3.default)(new _set2.default(t))); + (0, _log.debug)(NAME, '[orderupdate]: ' + this._order); + return this; + } + + /** + * Request to initialize and determine the proper Subscriber implementation based on configuration. + * + * The returned `Promise` will either resolve with the determined Subscriber instance or reject with an error String in failure to determine Subscriber type. + * + * @param {Object} options + * The initialization configuration map for each desired failover tech. + * @return {Promise} + */ + + }, { + key: 'init', + value: function init(options) { + this._options = options; + var deferred = new _promise.DeferredPromise(); + (0, _log.debug)(NAME, '[init]'); + this._getPlaybackFromOrder(this._order, this._options).then(function (subscriber) { + (0, _log.debug)(NAME, '[init:success]: subscriber found ' + subscriber.getType()); + deferred.resolve(subscriber); + }).catch(function (err) { + (0, _log.warn)(NAME, '[playerror]: Could not implement a subscriber: ' + err); + deferred.reject(err); + }); + return deferred.promise; + } + + /** + * Return enumerated value Subscriber types used in failover order. + * @type {Object} + */ + + }, { + key: 'playbackTypes', + get: function get() { + return _playback.PlaybackTypes; + } + }]); + return Red5ProSubscriber; +}(_eventEmitter2.default); + +exports.Red5ProSubscriber = Red5ProSubscriber; +exports.RTCSubscriber = _red5proRtc2.default; +exports.HLSSubscriber = _red5proHls2.default; +exports.RTMPSubscriber = _red5proRtmp2.default; + +/***/ }), +/* 126 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _extends2 = __webpack_require__(29); + +var _extends3 = _interopRequireDefault(_extends2); + +var _getPrototypeOf = __webpack_require__(6); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = __webpack_require__(8); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = __webpack_require__(7); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _browser = __webpack_require__(4); + +var _browser2 = _interopRequireDefault(_browser); + +var _websocket = __webpack_require__(42); + +var websocket = _interopRequireWildcard(_websocket); + +var _socketHelper = __webpack_require__(57); + +var _socketHelper2 = _interopRequireDefault(_socketHelper); + +var _red5proSourceHandlerHls = __webpack_require__(129); + +var _red5proSourceHandlerHls2 = _interopRequireDefault(_red5proSourceHandlerHls); + +var _playback = __webpack_require__(43); + +var _playback2 = _interopRequireDefault(_playback); + +var _index = __webpack_require__(24); + +var _event = __webpack_require__(15); + +var _playback3 = __webpack_require__(34); + +var _promise = __webpack_require__(5); + +var _log = __webpack_require__(2); + +var _urlEndpoint = __webpack_require__(58); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var NAME = 'HLSSubscriber'; + +/** + * Simple generation og unique subscriber id. + * + * @return {String} + * + * @private + */ +var generateSubscriptionId = function generateSubscriptionId() { + var id = Math.floor(Math.random() * 0x10000).toString(16); + return 'subscriber-' + id; +}; + +// Default to secure settings. +var defaultOptions = { + protocol: 'https', + port: 443, + app: 'live', + mimeType: 'application/x-mpegURL', + mediaElementId: 'red5pro-subscriber', + autoLayoutOrientation: true, + subscriptionId: generateSubscriptionId() + + /** + * Util to return the endpoint for an HLS video file. + * + * @param {Object} options + * The initialization object. + * @return {String} + * + * @private + */ +};var optionsToHlsURL = function optionsToHlsURL(options) { + var protocol = options.hlsprotocol ? options.hlsprotocol : options.protocol; + var port = options.hlsport ? options.hlsport : options.port; + var appEndpoint = options.context ? [options.app, options.context].join('/') : options.app; + return protocol + '://' + options.host + ':' + port + '/' + appEndpoint + '/' + options.streamName + '.m3u8'; +}; + +/** + * Main entry for HLS-based Subscriber. + * + * @extends EventEmitter + * @extends SubscriberPlaybackController + */ + +var HLSSubscriber = function (_PlaybackController) { + (0, _inherits3.default)(HLSSubscriber, _PlaybackController); + + function HLSSubscriber() { + (0, _classCallCheck3.default)(this, HLSSubscriber); + + var _this = (0, _possibleConstructorReturn3.default)(this, (HLSSubscriber.__proto__ || (0, _getPrototypeOf2.default)(HLSSubscriber)).call(this)); + + _this._options = undefined; + _this._view = undefined; + _this._sourceHandler = undefined; + _this._socketHelper = undefined; + _this._viewResolver = new _promise.DeferredPromise(); + _this._subscriptionResolver = new _promise.DeferredPromise(); + _this._boundBubbleSubscriberEvents = _this.bubbleSubscriberEvents.bind(_this); + return _this; + } + + (0, _createClass3.default)(HLSSubscriber, [{ + key: '_getViewResolverPromise', + value: function _getViewResolverPromise() { + return this._viewResolver.promise; + } + }, { + key: '_getSubscriptionResolverPromise', + value: function _getSubscriptionResolverPromise() { + return this._subscriptionResolver.promise; + } + + /** + * Proxy event bubbler through handler instance. + * + * @private + */ + + }, { + key: 'bubbleSubscriberEvents', + value: function bubbleSubscriberEvents(event) { + if (event.type === _event.SubscriberEventTypes.SUBSCRIBE_START) { + this._subscriptionResolver.resolve(this); + } + this.trigger(new _event.SubscriberEvent(event.type, this, event.data)); + } + + /** + * Gloms the Playback Controls API onto this instance to provide ease in use. + * + * @param {Object} handler + * The method request handler to bind and forward calls on. + * + * @private + */ + + }, { + key: '_glomSourceHandlerAPI', + value: function _glomSourceHandlerAPI(handler) { + var _this2 = this; + + this.play = handler.play.bind(handler); + this.pause = handler.pause.bind(handler); + this.resume = handler.resume.bind(handler); + this.stop = handler.stop.bind(handler); + this.mute = handler.mute.bind(handler); + this.unmute = handler.unmute.bind(handler); + this.setVolume = handler.setVolume.bind(handler); + this.seekTo = handler.seekTo.bind(handler); + this.toggleFullScreen = handler.toggleFullScreen.bind(handler); + handler.on('*', function (event) { + _this2.trigger(new _event.SubscriberEvent(event.type, _this2, event.data)); + }); + } + + /** + * Still in use, but hold-over of previous 3.x SDK versions designed to pair views and subscribers. In 4.0.0 it has been internalized. + * API deprecated. + * + * @private + */ + + }, { + key: '_setViewIfNotExist', + value: function _setViewIfNotExist(currentView) { + var mediaElementId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + + if (typeof currentView === 'undefined' && mediaElementId !== undefined) { + var view = new _playback2.default(mediaElementId); + view.attachSubscriber(this); + } + } + + /** + * Attempt to initialize the subscription handler for HLS. + * + * @param {Object} options + * The initialization configuration. + * @param {Object} handler + * The handler instance that will manage view interaction and events. + * + * @private + */ + + }, { + key: '_initHandler', + value: function _initHandler(options) { + var _this3 = this; + + var urlRegex = /^http(|s).*\.m3u8/g; + var url = this._options.streamName.match(urlRegex) ? this._options.streamName : optionsToHlsURL(this._options); + this._sourceHandler.on('*', this._boundBubbleSubscriberEvents); + this._sourceHandler.addSource(url, options.mimeType, options).then(function () { + _this3.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.CONNECT_SUCCESS)); + }).catch(function (err) { + (0, _log.error)(NAME, 'Could not establish an HLS Subscriber: ' + err); + _this3.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.CONNECT_FAILURE)); + }); + } + + /** + * Request to initialize the HLS-based Subscriber based on configuration. + * The returned `Promise` will either resolve with a reference to this instance or reject with an error `String` in failure. + * + * @param {Object} options + * The initialization configuration map. + * @return {Promise} + */ + + }, { + key: 'init', + value: function init(options) { + var _this4 = this; + + var deferred = new _promise.DeferredPromise(); + if (!_browser2.default.supportsHLS()) { + (0, _log.warn)(NAME, 'Could not resolve HLSSubscriber instance.'); + deferred.reject('Could not resolve HLSSubscriber instance.'); + } else if (options.connectionParams && !websocket.isSupported()) { + // If `connectionParams` are provided in the init config, + // then a subsequent validation call is made on a WebSocket to + // ensure that this client is allowed access. + (0, _log.warn)(NAME, 'Could not resolve HLSSubscriber instance with connection params. WebSocket support is required.'); + deferred.reject(NAME, 'Could not resolve HLSSubscriber instance with connection params. WebSocket support is required.'); + } else { + this._options = (0, _extends3.default)({}, defaultOptions, options); + var socketPromise = new _promise.DeferredPromise(); + if (this._options.connectionParams) { + this._socketHelper = new _socketHelper2.default(this, 'HLSSubscriptionSocket'); + var socketurl = (0, _urlEndpoint.hlsSocketEndpointFromOptions)(this._options, { + id: this._options.subscriptionId + }); + this._socketHelper.setUp(socketurl, socketPromise); + } else { + socketPromise.resolve(); + } + socketPromise.promise.then(function () { + // Tear down socket helper if exists. + // We only needed it to do validation with optional connectionParams. + if (_this4._socketHelper) { + _this4._socketHelper.tearDown(); + _this4._socketHelper = undefined; + } + _this4._setViewIfNotExist(_this4._view, _this4._options.mediaElementId); + _this4._getViewResolverPromise().then(function (view) { + _this4._sourceHandler = new _red5proSourceHandlerHls2.default(view.view, _this4.getType()); + _this4._glomSourceHandlerAPI(_this4._sourceHandler); + if (_this4._options) { + _this4._initHandler(_this4._options); + } + }); + deferred.resolve(_this4); + }).catch(function (error) { + deferred.reject(error); + _this4.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.CONNECT_FAILURE, _this4, error)); + }); + } + return deferred.promise; + } + + /** + * Still in use for assigning document element view management to this instance. + * API deprecated in 4.0.0. + * + * @private + */ + + }, { + key: 'setView', + value: function setView(view) { + this._view = view; + this._viewResolver.resolve(view); + return this; + } + + /** + * Request to begin subscribing to a stream. + * + * @return {Promise} + * The returned `Promise` will resolve or reject on successful start of playback. + */ + + }, { + key: 'subscribe', + value: function subscribe() { + return this._getSubscriptionResolverPromise(); + } + + /** + * Request to stop a subscription. + * The returned `Promise` will either resolve or reject on successful stop of subscription. + * + * @return {Promise} + */ + + }, { + key: 'unsubscribe', + value: function unsubscribe() { + (0, _log.debug)(NAME, '[unscubscribe]'); + var deferred = new _promise.DeferredPromise(); + if (this._socketHelper) { + this._socketHelper.tearDown(); + } + try { + this._sourceHandler.stop(); + this._sourceHandler.disconnect(); + deferred.resolve(); + } catch (e) { + deferred.reject(e.message); + } + return deferred.promise; + } + + /** + * Returns connection handler for playback. + * + * @return {Object} + */ + + }, { + key: 'getConnection', + value: function getConnection() { + return this._sourceHandler; + } + + /** + * Returns reference to playback controls if available. + * + * @return {PlaybackControls} + */ + + }, { + key: 'getControls', + value: function getControls() { + return this._sourceHandler ? this._sourceHandler.getControls() : undefined; + } + + /** + * Returns the initialization configuration used in `init()`. + * + * @return {Object} + */ + + }, { + key: 'getOptions', + value: function getOptions() { + return this._options; + } + + /** + * Returns the target view Element. + * + * @return {Element} + */ + + }, { + key: 'getPlayer', + value: function getPlayer() { + return this._view.view; + } + + /** + * Returns the type of implementation: `RTC`. + * + * @return {String} + */ + + }, { + key: 'getType', + value: function getType() { + return _playback3.PlaybackTypes.HLS.toUpperCase(); + } + }]); + return HLSSubscriber; +}(_index.PlaybackController); + +exports.default = HLSSubscriber; + +/***/ }), +/* 127 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _stringify = __webpack_require__(12); + +var _stringify2 = _interopRequireDefault(_stringify); + +var _extends2 = __webpack_require__(29); + +var _extends3 = _interopRequireDefault(_extends2); + +var _getPrototypeOf = __webpack_require__(6); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = __webpack_require__(8); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = __webpack_require__(7); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _browser = __webpack_require__(4); + +var _browser2 = _interopRequireDefault(_browser); + +var _translationUtil = __webpack_require__(81); + +var _webrtc = __webpack_require__(41); + +var webrtc = _interopRequireWildcard(_webrtc); + +var _websocket = __webpack_require__(42); + +var websocket = _interopRequireWildcard(_websocket); + +var _red5proSourceHandlerRtc = __webpack_require__(130); + +var _red5proSourceHandlerRtc2 = _interopRequireDefault(_red5proSourceHandlerRtc); + +var _socketHelperSub = __webpack_require__(115); + +var _socketHelperSub2 = _interopRequireDefault(_socketHelperSub); + +var _webrtcHelperSub = __webpack_require__(117); + +var _webrtcHelperSub2 = _interopRequireDefault(_webrtcHelperSub); + +var _playback = __webpack_require__(43); + +var _playback2 = _interopRequireDefault(_playback); + +var _controls = __webpack_require__(24); + +var _object = __webpack_require__(28); + +var _urlEndpoint = __webpack_require__(58); + +var _event = __webpack_require__(15); + +var _playback3 = __webpack_require__(34); + +var _webrtc2 = __webpack_require__(55); + +var _promise = __webpack_require__(5); + +var _log = __webpack_require__(2); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var subStartRegex = /(.*) starting/i; +var NAME = 'RTCSubscriber'; + +/** + * Simple generation og unique subscriber id. + * + * @return {String} + * + * @private + */ +var generateSubscriptionId = function generateSubscriptionId() { + var id = Math.floor(Math.random() * 0x10000).toString(16); + return 'subscriber-' + id; +}; + +// Default to secure settings. +var defaultOptions = { + protocol: 'wss', + port: 8083, + app: 'live', + autoLayoutOrientation: true, + mediaElementId: 'red5pro-subscriber', + iceServers: [{ urls: 'stun:stun2.l.google.com:19302' }], + iceTransport: _webrtc2.IceTransportTypes.UDP, + maintainConnectionOnSubscribeErrors: false + + /** + * Main entry for WebRTC-based Subscriber. + * + * @extends EventEmitter + * @extends SubscriberPlaybackController + */ +}; +var RTCSubscriber = function (_PlaybackController) { + (0, _inherits3.default)(RTCSubscriber, _PlaybackController); + + function RTCSubscriber() { + (0, _classCallCheck3.default)(this, RTCSubscriber); + + var _this = (0, _possibleConstructorReturn3.default)(this, (RTCSubscriber.__proto__ || (0, _getPrototypeOf2.default)(RTCSubscriber)).call(this)); + + _this._view = undefined; + _this._options = undefined; + _this._peerHelper = undefined; + _this._socketHelper = undefined; + _this._connectionClosed = true; + _this._sourceHandler = undefined; + _this._mediaStream = undefined; + _this._viewResolver = new _promise.DeferredPromise(); + _this._availabilityResolver = new _promise.DeferredPromise(); + _this._subscriptionResolver = new _promise.DeferredPromise(); + _this._orientation = 0; + return _this; + } + + (0, _createClass3.default)(RTCSubscriber, [{ + key: '_getViewResolverPromise', + value: function _getViewResolverPromise() { + return this._viewResolver.promise; + } + }, { + key: '_getAvailabilityResolverPromise', + value: function _getAvailabilityResolverPromise() { + return this._availabilityResolver.promise; + } + }, { + key: '_getSubscriptionResolverPromise', + value: function _getSubscriptionResolverPromise() { + return this._subscriptionResolver.promise; + } + + /** + * Gloms the Playback Controls API onto this instance to provide ease in use. + * + * @param {Object} handler + * The method request handler to bind and forward calls on. + * + * @private + */ + + }, { + key: '_glomSourceHandlerAPI', + value: function _glomSourceHandlerAPI(handler) { + var _this2 = this; + + this.play = handler.play.bind(handler); + this.pause = handler.pause.bind(handler); + this.resume = handler.resume.bind(handler); + this.stop = handler.stop.bind(handler); + this.mute = handler.mute.bind(handler); + this.unmute = handler.unmute.bind(handler); + this.setVolume = handler.setVolume.bind(handler); + this.seekTo = handler.seekTo.bind(handler); + this.toggleFullScreen = handler.toggleFullScreen.bind(handler); + handler.on('*', function (event) { + _this2.trigger(new _event.SubscriberEvent(event.type, _this2, event.data)); + }); + } + + /** + * Still in use, but hold-over of previous 3.x SDK versions designed to pair views and subscribers. In 4.0.0 it has been internalized. + * API deprecated. + * + * @private + */ + + }, { + key: '_setViewIfNotExist', + value: function _setViewIfNotExist(currentView) { + var mediaElementId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + + if (typeof currentView === 'undefined' && mediaElementId !== undefined) { + var view = new _playback2.default(mediaElementId); + view.attachSubscriber(this); + } + } + + /** + * Attempt to initialize the subscription handler for WebRTC. + * + * @param {Object} options + * The initialization configuration. + * @param {Object} handler + * The handler instance that will manage view interaction and events. + * + * @private + */ + + }, { + key: '_initHandler', + value: function _initHandler(options, handler) { + if (options && handler) { + handler.on('*', this._boundBubbleSubscriberEvents); + handler.addSource(options); + } + } + + /** + * Request available stream by name on server through WebSocket request. + * + * @param {String} streamName + * The name of the stream to look up. + * @private + */ + + }, { + key: '_requestAvailability', + value: function _requestAvailability(streamName) { + (0, _log.debug)(NAME, '[requestavailability]'); + // message on socket returns -> onStream(Un)Available + this._socketHelper.post({ + isAvailable: streamName + }); + } + + /** + * Request offer over WebSocket. + * + * @param {String} streamName + * The name of the stream to subscribe to. + * @param {String} subscriptionId + * The unique id of this subscriber. + * @param {String} vEncoding + * Optional encoding type for video. Defaults to server selection. + * @param {String} aEncoding + * Optional encoding type for audio. Defaults to server selection. + * + * @private + */ + + }, { + key: '_requestOffer', + value: function _requestOffer(streamName, subscriptionId, transport) { + var vEncoding = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : undefined; + var aEncoding = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : undefined; + + (0, _log.debug)(NAME, '[requestoffer]'); + var offer = { + requestOffer: streamName, + requestId: subscriptionId, + transport: transport + }; + if (typeof vEncoding !== 'undefined' && vEncoding !== _playback3.PlaybackVideoEncoder.NONE) { + offer.videoEncoding = vEncoding; + } + if (typeof aEncoding !== 'undefined' && aEncoding !== _playback3.PlaybackAudioEncoder.NONE) { + offer.audioEncoding = aEncoding; + } + this.trigger(new _event.SubscriberEvent(_event.RTCSubscriberEventTypes.OFFER_START, this)); + // message on socket returns -> onSDPOffer + this._socketHelper.post(offer); + } + + /** + * Creates and sends an answer based on provided SDP. + * + * @param {Object} sdp + * The SDP object to use in creating an SDP answer to send back. + * + * @private + */ + + }, { + key: '_requestAnswer', + value: function _requestAnswer(sdp) { + var _this3 = this; + + (0, _log.debug)(NAME, '[requestanswer]'); + // invokes -> sendAnswer + this._peerHelper.createAnswer(sdp).then(function (sessionDescription) { + (0, _log.debug)(NAME, '[onanswercreated]'); + (0, _log.debug)(NAME, '[> sendanswer]'); + _this3._sendAnswer(_this3._options.streamName, _this3._options.subscriptionId, sessionDescription); + }).catch(function (error) { + _this3.onSDPError(error); + }); + } + + /** + * Posts SDP answer to server over WebSocket. + * + * @param {String} streamName + * The target stream name. + * @param {String} subscriptionId + * The unique id of this subscriber. + * @param {Object} sdp + * The SDP to send as an answer. + * + * @private + */ + + }, { + key: '_sendAnswer', + value: function _sendAnswer(streamName, subscriptionId, sdp) { + (0, _log.debug)(NAME, '[sendanswer]: streamname(' + streamName + '), subscriptionid(' + subscriptionId + ')'); + this.trigger(new _event.SubscriberEvent(_event.RTCSubscriberEventTypes.ANSWER_START, this, sdp)); + // message on socket response -> onAddIceCandidate + // message on peer response -> onaddstream + this._socketHelper.post({ + handleAnswer: streamName, + requestId: subscriptionId, + data: { + sdp: sdp + } + }); + } + + /** + * Sends a candidate to the server over WebSocket. + * + * @param {Object} candidate + * The peer candidate description. + * + * @private + */ + + }, { + key: '_sendCandidate', + value: function _sendCandidate(candidate) { + (0, _log.debug)(NAME, '[sendcandidate]'); + this.trigger(new _event.SubscriberEvent(_event.RTCSubscriberEventTypes.CANDIDATE_START, this, candidate)); + // message on peer response -> onicecandidate + this._socketHelper.post({ + handleCandidate: this._options.streamName, + requestId: this._options.subscriptionId, + data: { + candidate: candidate + } + }); + } + + /** + * Setup and connect to begin a subscription. + * This is invoked once the availability of the stream is recognized on the server and notified on this instance. + * + * @param {Array} iceServers + * The ICE server list to use in trickle. + * + * @private + */ + + }, { + key: '_connect', + value: function _connect(iceServers) { + var _this4 = this; + + (0, _log.debug)(NAME, '[connect]'); + this._options.iceServers = iceServers; + var p = this._peerHelper.setUp(this._options.iceServers, undefined, this._options.rtcpMuxPolicy); + p.then(function (connection) { + _this4.trigger(new _event.SubscriberEvent(_event.RTCSubscriberEventTypes.PEER_CONNECTION_AVAILABLE, _this4, connection)); + _this4._requestOffer(_this4._options.streamName, _this4._options.subscriptionId, _this4._options.iceTransport, _this4._options.videoEncoding, _this4._options.audioEncoding); + }).catch(function () { + (0, _log.warn)(NAME, 'Could not establish RTCPeerConnection.'); + _this4.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.CONNECT_FAILURE, _this4)); + }); + // TODO: Normalize returns to either all be chainable or not be chainable + return this; + } + + /** + * Disconnect and teardown after close of subscription. + * + * @private + */ + + }, { + key: '_disconnect', + value: function _disconnect() { + if (this._socketHelper) { + (0, _log.debug)(NAME, '[disconnect:socket]'); + this._socketHelper.tearDown(); + } + if (this._peerHelper) { + (0, _log.debug)(NAME, '[disconnect:peer]'); + this._peerHelper.tearDown(); + } + if (this._sourceHandler) { + (0, _log.debug)(NAME, '[disconnect:source]'); + this._sourceHandler.disconnect(); + } + this._connectionClosed = true; + } + + /** + * Request to kick off autoplay if setting is flagged. + * + * @param {Object} options + * The initialization object. + * @param {Element} view + * The target element view that will playback the stream. + * + * @private + */ + + }, { + key: '_playIfAutoplaySet', + value: function _playIfAutoplaySet(options, view) { + if (options && view) { + options.autoplay = _browser2.default.hasAttributeDefined(view.view, 'autoplay'); + if (options.autoplay) { + this.play(); + } + } + } + + /** + * Request to begin subscription on server over WebSocket. + * + * @private + */ + + }, { + key: '_sendSubscribe', + value: function _sendSubscribe() { + (0, _log.debug)(NAME, '[sendsubscribe]'); + this._socketHelper.post({ + subscribe: this._options.streamName, + requestId: this._options.subscriptionId + }); + } + + /** + * Request to initialize the WebRTC-based Subscriber based on configuration. + * The returned `Promise` will either resolve with a reference to this instance or reject with an error `String` in failure. + * + * @param {Object} options + * The initialization configuration map. + * @return {Promise} + */ + + }, { + key: 'init', + value: function init(options) { + var _this5 = this; + + var deferred = new _promise.DeferredPromise(); + if (!webrtc.isSupported() || !websocket.isSupported()) { + deferred.reject('Cannot create WebRTC playback instance. Your environment does not support WebRTC and/or WebSockets.'); + } else { + this._disconnect(); + this._options = (0, _extends3.default)({}, defaultOptions, options); + this._options.subscriptionId = this._options.subscriptionId || generateSubscriptionId(); + + this._peerHelper = new _webrtcHelperSub2.default(this); + this._socketHelper = new _socketHelperSub2.default(this); + var socketPromise = new _promise.DeferredPromise(); + var socketurl = (0, _urlEndpoint.rtcSocketEndpointFromOptions)(this._options, { + id: this._options.subscriptionId + }); + + socketPromise.promise.then(function () { + deferred.resolve(_this5); + _this5._connectionClosed = false; + _this5.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.CONNECT_SUCCESS, _this5)); + }).catch(function (error) { + deferred.reject(error); + _this5.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.CONNECT_FAILURE, _this5, error)); + }); + + this._socketHelper.setUp(socketurl, socketPromise); + } + return deferred.promise; + } + + /** + * Still in use for assigning document element view management to this instance. + * API deprecated in 4.0.0. + * + * @private + */ + + }, { + key: 'setView', + value: function setView(view) { + this._view = view; + this._viewResolver.resolve(this._view); + return this; + } + + /** + * Request to begin subscribing to a stream. + * + * @return {Promise} + * The returned `Promise` will resolve or reject on successful start of playback. + * There are several processes that occur in order to establish a WebRTC subscription that involve - but are not limited to - ICE communication and assigning of local and remote SDPs on peer connections. + */ + + }, { + key: 'subscribe', + value: function subscribe() { + var _this6 = this; + + this._getViewResolverPromise().then(function (view) { + _this6._sourceHandler = new _red5proSourceHandlerRtc2.default(view.view, _this6.getType()); + _this6._glomSourceHandlerAPI(_this6._sourceHandler); + _this6._initHandler(_this6._options, _this6._sourceHandler); + }); + this._getAvailabilityResolverPromise().then(function () { + _this6._connect(_this6._options.iceServers); + }); + this._setViewIfNotExist(this._view, this._options.mediaElementId); + this._requestAvailability(this._options.streamName, this._options.streamType); + return this._getSubscriptionResolverPromise(); + } + + /** + * Request to stop a subscription. + * The returned `Promise` will either resolve or reject on successful stop of subscription. + * + * @return {Promise} + */ + + }, { + key: 'unsubscribe', + value: function unsubscribe() { + (0, _log.debug)(NAME, '[unsubscribe]'); + var deferred = new _promise.DeferredPromise(); + this.stop(); + this._disconnect(); + this._mediaStream = undefined; + deferred.resolve(this); + this.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.SUBSCRIBE_STOP, this)); + return deferred.promise; + } + + /** + * Event handler for stream being available on server. + * + * @private + */ + + }, { + key: 'onStreamAvailable', + value: function onStreamAvailable(receipt) { + (0, _log.debug)(NAME, '[onstreamavailable]: ' + (0, _stringify2.default)(receipt, null, 2)); + this._availabilityResolver.resolve(this); + } + + /** + * Event handler for stream being unavailable on server. + * + * @private + */ + + }, { + key: 'onStreamUnavailable', + value: function onStreamUnavailable(receipt) { + (0, _log.debug)(NAME, 'Stream ' + this._options.streamName + ' does not exist.'); + (0, _log.debug)(NAME, '[onstreamunavailable]: ' + (0, _stringify2.default)(receipt, null, 2)); + this.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.SUBSCRIBE_INVALID_NAME, this)); + this._availabilityResolver.reject('Stream ' + this._options.streamName + ' does not exist.'); + this._subscriptionResolver.reject('Stream ' + this._options.streamName + ' does not exist.'); + if (!this._options.maintainConnectionOnSubscribeErrors) { + this._disconnect(); + } else { + // Reset promise for possible retry. + this._availabilityResolver = new _promise.DeferredPromise(); + this._subscriptionResolver = new _promise.DeferredPromise(); + } + } + + /** + * Event handler for success of SDP being added remotely and locally through the Peer Connection. + * + * @param {Object} receipt + * + * @private + */ + + }, { + key: 'onSDPSuccess', + value: function onSDPSuccess(receipt) { + (0, _log.debug)(NAME, '[onsdpsuccess]: ' + (0, _stringify2.default)(receipt, null, 2)); + } + + /** + * Event handler for success in SDP offer. + * + * @param {Object} receipt + * The optional successful object. + * + * @private + */ + + }, { + key: 'onSDPOffer', + value: function onSDPOffer(receipt) { + (0, _log.debug)(NAME, '[onsdpoffer]: ' + (0, _stringify2.default)(receipt, null, 2)); + var sdp = new webrtc.RTCSessionDescription(receipt.sdp); + this.trigger(new _event.SubscriberEvent(_event.RTCSubscriberEventTypes.OFFER_END, this)); + this._requestAnswer(sdp); + } + + /** + * Event handler for all errors related to SDP through the Peer Connection. + * + * @param {Object} receipt + * The optional error object. + * + * @private + */ + + }, { + key: 'onSDPError', + value: function onSDPError(receipt) { + this.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.SUBSCRIBE_FAIL, this, receipt)); + this._subscriptionResolver.reject('Invalid SDP.'); + (0, _log.error)(NAME, '[onsdperror]'); + (0, _log.error)(NAME, receipt); + } + + /** + * Event handler for receipt of a `MediaStream`. + * + * @param {MediaStream} stream + * The stream returned on the Peer Connection. + * + * @private + */ + + }, { + key: 'onAnswerMediaStream', + value: function onAnswerMediaStream() { + var stream = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined; + // eslint-disable-line no-unused-vars + this.trigger(new _event.SubscriberEvent(_event.RTCSubscriberEventTypes.ANSWER_END, this)); + } + + /** + * Event handler on receipt of ICE candidate. + * + * @param {Object} candidate + * The ICE candidate. + * + * @private + */ + + }, { + key: 'onIceCandidate', + value: function onIceCandidate(candidate) { + (0, _log.debug)(NAME, '[onicecandidate]'); + this.trigger(new _event.SubscriberEvent(_event.RTCSubscriberEventTypes.CANDIDATE_END, this)); + this._sendCandidate(candidate); + } + + /** + * Event handler for end of ICE communication (trickle). + * + * @param {MediaStream} stream + * The `MediaStream` that has become available post-trickle. + * + * @private + */ + + }, { + key: 'onIceCandidateTrickleEnd', + value: function onIceCandidateTrickleEnd(stream) { + var _this7 = this; + + (0, _log.debug)(NAME, '[onicetrickleend]'); + this._getViewResolverPromise().then(function (view) { + view.attachStream(stream); + _this7._mediaStream = stream; + _this7.trigger(new _event.SubscriberEvent(_event.RTCSubscriberEventTypes.ON_ADD_STREAM, _this7, _this7._mediaStream)); + }); + } + + /** + * Event handler to add ICE candidate to Peer Connection. + * + * @param {Object} candidate + * + * @private + */ + + }, { + key: 'onAddIceCandidate', + value: function onAddIceCandidate(candidate) { + (0, _log.debug)(NAME, '[onaddicecandidate]'); + this._peerHelper.addIceCandidate(candidate); + } + + /** + * Event handler for receipt of empty candidate during ICE negotiation. + * + * @private + */ + + }, { + key: 'onEmptyCandidate', + value: function onEmptyCandidate() { + (0, _log.debug)(NAME, '[icecandidatetrickle:empty]'); + this.trigger(new _event.SubscriberEvent(_event.RTCSubscriberEventTypes.PEER_CANDIDATE_END)); + } + + /** + * Event handler for completion of peer ice candidate gathering. + * + * @private + */ + + }, { + key: 'onPeerGatheringComplete', + value: function onPeerGatheringComplete() { + (0, _log.debug)(NAME, '[icecandidategathering:end]'); + if (this._socketHelper) { + this._socketHelper.postEndOfCandidates(this._options.streamName); + } + } + + /** + * Event handler for notification of end in ice candidates over the WebSocket. + * + * @private + */ + + }, { + key: 'onSocketIceCandidateEnd', + value: function onSocketIceCandidateEnd() { + (0, _log.debug)(NAME, '[onsocketicecandidateend]'); + this.trigger(new _event.SubscriberEvent(_event.RTCSubscriberEventTypes.ICE_TRICKLE_COMPLETE, this)); + this._sendSubscribe(); + } + + /** + * General event handler for errors coming over the WebSocket. + * + * @param {String} message + * @param {Object} detail + * Optional additional detail. + * + * @private + */ + + }, { + key: 'onSocketMessageError', + value: function onSocketMessageError(message) { + var detail = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + + (0, _log.error)(NAME, 'Error in stream subscription: ' + message + '.\n[Optional detail]: ' + detail); + this._subscriptionResolver.reject('Error in stream subscription: ' + message + '.'); + this.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.SUBSCRIBE_FAIL, this, message)); + } + + /** + * Event handler for close on the WebSocket. + * + * @param {Event} closeEvent + * + * @private + */ + + }, { + key: 'onSocketClose', + value: function onSocketClose(closeEvent) { + (0, _log.debug)(NAME, '[onsocketclose]'); + if (this._peerHelper) { + this._peerHelper.tearDown(); + } + this.onConnectionClosed(closeEvent); + } + + /** + * Event handler for close of Peer Connection. + * + * @param {Event} event + * + * @private + */ + + }, { + key: 'onPeerConnectionClose', + value: function onPeerConnectionClose(event) { + (0, _log.debug)(NAME, '[onpeerconnectionclose]'); + if (this._socketHelper) { + this._socketHelper.tearDown(); + } + this.onSocketClose(event); + } + + /** + * Event handler for `Unpublish` of stream subscribed to. Occurs when a broadcaster stops their stream while this subscription stream is open. + * + * @private + */ + + }, { + key: 'onUnpublish', + value: function onUnpublish() { + (0, _log.debug)(NAME, '[onunpublish]'); + if (this._sourceHandler) { + this._sourceHandler.unpublish(); + } + this.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.PLAY_UNPUBLISH, this)); + } + + /** + * Event handler for connection on stream being closed. + * + * @private + */ + + }, { + key: 'onConnectionClosed', + value: function onConnectionClosed() { + var event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined; + + if (!this._connectionClosed) { + (0, _log.debug)(NAME, '[onconnectionclosed]'); + this._disconnect(); + this.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.CONNECTION_CLOSED, this, event)); + } + } + + /** + * Event handler for accepting data through the `send` API of a Publisher. This is the receiving end of the communication channel in which a Publisher can send data to all subscribers. + * + * @param {String} methodName + * The target method name associated with the communication. + * @param {Object} data + * The data being sent. + * + * @private + */ + + }, { + key: 'onSendReceived', + value: function onSendReceived(methodName, data) { + if (methodName === 'onMetaData') { + this.onMetaData(data); + } else { + // environment.invoke(methodName, data) + this.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.SUBSCRIBE_SEND_INVOKE, this, { + methodName: methodName, + data: data + })); + } + } + + /** + * Event handler for status notifications of the subscription stream coming over the WebSocket. + * + * @param {Object} status + * The status object. + * + * @private + */ + + }, { + key: 'onSubscriberStatus', + value: function onSubscriberStatus(status) { + (0, _log.debug)(NAME, '[subscriberstatus] - ' + (0, _stringify2.default)(status, null, 2)); + var startResult = subStartRegex.exec(status.message); + if (startResult && startResult[1] === this._options.streamName) { + this._subscriptionResolver.resolve(this); + this.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.SUBSCRIBE_START, this)); + this._playIfAutoplaySet(this._options, this._view); + } + } + + /** + * Event handler for metadata being sent related to the subscription stream coming over the WebSocket. + * + * @param {Object} metadata + * + * @private + */ + + }, { + key: 'onMetaData', + value: function onMetaData(metadata) { + if (typeof metadata.orientation !== 'undefined' && metadata.orientation !== this._orientation) { + this._orientation = metadata.orientation; + if (this._options.autoLayoutOrientation) { + (0, _translationUtil.applyOrientation)(this._view.view, parseInt(metadata.orientation, 10), (0, _object.metadataResolutionToObject)(metadata.resolution)); + if (this._sourceHandler) { + this._sourceHandler.handleOrientationChange(parseInt(metadata.orientation)); + } + } + this.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.ORIENTATION_CHANGE, this, { + orientation: parseInt(metadata.orientation), + viewElement: this._view.view + })); + } + this.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.SUBSCRIBE_METADATA, this, metadata)); + } + + /** + * Request to invoke a method on the Application Adapter related to the `app` config setting. + * + * @param {String} methodName + * The name of the method to invoke on thw Application Adapter + * @param {Array} args + * The ordered list of arguments to invoke on the method. Do not provide anything if the method takes no arguments. + * @return {Promise} + */ + + }, { + key: 'callServer', + value: function callServer(methodName, args) { + return this._socketHelper.postAsync({ + callAdapter: { + method: methodName, + arguments: args + } + }); + } + + /** + * Enters subscriber into standby mode - keeping connection open but not bothering to consume video or audio. + */ + + }, { + key: 'enableStandby', + value: function enableStandby() { + this._socketHelper.post({ + standby: true + }); + } + + /** + * Removes subscriber from standby mode - turning the audio and video back on and consumable after a mute request. + */ + + }, { + key: 'disableStandby', + value: function disableStandby() { + this._socketHelper.post({ + standby: false + }); + } + + /** + * Returns the current WebSocket connection helper if established. + * Used in SharedObject communication. + * + * @return {PublisherSocketHelper} + * + * @private + */ + + }, { + key: 'getConnection', + value: function getConnection() { + return this._socketHelper; + } + + /** + * Returns the current RTCPeerConnection helper if established. + * + * @return {RTCPeerConnection} + */ + + }, { + key: 'getPeerConnection', + value: function getPeerConnection() { + return this._peerHelper ? this._peerHelper.connection : undefined; + } + + /** + * Returns the `MediaStream` instance if generated through `getUserMedia` and exists for broadcast. + * + * @return {MediaStream} + */ + + }, { + key: 'getMediaStream', + value: function getMediaStream() { + return this._mediaStream; + } + + /** + * Returns reference to playback controls if available. + * + * @return {PlaybackControls} + */ + + }, { + key: 'getControls', + value: function getControls() { + return this._sourceHandler ? this._sourceHandler.getControls() : undefined; + } + + /** + * Returns the target view Element. + * + * @return {Element} + */ + + }, { + key: 'getPlayer', + value: function getPlayer() { + return this._view.view; + } + + /** + * Returns the initialization configuration used in `init()`. + * + * @return {Object} + */ + + }, { + key: 'getOptions', + value: function getOptions() { + return this._options; + } + + /** + * Returns the type of implementation: `RTC`. + * + * @return {String} + */ + + }, { + key: 'getType', + value: function getType() { + return _playback3.PlaybackTypes.RTC.toUpperCase(); + } + }]); + return RTCSubscriber; +}(_controls.PlaybackController); + +exports.default = RTCSubscriber; + +/***/ }), +/* 128 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _promise = __webpack_require__(61); + +var _promise2 = _interopRequireDefault(_promise); + +var _extends2 = __webpack_require__(29); + +var _extends3 = _interopRequireDefault(_extends2); + +var _getPrototypeOf = __webpack_require__(6); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = __webpack_require__(8); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = __webpack_require__(7); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _browser = __webpack_require__(4); + +var _browser2 = _interopRequireDefault(_browser); + +var _red5proSourceHandlerRtmp = __webpack_require__(131); + +var _red5proSourceHandlerRtmp2 = _interopRequireDefault(_red5proSourceHandlerRtmp); + +var _playback = __webpack_require__(43); + +var _playback2 = _interopRequireDefault(_playback); + +var _controls = __webpack_require__(24); + +var _event = __webpack_require__(15); + +var _playback3 = __webpack_require__(34); + +var _state = __webpack_require__(35); + +var _promise3 = __webpack_require__(5); + +var _log = __webpack_require__(2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var NAME = 'RTMPSubcriber'; + +var defaultOptions = { + protocol: 'rtmp', + port: 1935, + width: 320, // media playback + height: 240, // media playback + embedWidth: '100%', // DOM display style + embedHeight: '100%', // DOM display style + minFlashVersion: '10.0.0', + swf: 'lib/red5pro/red5pro-subscriber.swf', + swfobjectURL: 'lib/swfobject/swfobject.js', + productInstallUrl: 'lib/swfobject/playerProductInstall.swf', + mediaElementId: 'red5pro-subscriber', + // with Autoscale enabled server only => + useAdaptiveBitrateController: false, + abrVariants: undefined, + abrVariantUpgradeSettings: { + minimumDowngradePlaybackSpan: 10000, // Amount of time playback needs to exceed between playback and downgrade in order to be eligible for upgrade + upgrade: [{ + level: 1, + retryTimeout: 0 + }, { + level: 2, + retryTimeout: 10000 // If on level 2, in 10 seconds after playback, try and switch up. + }, { + level: 3, + retryTimeout: 20000 // If on level 3, in 20 seconds after playback, try and switch up. + }] + } + + /** + * Main entry for Flash-based Subscriber over RTMP. + * + * @extends EventEmitter + * @extends SubscriberPlaybackController + */ +}; +var RTMPSubscriber = function (_PlaybackController) { + (0, _inherits3.default)(RTMPSubscriber, _PlaybackController); + + function RTMPSubscriber() { + (0, _classCallCheck3.default)(this, RTMPSubscriber); + + var _this = (0, _possibleConstructorReturn3.default)(this, (RTMPSubscriber.__proto__ || (0, _getPrototypeOf2.default)(RTMPSubscriber)).call(this)); + + _this._options = undefined; + _this._view = undefined; + _this._sourceHandler = undefined; + _this._elementId = undefined; + _this._embedPromise = undefined; + _this._getEmbedPromise().then(function () { + _this.onEmbedComplete(); + }).catch(function (err) { + return _this.onEmbedFailure(err); + }); + _this._viewResolver = new _promise3.DeferredPromise(); + _this._subscriptionResolver = new _promise3.DeferredPromise(); + return _this; + } + + (0, _createClass3.default)(RTMPSubscriber, [{ + key: '_getViewResolverPromise', + value: function _getViewResolverPromise() { + return this._viewResolver.promise; + } + }, { + key: '_getSubscriptionResolverPromise', + value: function _getSubscriptionResolverPromise() { + return this._subscriptionResolver.promise; + } + }, { + key: '_getEmbedPromise', + value: function _getEmbedPromise() { + this._embedPromise = _promise3.Future.createIfNotExist(this._embedPromise); + return this._embedPromise.promise; + } + + /** + * Gloms the Playback Controls API onto this instance to provide ease in use. + * + * @param {Object} handler + * The method request handler to bind and forward calls on. + * + * @private + */ + + }, { + key: '_glomSourceHandlerAPI', + value: function _glomSourceHandlerAPI(handler) { + var _this2 = this; + + /* + * || Note || + * play() is not glommed as it needs to be handled differently. + */ + + this.pause = handler.pause.bind(handler); + this.resume = handler.resume.bind(handler); + this.stop = handler.stop.bind(handler); + this.mute = handler.mute.bind(handler); + this.unmute = handler.unmute.bind(handler); + this.setVolume = handler.setVolume.bind(handler); + this.seekTo = handler.seekTo.bind(handler); + this.toggleFullScreen = handler.toggleFullScreen.bind(handler); + + // Adaptive Bitrate Controller - Autoscale enabled only. + this.setABRLevel = handler.setABRLevel.bind(handler); + this.setABRVariants = handler.setABRVariants.bind(handler); + this.stopABRController = handler.stopABRController.bind(handler); + this.startABRController = handler.startABRController.bind(handler); + this.setABRVariantUpgradeSettings = handler.setABRVariantUpgradeSettings.bind(handler); + + handler.on('*', function (event) { + _this2.trigger(new _event.SubscriberEvent(event.type, _this2, event.data)); + }); + } + + /** + * Still in use, but hold-over of previous 3.x SDK versions designed to pair views and subscribers. In 4.0.0 it has been internalized. + * API deprecated. + * + * @private + */ + + }, { + key: '_setViewIfNotExist', + value: function _setViewIfNotExist(currentView) { + var mediaElementId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + + if (typeof currentView === 'undefined' && mediaElementId !== undefined) { + var view = new _playback2.default(mediaElementId); + view.attachSubscriber(this); + } + } + + /** + * Define global function handlers for ExternalInterface to invoke for API communication. + * + * @private + */ + + }, { + key: '_establishExtIntHandlers', + value: function _establishExtIntHandlers(id) { + var _this3 = this; + + (0, _log.debug)(NAME, 'Subscriber ID provided to client: (' + id + ').'); + var invokeFn = function invokeFn(label) { + return ['subscriber', label, id.split('-').join('_')].join('_'); + }; + window[invokeFn('r5proConnectClosed')] = function () { + return _this3.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.CONNECTION_CLOSED, _this3)); + }; + window[invokeFn('r5proConnectSuccess')] = function () { + return _this3.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.CONNECT_SUCCESS, _this3)); + }; + window[invokeFn('r5proConnectFailure')] = function () { + _this3.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.CONNECT_FAILURE, _this3)); + }; + window[invokeFn('r5proSubscribeStop')] = function () { + return _this3.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.SUBSCRIBE_STOP, _this3)); + }; + window[invokeFn('r5proSubscribeMetadata')] = function (metadata) { + return _this3.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.SUBSCRIBE_METADATA, _this3, JSON.parse(metadata))); + }; + window[invokeFn('r5proSubscribeUnpublish')] = function () { + return _this3.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.PLAY_UNPUBLISH, _this3)); + }; + window[invokeFn('r5proSubscribeSendInvoke')] = function (payload) { + _this3.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.SUBSCRIBE_SEND_INVOKE, _this3, typeof payload === 'string' ? JSON.parse(payload) : payload)); + }; + window[invokeFn('r5proSubscribePlayRequest')] = function () { + _this3.play(); + }; + window[invokeFn('r5proSubscribeStart')] = function () { + _this3._subscriptionResolver.resolve(_this3); + _this3.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.SUBSCRIBE_START, _this3)); + }; + window[invokeFn('r5proSubscribeInvalidName')] = function () { + _this3._subscriptionResolver.reject('NetStream.Play.StreamNotFound', _this3); + _this3.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.SUBSCRIBE_INVALID_NAME, _this3)); + }; + window[invokeFn('r5proSubscribeFail')] = function () { + _this3._subscriptionResolver.reject('NetStream.Failed', _this3); + _this3.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.SUBSCRIBE_FAIL, _this3)); + }; + window[invokeFn('r5proSubscribeVolumeChange')] = function (payload) { + _this3.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.VOLUME_CHANGE, _this3, { + volume: JSON.parse(payload).volume + })); + }; + window[invokeFn('r5proSubscribePlaybackTimeChange')] = function (payload) { + var data = JSON.parse(payload); + _this3.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.PLAYBACK_TIME_UPDATE, _this3, { + time: data.value, + duration: data.duration + })); + }; + window[invokeFn('r5proSubscribePlaybackStateChange')] = function (payload) { + var code = JSON.parse(payload).code; + _this3.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.PLAYBACK_STATE_CHANGE, _this3, { + code: code, + state: _state.PlaybackStateReadable[code] + })); + }; + window[invokeFn('r5proSubscribeABRLevelChange')] = function (payload) { + var data = JSON.parse(payload); + var level = data.level, + stream = data.stream; + + var settings = JSON.parse(decodeURIComponent(stream)); + _this3.trigger(new _event.SubscriberEvent(_event.RTMPSubscriberEventTypes.ABR_LEVEL_CHANGE, _this3, { + level: level, + stream: settings + })); + }; + } + + /** + * Request to initialize the HLS-based Subscriber based on configuration. + * The returned `Promise` will either resolve with a reference to this instance or reject with an error `String` in failure. + * + * @param {Object} options + * The initialization configuration map. + * @return {Promise} + */ + + }, { + key: 'init', + value: function init(options) { + var _this4 = this; + + var deferred = new _promise3.DeferredPromise(); + var version = options.minFlashVersion || defaultOptions.minFlashVersion; + if (!_browser2.default.supportsFlashVersion(version)) { + (0, _log.warn)(NAME, 'Could not resolve RTMPSubscriber instance. Requires minimum Flash Player install of ' + version + '.'); + deferred.reject('Could not resolve RTMPSubscriber instance. Requires minimum Flash Player install of ' + version + '.'); + } else { + this._options = (0, _extends3.default)({}, defaultOptions, options); + var establishSourceHandler = function establishSourceHandler() { + _this4._getViewResolverPromise().then(function (view) { + _this4._sourceHandler = new _red5proSourceHandlerRtmp2.default(_this4, view.view, _this4.getType()); + _this4._glomSourceHandlerAPI(_this4._sourceHandler); + if (_this4._options) { + var dfd = _this4._embedPromise; + _this4._sourceHandler.addSource(_this4._elementId, _this4._options).then(function (subscriberId) { + _this4._establishExtIntHandlers(subscriberId); + dfd.resolve(_this4); + }).catch(function (err) { + return dfd.reject(err); + }); + } + }); + }; + + try { + _browser2.default.injectScript(this._options.swfobjectURL).then(function () { + var embedDfd = _this4._embedPromise; + (0, _log.debug)(NAME, 'SWFObject embedded.'); + if (_this4._sourceHandler) { + _this4._sourceHandler.addSource(_this4._elementId, _this4._options).then(function (subscriberId) { + _this4._establishExtIntHandlers(subscriberId); + embedDfd.resolve(_this4); + }).catch(function (err) { + embedDfd.reject(err); + }); + return _this4._getEmbedPromise(); + } + establishSourceHandler(); + return true; + }).then(function () { + _this4._setViewIfNotExist(_this4._view, _this4._options.mediaElementId); + deferred.resolve(_this4); + }).catch(function (err) { + (0, _log.error)(NAME, 'Could not embed Flash-based RTMP Player. Reason: ' + err); + if (_this4._sourceHandler) { + _this4._sourceHandler.disconnect(); + } + deferred.reject(err); + _this4.trigger(new _event.SubscriberEvent(_event.RTMPSubscriberEventTypes.EMBED_FAILURE, _this4)); + }); + } catch (e) { + deferred.reject('Could not inject Flash-based Player into the page. Reason: ' + e.message); + this.trigger(new _event.SubscriberEvent(_event.RTMPSubscriberEventTypes.EMBED_FAILURE, this)); + } + } + return deferred.promise; + } + + /** + * Still in use for assigning document element view management to this instance. + * API deprecated in 4.0.0. + * + * @private + */ + + }, { + key: 'setView', + value: function setView(view, elementId) { + this._view = view; + this._elementId = elementId; + this._viewResolver.resolve(this._view); + return this; + } + + /** + * Request to begin subscribing to a stream. + * + * @return {Promise} + * The returned `Promise` will resolve or reject on successful start of playback. + */ + + }, { + key: 'subscribe', + value: function subscribe() { + return this._getSubscriptionResolverPromise(); + } + + /** + * Request to stop a subscription. + * The returned `Promise` will either resolve or reject on successful stop of subscription. + * + * @return {Promise} + */ + + }, { + key: 'unsubscribe', + value: function unsubscribe() { + var _this5 = this; + + (0, _log.debug)(NAME, '[unsubscribe]'); + var cb = function cb(resolve, reject) { + try { + _this5._sourceHandler.disconnect(); + resolve(); + } catch (e) { + reject(e.message); + } + }; + return new _promise2.default(cb); + } + + /** + * Request to start playing the stream. + */ + + }, { + key: 'play', + value: function play() { + var _this6 = this; + + (0, _log.debug)(NAME, '[play]'); + this._getEmbedPromise().then(function () { + _this6._sourceHandler.play(); + }); + } + + /** + * Event handler for completion of embedding Flash element into page. + * + * @private + */ + + }, { + key: 'onEmbedComplete', + value: function onEmbedComplete() { + (0, _log.debug)(NAME, '[embed:complete]'); + this.trigger(new _event.SubscriberEvent(_event.RTMPSubscriberEventTypes.EMBED_SUCCESS, this)); + } + + /** + * Event handler for failure in embedding Flash element into page. + * + * @private + */ + + }, { + key: 'onEmbedFailure', + value: function onEmbedFailure(err) { + (0, _log.debug)(NAME, '[embed:failure] - ' + err); + this.trigger(new _event.SubscriberEvent(_event.RTMPSubscriberEventTypes.EMBED_FAILURE, this)); + } + + /** + * Returns connection handler for playback. + * Used in SharedObject communication. + * + * @return {Object} + * + * @private + */ + + }, { + key: 'getConnection', + value: function getConnection() { + return this._sourceHandler; + } + + /** + * Returns reference to playback controls if available. + * + * @return {PlaybackControls} + */ + + }, { + key: 'getControls', + value: function getControls() { + return this._sourceHandler ? this._sourceHandler.getControls() : undefined; + } + + /** + * Returns the initialization configuration used in `init()`. + * + * @return {Object} + */ + + }, { + key: 'getOptions', + value: function getOptions() { + return this._options; + } + + /** + * Returns the target view Element. + * + * @return {Element} + */ + + }, { + key: 'getPlayer', + value: function getPlayer() { + return this._sourceHandler ? this._sourceHandler.getEmbeddedView() : undefined; + } + + /** + * Returns the type of implementation: `RTMP`. + * + * @return {String} + */ + + }, { + key: 'getType', + value: function getType() { + return _playback3.PlaybackTypes.RTMP.toUpperCase(); + } + }]); + return RTMPSubscriber; +}(_controls.PlaybackController); + +exports.default = RTMPSubscriber; + +/***/ }), +/* 129 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _stringify = __webpack_require__(12); + +var _stringify2 = _interopRequireDefault(_stringify); + +var _isFinite = __webpack_require__(90); + +var _isFinite2 = _interopRequireDefault(_isFinite); + +var _getPrototypeOf = __webpack_require__(6); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = __webpack_require__(8); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = __webpack_require__(7); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _browser = __webpack_require__(4); + +var _browser2 = _interopRequireDefault(_browser); + +var _translationUtil = __webpack_require__(81); + +var _object = __webpack_require__(28); + +var _controls = __webpack_require__(24); + +var _state = __webpack_require__(35); + +var _event = __webpack_require__(15); + +var _promise = __webpack_require__(5); + +var _log = __webpack_require__(2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var NAME = 'HLSSourceHandler'; + +/** + * Source Handler for HLS-based Subscribers, which serves as a Presentation Controller between view and subscriber. + * + * @extends EventEmitter + * @extends SubscriberPlaybackController + * + * @private + */ + +var HLSSourceHandler = function (_PlaybackController) { + (0, _inherits3.default)(HLSSourceHandler, _PlaybackController); + + function HLSSourceHandler(media, type) { + (0, _classCallCheck3.default)(this, HLSSourceHandler); + + var _this = (0, _possibleConstructorReturn3.default)(this, (HLSSourceHandler.__proto__ || (0, _getPrototypeOf2.default)(HLSSourceHandler)).call(this)); + + _this.media = media; + _this.clone = _this.media.cloneNode(true); + _this.parent = _this.media.parentNode; + _this.holder = _this._determineHolder(media); + _this.playerType = type; + _this._isVOD = false; + _this._controls = undefined; + _this._playbackNotificationCenter = _this.media; + _browser2.default.onFullScreenStateChange(_this._handleFullScreenChange.bind(_this)); + return _this; + } + + /** + * Established DOM Element order for playback. + * + * @param {Element} media + * The target media element: e.g., `video` or `audio`. + * + * @private + */ + + + (0, _createClass3.default)(HLSSourceHandler, [{ + key: '_determineHolder', + value: function _determineHolder(media) { + if (media.parentNode.classList.contains('red5pro-media-container')) { + return media.parentNode; + } else { + var parent = media.parentNode; + var div = _browser2.default.createElement('div'); + div.classList.add('red5pro-media-container'); + parent.insertBefore(div, media); + parent.removeChild(media); + div.appendChild(media); + return div; + } + } + + /** + * Clean up of DOM Element order upon stop of playback. + * + * @private + */ + + }, { + key: '_cleanUp', + value: function _cleanUp() { + // Return to prior DOM manipulation. + var el = this.media; + var elParent = el.parentNode; + var mediaHolder = this.holder; + if (elParent) { + elParent.removeChild(el); + // The object parent could be a wrapper child in the original parent element. + if (elParent !== this.parent) { + elParent.parentNode.removeChild(elParent); + mediaHolder = this.parent; + } + } else { + try { + el.remove(); + } catch (e) { + warn(NAME, 'Issue in DOM cleanup of flash object embed: ' + e.message); + } + } + this.media = this.clone.cloneNode(true); + mediaHolder.appendChild(this.media); + if (this._controls) { + this._controls.detach(); + } + } + + /** + * Assigns and handlers event notificiations coming from the media notifier (e.g., `video` or `audio` element). + * + * @param {Object} notifier + * + * @private + */ + + }, { + key: '_addPlaybackHandlers', + value: function _addPlaybackHandlers(notifier) { + var _this2 = this; + + var controls = this.getControls(); + var hasControls = typeof controls !== 'undefined'; + + notifier.oncanplay = function () { + if (controls) { + controls.enable(true); + } + _this2.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.PLAYBACK_STATE_CHANGE, undefined, { + code: _state.PlaybackState.AVAILABLE, + state: _state.PlaybackStateReadable[_state.PlaybackState.AVAILABLE] + })); + _this2.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.VOLUME_CHANGE, undefined, { + volume: notifier.volume + })); + }; + notifier.ondurationchange = function (event) { + // eslint-disable-line no-unused-vars + if (!isNaN(notifier.duration) && (0, _isFinite2.default)(notifier.duration)) { + _this2.isVOD = true; + } + if (hasControls) { + controls.setPlaybackDuration(notifier.duration); + } + }; + notifier.onended = function () { + (0, _log.debug)(NAME, '[videoelement:onended]'); + if (hasControls) { + controls.setState(_state.PlaybackState.IDLE); + } + _this2.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.PLAYBACK_STATE_CHANGE, undefined, { + code: _state.PlaybackState.IDLE, + state: _state.PlaybackStateReadable[_state.PlaybackState.IDLE] + })); + }; + notifier.ontimeupdate = function (event) { + // eslint-disable-line no-unused-vars + if (hasControls) { + controls.setSeekTime(notifier.currentTime, self.isVOD ? notifier.duration : undefined); + } + _this2.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.PLAYBACK_TIME_UPDATE, undefined, { + time: notifier.currentTime, + duration: notifier.duration + })); + }; + notifier.onseeked = function (event) {// eslint-disable-line no-unused-vars + // debug(NAME, 'Seeked.') + }; + notifier.onseeking = function (event) {// eslint-disable-line no-unused-vars + // debug(NAME, 'Seeking.') + }; + notifier.onplay = function () { + if (hasControls) { + controls.setState(_state.PlaybackState.PLAYING); + } + _this2.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.PLAYBACK_STATE_CHANGE, undefined, { + code: _state.PlaybackState.PLAYING, + state: _state.PlaybackStateReadable[_state.PlaybackState.PLAYING] + })); + }; + notifier.onpause = function () { + if (hasControls) { + controls.setState(_state.PlaybackState.PAUSED); + } + _this2.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.PLAYBACK_STATE_CHANGE, undefined, { + code: _state.PlaybackState.PAUSED, + state: _state.PlaybackStateReadable[_state.PlaybackState.PAUSED] + })); + }; + notifier.onvolumechange = function (event) { + // eslint-disable-line no-unused-vars + if (hasControls && controls.getVolume() !== _this2.media.volume) { + controls.setVolume(_this2.media.volume); + } + _this2.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.VOLUME_CHANGE, undefined, { + volume: notifier.muted ? 0 : notifier.volume + })); + }; + // for debugging purposes. + notifier.onencrypted = function () { + (0, _log.debug)(NAME, '[videoelement:event] encrypted'); + }; + notifier.onemptied = function () { + (0, _log.debug)(NAME, '[videoelement:event] emptied'); + }; + notifier.onloadeddata = function () { + (0, _log.debug)(NAME, '[videoelement:event] loadeddata'); + }; + notifier.onloadedmetadata = function () { + (0, _log.debug)(NAME, '[videoelement:event] loadedmetadata'); + }; + notifier.onloadstart = function () { + (0, _log.debug)(NAME, '[videoelement:event] loadedstart'); + }; + notifier.onstalled = function () { + (0, _log.debug)(NAME, '[videoelement:event] stalled'); + }; + notifier.onsuspend = function () { + (0, _log.debug)(NAME, '[videoelement:event] suspend'); + }; + notifier.onwaiting = function () { + (0, _log.debug)(NAME, '[videoelement:event] waiting'); + }; + // notifier.onprogress = () => { debug(NAME, '[videoelement:event] progress. Played: ' + notifier.played.length + ', Buffered: ' + notifier.buffered.length + '.') } + } + + /** + * Event handler for change in fullscreen state. + * + * @param {Boolean} isFullScreen + * + * @private + */ + + }, { + key: '_handleFullScreenChange', + value: function _handleFullScreenChange(isFullScreen) { + if (isFullScreen) { + this.holder.classList.add('red5pro-media-container-full-screen'); + this.media.classList.add('red5pro-media-container-full-screen'); + } else { + this.holder.classList.remove('red5pro-media-container-full-screen'); + this.media.classList.remove('red5pro-media-container-full-screen'); + } + this.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.FULL_SCREEN_STATE_CHANGE, undefined, isFullScreen)); + } + + /** + * Define the source element on the HLS playback element. + * + * @param {String} url + * The playback endpoint URL. + * @param {String} type + * The mime type of the playback stream. + * @param {Object} options + * The initialization configuration map. + * + * @private + */ + + }, { + key: '_embedMediaSource', + value: function _embedMediaSource(url, type, options) { + // eslint-disable-line no-unused-vars + var self = this; + var deferred = new _promise.DeferredPromise(); + try { + var source = _browser2.default.createElement('source'); + source.type = type; + source.src = url; + if (this.media.firstChild) { + this.media.insertBefore(source, this.media.firstChild); + } else { + this.media.appendChild(source); + } + self.orientation = 0; + _browser2.default.onOrientationMetadata(this.media, function (metadata) { + (0, _log.debug)(NAME, 'Metadata received: ' + (0, _stringify2.default)(metadata, null, 2)); + if (self.orientation !== metadata.orientation) { + self.orientation = metadata.orientation; + if (options.autoLayoutOrientation) { + (0, _translationUtil.applyOrientation)(self.media, parseInt(metadata.orientation, 10), (0, _object.metadataResolutionToObject)(metadata.resolution)); + self.handleOrientationChange(parseInt(self.orientation)); + } + self.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.ORIENTATION_CHANGE, undefined, { + orientation: parseInt(self.orientation), + viewElement: self.media + })); + self.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.SUBSCRIBE_METADATA, undefined, metadata)); + } + self.orientation = metadata.orientation; + }); + deferred.resolve(); + } catch (e) { + deferred.reject(e.message); + } + return deferred.promise; + } + + /** + * Request to setup the presentation of a playback stream using HLS. + * + * @param {String} url + * The endpoint URL for playback. + * @param {String} type + * The mime type for playback. + * @param {Object} options + * The initialization configuration map. + * + * @returns {Promise} + */ + + }, { + key: 'addSource', + value: function addSource(url, type, options) { + var _this3 = this; + + (0, _log.debug)(NAME, '[addsource]'); + this.holder = this._determineHolder(this.media); + var deferred = new _promise.DeferredPromise(); + var hasDefinedControls = options.controls; + var isMuted = _browser2.default.hasAttributeDefined(this.media, 'muted'); + var usePlaybackControls = _browser2.default.hasAttributeDefined(this.media, 'controls') && _browser2.default.hasClassDefined(this.media, 'red5pro-media'); + this._embedMediaSource(url, type, options).then(function () { + if (hasDefinedControls || usePlaybackControls) { + if (hasDefinedControls) { + _this3._controls = options.controls; + } else { + _this3._controls = new _controls.PlaybackControlsImpl(_this3, _this3.holder); + } + _this3.media.controls = false; + _this3._controls.setAsVOD(_this3.isVOD); + _this3._controls.setMutedState(isMuted); + } + _this3._addPlaybackHandlers(_this3._playbackNotificationCenter); + deferred.resolve(); + }).catch(function (e) { + return deferred.reject(e); + }); + return deferred.promise; + } + + /** + * Request to connect to stream. + */ + + }, { + key: 'connect', + value: function connect() { + (0, _log.debug)(NAME, '[connect]'); + } + }, { + key: 'play', + value: function play() { + (0, _log.debug)(NAME, '[videoelement:action] play'); + try { + var maybePromise = this.media.play(); + if (maybePromise) { + maybePromise.then(function () { + return (0, _log.debug)(NAME, '[videoelement:action] play (START)'); + }).catch(function (err) { + return (0, _log.error)(NAME, '[videoelement:action] play (FAULT) ' + (err.message ? err.message : err)); + }); + } + } catch (e) { + (0, _log.error)(NAME, '[videoelement:action] play (FAULT) - ' + e.message); + } + } + }, { + key: 'pause', + value: function pause() { + (0, _log.debug)(NAME, '[videoelement:action] pause'); + try { + this.media.pause(); + } catch (e) { + (0, _log.debug)(NAME, '[videoelement:action] pause (FAULT) - ' + e.message); + } + } + }, { + key: 'resume', + value: function resume() { + (0, _log.debug)(NAME, '[videoelement:action] resume'); + try { + var maybePromise = this.media.play(); + if (maybePromise) { + maybePromise.then(function () { + return (0, _log.debug)(NAME, '[videoelement:action] play (START)'); + }).catch(function (err) { + return (0, _log.error)(NAME, '[videoelement:action] play (FAULT) ' + (err.message ? err.message : err)); + }); + } + } catch (e) { + (0, _log.error)(NAME, '[videoelement:action] resume (FAULT) - ' + e.message); + } + } + }, { + key: 'stop', + value: function stop() { + try { + this.media.stop(); + } catch (e) { + // ok. + } + } + }, { + key: 'mute', + value: function mute() { + this.media.muted = true; + } + }, { + key: 'unmute', + value: function unmute() { + this.media.muted = false; + } + }, { + key: 'setVolume', + value: function setVolume(value) { + this.unmute(); + this.media.volume = value; + } + }, { + key: 'seekTo', + value: function seekTo(percentage) { + var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + + this.media.currentTime = duration ? percentage * duration : percentage; + } + }, { + key: 'toggleFullScreen', + value: function toggleFullScreen() { + try { + _browser2.default.toggleFullScreen(this.holder); + } catch (e) { + throw e; + // nada. + } + } + + /** + * Notification of current stream being in an unpublished state. + * The stream enters an unpublished state when the broadcaster stop the stream and the subscriber is still connected. + */ + + }, { + key: 'unpublish', + value: function unpublish() { + try { + this.stop(); + this.media.onended.call(this.media); + } catch (e) { + // nada. + } + } + + /** + * Request to disconnect playback. + */ + + }, { + key: 'disconnect', + value: function disconnect() { + this._cleanUp(); + } + + /** + * Responder to change in orientation received through metadata. + * + * @param {Number} orientation + * The orientation value. + * + * @private + */ + + }, { + key: 'handleOrientationChange', + value: function handleOrientationChange(orientation) { + if (this._controls && orientation % 180 !== 0) { + this.holder.classList.add('red5pro-media-background'); + this.media.classList.remove('red5pro-media-background'); + } + } + + /* + * || SHARED OBJECT INTEGRATION NOT AVAILABLE FOR HLS PLAYBACK || + */ + // eslint-disable-next-line no-unused-vars + + }, { + key: 'addSharedObjectResponseHandler', + value: function addSharedObjectResponseHandler(handler) {} + + // eslint-disable-next-line no-unused-vars + + }, { + key: 'removeSharedObjectResponseHandler', + value: function removeSharedObjectResponseHandler(handler) {} + + // eslint-disable-next-line no-unused-vars + + }, { + key: 'sendToSharedObject', + value: function sendToSharedObject(name, callName, message) {} + + // eslint-disable-next-line no-unused-vars + + }, { + key: 'sendPropertyToSharedObject', + value: function sendPropertyToSharedObject(name, key, value) {} + + // eslint-disable-next-line no-unused-vars + + }, { + key: 'getRemoteSharedObject', + value: function getRemoteSharedObject(sharedObjectName) {} + + // eslint-disable-next-line no-unused-vars + + }, { + key: 'connectToSharedObject', + value: function connectToSharedObject(sharedObjectName) {} + + // eslint-disable-next-line no-unused-vars + + }, { + key: 'closeSharedObject', + value: function closeSharedObject(sharedObjectName) {} + + /** + * Returns playback controls if available. + * + * @returns {PlaybackControls} + */ + + }, { + key: 'getControls', + value: function getControls() { + return this._controls; + } + + /** + * Returns the subscriber type associated with this controller. + * + * @returns {String} + */ + + }, { + key: 'getType', + value: function getType() { + return this.playerType; + } + + /** + * Returns flag of video being recognized as VOD (Video On Demand). + * + * @returns {Boolean} + */ + + }, { + key: 'isVOD', + get: function get() { + return this._isVOD; + } + + /** + * Sets flag of video being considered as VOD (Video On Demand). + * + * @param {Boolean} value + */ + , + set: function set(value) { + this._isVOD = value; + if (this._controls) { + this._controls.setAsVOD(value); + } + } + }]); + return HLSSourceHandler; +}(_controls.PlaybackController); + +exports.default = HLSSourceHandler; + +/***/ }), +/* 130 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _isFinite = __webpack_require__(90); + +var _isFinite2 = _interopRequireDefault(_isFinite); + +var _getPrototypeOf = __webpack_require__(6); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = __webpack_require__(8); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = __webpack_require__(7); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _browser = __webpack_require__(4); + +var _browser2 = _interopRequireDefault(_browser); + +var _controls = __webpack_require__(24); + +var _state = __webpack_require__(35); + +var _event = __webpack_require__(15); + +var _promise = __webpack_require__(5); + +var _log = __webpack_require__(2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var NAME = 'RTCSourceHandler'; + +/** + * Source Handler for WebRTC-based Subscribers, which serves as a Presentation Controller between view and subscriber. + * + * @extends EventEmitter + * @extends SubscriberPlaybackController + * + * @private + */ + +var RTCSourceHandler = function (_PlaybackController) { + (0, _inherits3.default)(RTCSourceHandler, _PlaybackController); + + function RTCSourceHandler(media, type) { + (0, _classCallCheck3.default)(this, RTCSourceHandler); + + var _this = (0, _possibleConstructorReturn3.default)(this, (RTCSourceHandler.__proto__ || (0, _getPrototypeOf2.default)(RTCSourceHandler)).call(this)); + + _this.media = media; + _this.clone = _this.media.cloneNode(true); + _this.parent = _this.media.parentNode; + _this.holder = _this._determineHolder(_this.media); + _this.playerType = type; + _this._isVOD = false; + _this._controls = undefined; + _this._playbackNotificationCenter = _this.media; + _browser2.default.onFullScreenStateChange(_this._handleFullScreenChange.bind(_this)); + return _this; + } + + /** + * Established DOM Element order for playback. + * + * @param {Element} media + * The target media element: e.g., `video` or `audio`. + * + * @private + */ + + + (0, _createClass3.default)(RTCSourceHandler, [{ + key: '_determineHolder', + value: function _determineHolder(media) { + if (media.parentNode.classList.contains('red5pro-media-container')) { + return media.parentNode; + } else { + var parent = media.parentNode; + var div = _browser2.default.createElement('div'); + div.classList.add('red5pro-media-container'); + parent.insertBefore(div, media); + parent.removeChild(media); + div.appendChild(media); + return div; + } + } + + /** + * Established DOM Element order for playback. + * + * @param {Element} media + * The target media element: e.g., `video` or `audio`. + * + * @private + */ + + }, { + key: '_cleanUp', + value: function _cleanUp() { + // Return to prior DOM manipulation. + var el = this.media; + var elParent = el.parentNode; + var mediaHolder = this.holder; + if (elParent) { + elParent.removeChild(el); + // The object parent could be a wrapper child in the original parent element. + if (elParent !== this.parent) { + elParent.parentNode.removeChild(elParent); + mediaHolder = this.parent; + } + } else { + try { + el.remove(); + } catch (e) { + (0, _log.warn)(NAME, 'Issue in DOM cleanup of flash object embed: ' + e.message); + } + } + this.media = this.clone.cloneNode(true); + mediaHolder.appendChild(this.media); + if (this._controls) { + this._controls.detach(); + } + } + + /** + * Assigns and handlers event notificiations coming from the media notifier (e.g., `video` or `audio` element). + * + * @param {Object} notifier + * + * @private + */ + + }, { + key: '_addPlaybackHandlers', + value: function _addPlaybackHandlers(notifier) { + var _this2 = this; + + var controls = this.getControls(); + var hasControls = typeof controls !== 'undefined'; + + notifier.oncanplay = function () { + (0, _log.debug)(NAME, '[videoelement:event] canplay'); + if (controls) { + controls.enable(true); + } + _this2.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.PLAYBACK_STATE_CHANGE, undefined, { + code: _state.PlaybackState.AVAILABLE, + state: _state.PlaybackStateReadable[_state.PlaybackState.AVAILABLE] + })); + _this2.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.VOLUME_CHANGE, undefined, { + volume: notifier.volume + })); + }; + notifier.ondurationchange = function (event) { + // eslint-disable-line no-unused-vars + (0, _log.debug)(NAME, '[videoelement:event] durationchange'); + if (!isNaN(notifier.duration) && (0, _isFinite2.default)(notifier.duration)) { + _this2.isVOD = true; + } + if (hasControls) { + controls.setPlaybackDuration(notifier.duration); + } + }; + notifier.onended = function () { + (0, _log.debug)(NAME, '[videoelement:event] ended'); + if (hasControls) { + controls.setState(_state.PlaybackState.IDLE); + } + _this2.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.PLAYBACK_STATE_CHANGE, undefined, { + code: _state.PlaybackState.IDLE, + state: _state.PlaybackStateReadable[_state.PlaybackState.IDLE] + })); + }; + notifier.ontimeupdate = function (event) { + // eslint-disable-line no-unused-vars + if (hasControls) { + controls.setSeekTime(notifier.currentTime, self.isVOD ? notifier.duration : undefined); + } + _this2.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.PLAYBACK_TIME_UPDATE, undefined, { + time: notifier.currentTime, + duration: notifier.duration + })); + }; + notifier.onseeked = function (event) {// eslint-disable-line no-unused-vars + // debug(NAME, 'Seeked.') + }; + notifier.onseeking = function (event) {// eslint-disable-line no-unused-vars + // debug(NAME, 'Seeking.') + }; + notifier.onplay = function () { + (0, _log.debug)(NAME, '[videoelement:event] play'); + if (hasControls) { + controls.setState(_state.PlaybackState.PLAYING); + } + _this2.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.PLAYBACK_STATE_CHANGE, undefined, { + code: _state.PlaybackState.PLAYING, + state: _state.PlaybackStateReadable[_state.PlaybackState.PLAYING] + })); + }; + notifier.onpause = function () { + (0, _log.debug)(NAME, '[videoelement:event] pause'); + if (hasControls) { + controls.setState(_state.PlaybackState.PAUSED); + } + _this2.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.PLAYBACK_STATE_CHANGE, undefined, { + code: _state.PlaybackState.PAUSED, + state: _state.PlaybackStateReadable[_state.PlaybackState.PAUSED] + })); + }; + notifier.onvolumechange = function (event) { + // eslint-disable-line no-unused-vars + if (hasControls && controls.getVolume() !== _this2.media.volume) { + controls.setVolume(_this2.media.volume); + } + _this2.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.VOLUME_CHANGE, undefined, { + volume: notifier.muted ? 0 : notifier.volume + })); + }; + // for debugging purposes. + notifier.onencrypted = function () { + (0, _log.debug)(NAME, '[videoelement:event] encrypted'); + }; + notifier.onemptied = function () { + (0, _log.debug)(NAME, '[videoelement:event] emptied'); + }; + notifier.onloadeddata = function () { + (0, _log.debug)(NAME, '[videoelement:event] loadeddata'); + }; + notifier.onloadedmetadata = function () { + (0, _log.debug)(NAME, '[videoelement:event] loadedmetadata'); + }; + notifier.onloadstart = function () { + (0, _log.debug)(NAME, '[videoelement:event] loadedstart'); + }; + notifier.onstalled = function () { + (0, _log.debug)(NAME, '[videoelement:event] stalled'); + }; + notifier.onsuspend = function () { + (0, _log.debug)(NAME, '[videoelement:event] suspend'); + }; + notifier.onwaiting = function () { + (0, _log.debug)(NAME, '[videoelement:event] waiting'); + }; + // notifier.onprogress = () => { debug(NAME, '[videoelement:event] progress. Played: ' + notifier.played.length + ', Buffered: ' + notifier.buffered.length + '.') } + } + + /** + * Event handler for change in fullscreen state. + * + * @param {Boolean} isFullScreen + * + * @private + */ + + }, { + key: '_handleFullScreenChange', + value: function _handleFullScreenChange(isFullScreen) { + if (isFullScreen) { + this.holder.classList.add('red5pro-media-container-full-screen'); + this.media.classList.add('red5pro-media-container-full-screen'); + } else { + this.holder.classList.remove('red5pro-media-container-full-screen'); + this.media.classList.remove('red5pro-media-container-full-screen'); + } + this.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.FULL_SCREEN_STATE_CHANGE, undefined, isFullScreen)); + } + + /** + * Request to setup the presentation of a playback stream using WebRTC. + * + * @param {Object} options + * The initialization configuration map. + * + * @returns {Promise} + */ + + }, { + key: 'addSource', + value: function addSource(options) { + (0, _log.debug)(NAME, '[addsource]'); + this.holder = this._determineHolder(this.media); + var deferred = new _promise.DeferredPromise(); + var hasDefinedControls = options.controls; + var isMuted = _browser2.default.hasAttributeDefined(this.media, 'muted'); + var usePlaybackControls = _browser2.default.hasAttributeDefined(this.media, 'controls') && _browser2.default.hasClassDefined(this.media, 'red5pro-media'); + if (hasDefinedControls || usePlaybackControls) { + if (hasDefinedControls) { + this._controls = options.controls; + } else { + this._controls = new _controls.PlaybackControlsImpl(this, this.holder); + } + this.media.controls = false; + this._controls.setAsVOD(this.isVOD); + this._controls.setMutedState(isMuted); + } + this._addPlaybackHandlers(this._playbackNotificationCenter); + deferred.resolve(); + return deferred.promise; + } + + /** + * Request to connect to stream. + */ + + }, { + key: 'connect', + value: function connect() { + (0, _log.debug)(NAME, '[connect]'); + } + }, { + key: 'play', + value: function play() { + (0, _log.debug)(NAME, '[videoelement:action] play'); + try { + var maybePromise = this.media.play(); + if (maybePromise) { + maybePromise.then(function () { + return (0, _log.debug)(NAME, '[videoelement:action] play (START)'); + }).catch(function (err) { + return (0, _log.error)(NAME, '[videoelement:action] play (FAULT) ' + (err.message ? err.message : err)); + }); + } + } catch (e) { + (0, _log.error)(NAME, '[videoelement:action] play (FAULT) - ' + e.message); + } + } + }, { + key: 'pause', + value: function pause() { + (0, _log.debug)(NAME, '[videoelement:action] pause'); + try { + this.media.pause(); + } catch (e) { + (0, _log.warn)(NAME, '[videoelement:action] pause (CATCH::FAULT) - ' + e.message); + } + } + }, { + key: 'resume', + value: function resume() { + (0, _log.debug)(NAME, '[videoelement:action] resume'); + try { + var maybePromise = this.media.play(); + if (maybePromise) { + maybePromise.then(function () { + return (0, _log.debug)(NAME, '[videoelement:action] play (START)'); + }).catch(function (err) { + return (0, _log.warn)(NAME, '[videoelement:action] play (CATCH::FAULT) ' + (err.message ? err.message : err)); + }); + } + } catch (e) { + (0, _log.warn)(NAME, '[videoelement:action] resume (CATCH::FAULT) - ' + e.message); + } + } + }, { + key: 'stop', + value: function stop() { + (0, _log.debug)(NAME, '[videoelement:action] stop'); + try { + this.media.stop(); + } catch (e) { + // ok. + } + } + }, { + key: 'mute', + value: function mute() { + this.media.muted = true; + var controls = this.getControls(); + if (controls) { + controls.setMutedState(true); + } + } + }, { + key: 'unmute', + value: function unmute() { + this.media.muted = false; + var controls = this.getControls(); + if (controls) { + controls.setMutedState(false); + } + } + }, { + key: 'setVolume', + value: function setVolume(value) { + this.unmute(); + this.media.volume = value; + } + }, { + key: 'seekTo', + value: function seekTo(percentage) { + var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + + this.media.currentTime = duration ? percentage * duration : percentage; + } + }, { + key: 'toggleFullScreen', + value: function toggleFullScreen() { + try { + _browser2.default.toggleFullScreen(this.holder); + } catch (e) { + throw e; + // nada. + } + } + + /** + * Notification of current stream being in an unpublished state. + * The stream enters an unpublished state when the broadcaster stop the stream and the subscriber is still connected. + */ + + }, { + key: 'unpublish', + value: function unpublish() { + try { + this.stop(); + this.media.onended.call(this.media); + } catch (e) { + // nada. + } + } + + /** + * Request to disconnect playback. + */ + + }, { + key: 'disconnect', + value: function disconnect() { + this._cleanUp(); + } + + /** + * Responder to change in orientation received through metadata. + * + * @param {Number} orientation + * The orientation value. + * + * @private + */ + + }, { + key: 'handleOrientationChange', + value: function handleOrientationChange(orientation) { + if (this._controls && orientation % 180 !== 0) { + this.holder.classList.add('red5pro-media-background'); + this.media.classList.remove('red5pro-media-background'); + } + } + + /* + * || SHARED OBJECT INTEGRATION NOT AVAILABLE FOR HLS PLAYBACK || + */ + // eslint-disable-next-line no-unused-vars + + }, { + key: 'addSharedObjectResponseHandler', + value: function addSharedObjectResponseHandler(handler) {} + + // eslint-disable-next-line no-unused-vars + + }, { + key: 'removeSharedObjectResponseHandler', + value: function removeSharedObjectResponseHandler(handler) {} + + // eslint-disable-next-line no-unused-vars + + }, { + key: 'sendToSharedObject', + value: function sendToSharedObject(name, callName, message) {} + + // eslint-disable-next-line no-unused-vars + + }, { + key: 'sendPropertyToSharedObject', + value: function sendPropertyToSharedObject(name, key, value) {} + + // eslint-disable-next-line no-unused-vars + + }, { + key: 'getRemoteSharedObject', + value: function getRemoteSharedObject(sharedObjectName) {} + + // eslint-disable-next-line no-unused-vars + + }, { + key: 'connectToSharedObject', + value: function connectToSharedObject(sharedObjectName) {} + + // eslint-disable-next-line no-unused-vars + + }, { + key: 'closeSharedObject', + value: function closeSharedObject(sharedObjectName) {} + + /** + * Returns playback controls if available. + * + * @returns {PlaybackControls} + */ + + }, { + key: 'getControls', + value: function getControls() { + return this._controls; + } + + /** + * Returns the subscriber type associated with this controller. + * + * @returns {String} + */ + + }, { + key: 'getType', + value: function getType() { + return this.playerType; + } + + /** + * Returns flag of video being recognized as VOD (Video On Demand). + * + * @returns {Boolean} + */ + + }, { + key: 'isVOD', + get: function get() { + return this._isVOD; + } + + /** + * Sets flag of video being considered as VOD (Video On Demand). + * + * @param {Boolean} value + */ + , + set: function set(value) { + this._isVOD = value; + if (this._controls) { + this._controls.setAsVOD(value); + } + } + }]); + return RTCSourceHandler; +}(_controls.PlaybackController); + +exports.default = RTCSourceHandler; + +/***/ }), +/* 131 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _stringify = __webpack_require__(12); + +var _stringify2 = _interopRequireDefault(_stringify); + +var _getPrototypeOf = __webpack_require__(6); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = __webpack_require__(0); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = __webpack_require__(1); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = __webpack_require__(8); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = __webpack_require__(7); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _embed = __webpack_require__(80); + +var embed = _interopRequireWildcard(_embed); + +var _browser = __webpack_require__(4); + +var _browser2 = _interopRequireDefault(_browser); + +var _sharedobjectHelperRtmp = __webpack_require__(84); + +var _sharedobjectHelperRtmp2 = _interopRequireDefault(_sharedobjectHelperRtmp); + +var _controls = __webpack_require__(24); + +var _state = __webpack_require__(35); + +var _event = __webpack_require__(15); + +var _promise = __webpack_require__(5); + +var _log = __webpack_require__(2); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var NAME = 'RTMPSourceHandler'; + +/** + * Simple util to convert value to Integer. + * @private + */ +var toInt = function toInt(value) { + if (typeof value === 'string') { + return parseInt(value, 10); + } else { + return Math.round(value); + } +}; + +/** + * Quick test if streamName has an extension which infers VOD. + * @param {String} streamName + * @return {Boolean} + * @private + */ +var isVODStreamName = function isVODStreamName(streamName) { + return (/^.*\.(flv|mp4|mp3)/.test(streamName) + ); +}; + +/** + * Source Handler for Flash-based Subscribers, which serves as a Presentation Controller between view and subscriber. + * + * @extends EventEmitter + * @extends SubscriberPlaybackController + * + * @private + */ + +var RTMPSourceHandler = function (_PlaybackController) { + (0, _inherits3.default)(RTMPSourceHandler, _PlaybackController); + + function RTMPSourceHandler(notificationCenter, media, type) { + var soResponder = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : undefined; + (0, _classCallCheck3.default)(this, RTMPSourceHandler); + + var _this = (0, _possibleConstructorReturn3.default)(this, (RTMPSourceHandler.__proto__ || (0, _getPrototypeOf2.default)(RTMPSourceHandler)).call(this)); + + _this.media = media; + _this.clone = _this.media.cloneNode(true); + _this.parent = _this.media.parentNode; + _this.holder = _this._determineHolder(_this.media); + _this.playerType = type; + _this._swfId = undefined; + _this._controls = undefined; + _this._soResponder = soResponder || new _sharedobjectHelperRtmp2.default(); + _this._playbackNotificationCenter = notificationCenter; + _browser2.default.onFullScreenStateChange(_this._handleFullScreenChange.bind(_this)); + return _this; + } + + /** + * Established DOM Element order for playback. + * + * @param {Element} media + * The target media element: e.g., `video` or `audio`. + * + * @private + */ + + + (0, _createClass3.default)(RTMPSourceHandler, [{ + key: '_determineHolder', + value: function _determineHolder(media) { + if (media.parentNode.classList.contains('red5pro-media-container')) { + return media.parentNode; + } else { + var parent = media.parentNode; + var div = _browser2.default.createElement('div'); + div.classList.add('red5pro-media-container'); + parent.insertBefore(div, media); + parent.removeChild(media); + div.appendChild(media); + return div; + } + } + + /** + * Clean up of DOM Element order upon stop of playback. + * + * @private + */ + + }, { + key: '_cleanUp', + value: function _cleanUp() { + // Return to prior DOM manipulation. + var el = this.getEmbeddedView(); + var elParent = el.parentNode; + var mediaHolder = this.holder; + if (elParent) { + elParent.removeChild(el); + // The object parent could be a wrapper child in the original parent element. + if (elParent !== this.parent) { + elParent.parentNode.removeChild(elParent); + mediaHolder = this.parent; + } + } else { + try { + el.remove(); + } catch (e) { + (0, _log.warn)(NAME, 'Issue in DOM cleanup of flash object embed: ' + e.message); + } + } + this.media = this.clone.cloneNode(true); + mediaHolder.appendChild(this.media); + if (this._controls) { + this._controls.detach(); + } + } + + /** + * Assigns and handlers event notificiations coming from the media notifier (e.g., `video` or `audio` element). + * + * @param {Object} notifier + * + * @private + */ + + }, { + key: '_addPlaybackHandlers', + value: function _addPlaybackHandlers(notifier) { + var controls = this.getControls(); + if (typeof controls === 'undefined') { + return; + } + notifier.on(_event.SubscriberEventTypes.SUBSCRIBE_START, function () { + controls.setState(_state.PlaybackState.PLAYING); + }); + notifier.on(_event.SubscriberEventTypes.SUBSCRIBE_STOP, function () { + controls.setState(_state.PlaybackState.IDLE); + }); + notifier.on(_event.SubscriberEventTypes.PLAY_UNPUBLISH, function () { + controls.setState(_state.PlaybackState.IDLE); + }); + notifier.on(_event.SubscriberEventTypes.SUBSCRIBE_METADATA, function (event) { + if (event.data.duration) { + controls.setPlaybackDuration(event.data.duration); + } + }); + notifier.on(_event.SubscriberEventTypes.VOLUME_CHANGE, function (event) { + controls.setVolume(event.data.volume); + }); + notifier.on(_event.SubscriberEventTypes.PLAYBACK_STATE_CHANGE, function (event) { + if (event.data.code === _state.PlaybackState.AVAILABLE) { + controls.enable(true); + } + controls.setState(event.data.code); + }); + notifier.on(_event.SubscriberEventTypes.PLAYBACK_TIME_UPDATE, function (event) { + controls.setSeekTime(event.data.time, event.data.duration); + }); + notifier.on(_event.SubscriberEventTypes.FULL_SCREEN_STATE_CHANGE, function (event) { + controls.onFullScreenChange(event.data); + }); + } + + /** + * Event handler for change in fullscreen state. + * + * @param {Boolean} isFullScreen + * + * @private + */ + + }, { + key: '_handleFullScreenChange', + value: function _handleFullScreenChange(isFullScreen) { + var swfobject = this.getEmbeddedView(); + if (isFullScreen) { + this.holder.classList.add('red5pro-media-container-full-screen'); + swfobject.classList.add('red5pro-media-container-full-screen'); + } else { + this.holder.classList.remove('red5pro-media-container-full-screen'); + swfobject.classList.remove('red5pro-media-container-full-screen'); + } + this.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.FULL_SCREEN_STATE_CHANGE, undefined, isFullScreen)); + } + + /** + * Establishes event handler for recognizing complete on embed and initialization of Flash-based subscriber. + * + * @param {Promise} promise + * The target `Promise` object to resolve or reject upon completion. + * + * @private + */ + + }, { + key: '_setUpInitCallback', + value: function _setUpInitCallback(promise) { + var self = this; + _browser2.default.addSubscriptionAssignmentHandler(function (successId) { + (0, _log.debug)(NAME, 'Embed and init() complete for subscriber swf. successId(' + successId + ').'); + promise.resolve(successId); + self._tearDownInitCallback(); + }); + } + + /** + * Tears down established handler for completion of Flash embed and init. + * + * @private + */ + + }, { + key: '_tearDownInitCallback', + value: function _tearDownInitCallback() {} + + /** + * Request to setup the presentation of a playback stream using HLS. + * + * @param {String} url + * The endpoint URL for playback. + * @param {Object} options + * The initialization configuration map. + * @param {String} swfUrl + * The endpoint url to the SWF to embed. Defaults to relative link to red5pro-subscriber.swf of the SDK distribution. + * @param {String} minFlashVersion + * The minimum Flash version for support of playback. Default: `10.0.0`. + * + * @returns {Promise} + */ + + }, { + key: 'addSource', + value: function addSource(swfId, options) { + var _this2 = this; + + var swfUrl = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + var minFlashVersion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + + (0, _log.debug)(NAME, '[addsource]'); + this._swfId = swfId; + this.holder = this._determineHolder(this.media); + var soResponder = this._soResponder; + var deferred = new _promise.DeferredPromise(); + var hasDefinedControls = options.controls; + var isMuted = _browser2.default.hasAttributeDefined(this.media, 'muted'); + var usePlaybackControls = _browser2.default.hasAttributeDefined(this.media, 'controls') && _browser2.default.hasClassDefined(this.media, 'red5pro-media'); + options.swf = swfUrl || options.swf; + options.minFlashVersion = minFlashVersion || options.minFlashVersion; + this._setUpInitCallback(deferred); + var classList = this.media.classList; + embed.defineEmbedElement(this.media, this.holder).then(function (elementId) { + var flashvars = { + stream: options.streamName, + app: options.context ? options.app + '/' + options.context : options.app, + host: options.host, + muted: _browser2.default.hasAttributeDefined(_this2.media, 'muted'), + autoplay: _browser2.default.hasAttributeDefined(_this2.media, 'autoplay'), + useAdaptiveBitrateController: options.useAdaptiveBitrateController + }; + if (options.backgroundColor) { + flashvars.backgroundColor = options.backgroundColor; + } + if (options.buffer && !isNaN(Number(options.buffer))) { + flashvars.buffer = options.buffer; + } + if (options.width && !isNaN(options.width)) { + flashvars.width = toInt(options.width); + } + if (options.height && !isNaN(options.height)) { + flashvars.height = toInt(options.height); + } + if (options.embedWidth === '100%' || options.embedHeight === '100%') { + flashvars.autosize = true; + } + _this2._swfId = swfId; + if (typeof options.connectionParams !== 'undefined') { + flashvars.connectionParams = encodeURIComponent((0, _stringify2.default)(options.connectionParams)); + } + if (typeof options.abrVariants !== 'undefined') { + flashvars.abrVariants = encodeURIComponent((0, _stringify2.default)(options.abrVariants)); + } + if (typeof options.abrVariantUpgradeSettings !== 'undefined') { + flashvars.abrVariantUpgradeSettings = encodeURIComponent((0, _stringify2.default)(options.abrVariantUpgradeSettings)); + } + return embed.embedSwfObject(swfId, options, flashvars, _browser2.default.getSwfObject(), elementId); + }).then(function () { + if (hasDefinedControls || usePlaybackControls) { + if (hasDefinedControls) { + _this2._controls = options.controls; + } else { + _this2._controls = new _controls.PlaybackControlsImpl(_this2, _this2.holder); + } + _this2.media.controls = false; + _this2._controls.setAsVOD(isVODStreamName(options.streamName)); + _this2._controls.setMutedState(isMuted); + var embedded = _this2.getEmbeddedView(); + var index = classList.length, + clazz = void 0; + while (--index > -1) { + clazz = classList.item(index); + embedded.classList.add(clazz); + } + } + _this2._addPlaybackHandlers(_this2._playbackNotificationCenter); + _this2.trigger(new _event.SubscriberEvent(_event.SubscriberEventTypes.PLAYBACK_STATE_CHANGE, undefined, { + code: _state.PlaybackState.AVAILABLE, + state: _state.PlaybackStateReadable[_state.PlaybackState.AVAILABLE] + })); + return true; + }).then(function () { + soResponder.connect(swfId); + return true; + }).catch(function (e) { + return deferred.reject(e); + }); + return deferred.promise; + } + + /** + * Request to connect to stream. + */ + + }, { + key: 'connect', + value: function connect() { + (0, _log.debug)(NAME, '[connect]'); + try { + this.getEmbeddedView().connect(); + } catch (e) { + throw e; + } + } + }, { + key: 'play', + value: function play() { + try { + this.getEmbeddedView().play(); + } catch (e) { + throw e; + } + } + }, { + key: 'pause', + value: function pause() { + try { + this.getEmbeddedView().pause(); + } catch (e) { + throw e; + } + } + }, { + key: 'resume', + value: function resume() { + try { + this.getEmbeddedView().resume(); + } catch (e) { + throw e; + } + } + }, { + key: 'stop', + value: function stop() { + try { + this.getEmbeddedView().stop(); + } catch (e) { + throw e; + } + } + }, { + key: 'mute', + value: function mute() { + try { + this.getEmbeddedView().mute(); + } catch (e) { + throw e; + } + } + }, { + key: 'unmute', + value: function unmute() { + try { + this.getEmbeddedView().unmute(); + } catch (e) { + throw e; + } + } + }, { + key: 'setVolume', + value: function setVolume(value) { + try { + this.getEmbeddedView().setVolume(value); + } catch (e) { + throw e; + } + } + }, { + key: 'seekTo', + value: function seekTo(value) { + var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + + try { + this.getEmbeddedView().seekTo(value, duration); + } catch (e) { + throw e; + } + } + }, { + key: 'toggleFullScreen', + value: function toggleFullScreen() { + try { + _browser2.default.toggleFullScreen(this.holder); + } catch (e) { + throw e; + } + } + + /** + * Request to disconnect from the playback stream. + */ + + }, { + key: 'disconnect', + value: function disconnect() { + try { + this.getEmbeddedView().disconnect(); + (0, _log.debug)(NAME, '[disconnect]'); + } catch (e) { + // nada. + } + this._cleanUp(); + this._soResponder.disconnect(); + } + + /** + * Assign response handler for SharedObject communication. + * + * @param {Object} handler + * + * @private + */ + + }, { + key: 'addSharedObjectResponseHandler', + value: function addSharedObjectResponseHandler(handler) { + this._soResponder.addResponseHandler(handler); + } + + /** + * Remove response handler from SharedObject communication. + * + * @param {Object} handler + * + * @private + */ + + }, { + key: 'removeSharedObjectResponseHandler', + value: function removeSharedObjectResponseHandler(handler) { + this._soResponder.removeResponseHandler(handler); + } + + /** + * Send message on SharedObject. + * + * @param {String} name + * The name of the SharedObject. + * @param {String} callName + * The method name to invoke on the SharedObject. + * @param {String} message + * The message to send along. + * + * @private + */ + + }, { + key: 'sendToSharedObject', + value: function sendToSharedObject(name, callName, message) { + this._soResponder.sendToSharedObject(name, callName, message); + } + + /** + * Send property update to SharedObject. + * + * @param {String} name + * The name of the SharedObject. + * @param {String} key + * The property name to update. + * @param {String} value + * The property value to set. + * + * @private + */ + + }, { + key: 'sendPropertyToSharedObject', + value: function sendPropertyToSharedObject(name, key, value) { + this._soResponder.sendPropertyToSharedObject(name, key, value); + } + + /** + * Request to get the remote SharedObject on the server by name. + * + * @param {String} sharedObjectName + * + * @private + */ + + }, { + key: 'getRemoteSharedObject', + value: function getRemoteSharedObject(sharedObjectName) { + this._soResponder.getRemoteSharedObject(sharedObjectName); + } + + /** + * Request to connect to SharedObject by name. + * + * @param {String} sharedObjectName + * + * @private + */ + + }, { + key: 'connectToSharedObject', + value: function connectToSharedObject(sharedObjectName) { + this._soResponder.connectToSharedObject(sharedObjectName); + } + + /** + * Request to close the SharedObject by name. + * + * @param {String} sharedObjectName + * + * @private + */ + + }, { + key: 'closeSharedObject', + value: function closeSharedObject(sharedObjectName) { + this._soResponder.closeSharedObject(sharedObjectName); + } + + /* + * Request to start the Adaptive Bitrate Controller to automatically downgrade and upgrade streams based on NetStatus and bandwidth. + * The ABR is started automatically when providing the `useAdaptiveBitrateController` configuration property. + * + * NOTE: Adaptive Bitrate Controller API is only available when using Autoscale-Enabled Red5 Pro Server. + */ + + }, { + key: 'startABRController', + value: function startABRController() { + try { + this.getEmbeddedView().startABRController(); + } catch (e) { + (0, _log.debug)(NAME, 'Could not start the Adaptive Bitrate Controller: ' + e.message); + } + } + + /* + * Request to stop the Adaptive Bitrate Controller from automatically downgrading and upgrading streams based on NetStatus and bandwidth. + * + * NOTE: Adaptive Bitrate Controller API is only available when using Autoscale-Enabled Red5 Pro Server. + */ + + }, { + key: 'stopABRController', + value: function stopABRController() { + try { + this.getEmbeddedView().stopABRController(); + } catch (e) { + (0, _log.debug)(NAME, 'Could not stop the Adaptive Bitrate Controller: ' + e.message); + } + } + + /** + * Request to use the provide ABR Variants when performing Adaptive Bitrate Control. + * Requires the `useAdaptiveBitrateController` intitialization configuration property to be `true`. + * NOTE: Adaptive Bitrate Controller API is only available when using Autoscale-Enabled Red5 Pro Server. + * + * @param {Object} abrSettings + * TODO: Provide ABR Variant object schema expected. + * @param {int} level + * The level to start out on for ABR. + */ + + }, { + key: 'setABRVariants', + value: function setABRVariants(abrVariants, level) { + try { + var value = typeof abrVariants === 'string' ? encodeURIComponent(abrVariants) : encodeURIComponent((0, _stringify2.default)(abrVariants)); + this.getEmbeddedView().setABRVariants(value, level || 1); + } catch (e) { + (0, _log.debug)(NAME, 'Could not set ABR Variants: ' + e.message); + } + } + + /** + * Request to set ABR level explicitly. The SDK attempts to properly choose the correct level based on bandwidth, but this API allows for the level to be set explicitly. + * + * NOTE: Adaptive Bitrate Controller API is only available when using Autoscale-Enabled Red5 Pro Server. + * + * @param {int} level + * The level to set the ABR based on the variants provided in `setABRVariants`. + * @param {boolean} firm + * Flag to set level firmly, disabling the automatic switching of the Adaptive Bitrate Controller. + */ + + }, { + key: 'setABRLevel', + value: function setABRLevel(level, firm) { + try { + this.getEmbeddedView().setABRLevel(level, !!firm); + } catch (e) { + (0, _log.debug)(NAME, 'Could not set ABR level: ' + e.message); + } + } + + /** + * Provides the upgrade settings to use by the Adaptive Bitrate Control in upgrading previously downgraded streams. + * + * NOTE: Adaptive Bitrate Controller API is only available when using Autoscale-Enabled Red5 Pro Server. + * + * @param {Object} abrVariantUpgrades + * A configuration object that defines the associated retry limits based on levels of the Provision Variants. + * @example + * { + * minimumDowngradePlaybackSpan: 2000, + * upgrade: [ + * { + * level: 1, + * retryTimeout: 0 + * }, + * { + * level: 2, + * retryTimeout: 2000 + * }, + * { + * level: 3, + * retryTimeout: 4000 + * } + * ] + * } + */ + + }, { + key: 'setABRVariantUpgradeSettings', + value: function setABRVariantUpgradeSettings(abrVariantUpgrades) { + try { + var value = typeof abrVariants === 'string' ? encodeURIComponent(abrVariantUpgrades) : encodeURIComponent((0, _stringify2.default)(abrVariantUpgrades)); + this.getEmbeddedView().setABRVariantUpgradeSettings(value); + } catch (e) { + (0, _log.debug)(NAME, 'Could not set ABR Variants: ' + e.message); + } + } + + /** + * Returns the embedded Flash object if available. + * + * @returns {Element} + */ + + }, { + key: 'getEmbeddedView', + value: function getEmbeddedView() { + return _browser2.default.getEmbedObject(this._swfId); + } + + /** + * Returns playback controls if available. + * + * @returns {PlaybackControls} + */ + + }, { + key: 'getControls', + value: function getControls() { + return this._controls; + } + + /** + * Returns the subscriber type associated with this controller. + * + * @returns {String} + */ + + }, { + key: 'getType', + value: function getType() { + return this.playerType; + } + }]); + return RTMPSourceHandler; +}(_controls.PlaybackController); + +exports.default = RTMPSourceHandler; + +/***/ }), +/* 132 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = { "default": __webpack_require__(145), __esModule: true }; + +/***/ }), +/* 133 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = { "default": __webpack_require__(146), __esModule: true }; + +/***/ }), +/* 134 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = { "default": __webpack_require__(147), __esModule: true }; + +/***/ }), +/* 135 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = { "default": __webpack_require__(151), __esModule: true }; + +/***/ }), +/* 136 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = { "default": __webpack_require__(152), __esModule: true }; + +/***/ }), +/* 137 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = { "default": __webpack_require__(153), __esModule: true }; + +/***/ }), +/* 138 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = { "default": __webpack_require__(156), __esModule: true }; + +/***/ }), +/* 139 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = { "default": __webpack_require__(159), __esModule: true }; + +/***/ }), +/* 140 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = { "default": __webpack_require__(162), __esModule: true }; + +/***/ }), +/* 141 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = { "default": __webpack_require__(163), __esModule: true }; + +/***/ }), +/* 142 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = { "default": __webpack_require__(164), __esModule: true }; + +/***/ }), +/* 143 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +exports.__esModule = true; + +var _isIterable2 = __webpack_require__(134); + +var _isIterable3 = _interopRequireDefault(_isIterable2); + +var _getIterator2 = __webpack_require__(133); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = function () { + function sliceIterator(arr, i) { + var _arr = []; + var _n = true; + var _d = false; + var _e = undefined; + + try { + for (var _i = (0, _getIterator3.default)(arr), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"]) _i["return"](); + } finally { + if (_d) throw _e; + } + } + + return _arr; + } + + return function (arr, i) { + if (Array.isArray(arr)) { + return arr; + } else if ((0, _isIterable3.default)(Object(arr))) { + return sliceIterator(arr, i); + } else { + throw new TypeError("Invalid attempt to destructure non-iterable instance"); + } + }; +}(); + +/***/ }), +/* 144 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = __webpack_require__(206); + + +/***/ }), +/* 145 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(26); +__webpack_require__(185); +module.exports = __webpack_require__(3).Array.from; + +/***/ }), +/* 146 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(27); +__webpack_require__(26); +module.exports = __webpack_require__(183); + +/***/ }), +/* 147 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(27); +__webpack_require__(26); +module.exports = __webpack_require__(184); + +/***/ }), +/* 148 */ +/***/ (function(module, exports, __webpack_require__) { + +var core = __webpack_require__(3) + , $JSON = core.JSON || (core.JSON = {stringify: JSON.stringify}); +module.exports = function stringify(it){ // eslint-disable-line no-unused-vars + return $JSON.stringify.apply($JSON, arguments); +}; + +/***/ }), +/* 149 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(40); +__webpack_require__(26); +__webpack_require__(27); +__webpack_require__(187); +__webpack_require__(202); +module.exports = __webpack_require__(3).Map; + +/***/ }), +/* 150 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(188); +module.exports = __webpack_require__(3).Number.isFinite; + +/***/ }), +/* 151 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(189); +module.exports = __webpack_require__(3).Number.isNaN; + +/***/ }), +/* 152 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(190); +module.exports = __webpack_require__(3).Object.assign; + +/***/ }), +/* 153 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(191); +var $Object = __webpack_require__(3).Object; +module.exports = function create(P, D){ + return $Object.create(P, D); +}; + +/***/ }), +/* 154 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(192); +var $Object = __webpack_require__(3).Object; +module.exports = function defineProperty(it, key, desc){ + return $Object.defineProperty(it, key, desc); +}; + +/***/ }), +/* 155 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(193); +module.exports = __webpack_require__(3).Object.freeze; + +/***/ }), +/* 156 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(194); +var $Object = __webpack_require__(3).Object; +module.exports = function getOwnPropertyDescriptor(it, key){ + return $Object.getOwnPropertyDescriptor(it, key); +}; + +/***/ }), +/* 157 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(195); +module.exports = __webpack_require__(3).Object.getPrototypeOf; + +/***/ }), +/* 158 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(196); +module.exports = __webpack_require__(3).Object.keys; + +/***/ }), +/* 159 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(197); +module.exports = __webpack_require__(3).Object.setPrototypeOf; + +/***/ }), +/* 160 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(40); +__webpack_require__(26); +__webpack_require__(27); +__webpack_require__(198); +module.exports = __webpack_require__(3).Promise; + +/***/ }), +/* 161 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(40); +__webpack_require__(26); +__webpack_require__(27); +__webpack_require__(199); +__webpack_require__(203); +module.exports = __webpack_require__(3).Set; + +/***/ }), +/* 162 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(200); +__webpack_require__(40); +__webpack_require__(204); +__webpack_require__(205); +module.exports = __webpack_require__(3).Symbol; + +/***/ }), +/* 163 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(26); +__webpack_require__(27); +module.exports = __webpack_require__(78).f('iterator'); + +/***/ }), +/* 164 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(40); +__webpack_require__(27); +__webpack_require__(201); +module.exports = __webpack_require__(3).WeakMap; + +/***/ }), +/* 165 */ +/***/ (function(module, exports) { + +module.exports = function(){ /* empty */ }; + +/***/ }), +/* 166 */ +/***/ (function(module, exports, __webpack_require__) { + +var forOf = __webpack_require__(37); + +module.exports = function(iter, ITERATOR){ + var result = []; + forOf(iter, false, result.push, result, ITERATOR); + return result; +}; + + +/***/ }), +/* 167 */ +/***/ (function(module, exports, __webpack_require__) { + +// false -> Array#indexOf +// true -> Array#includes +var toIObject = __webpack_require__(22) + , toLength = __webpack_require__(52) + , toIndex = __webpack_require__(182); +module.exports = function(IS_INCLUDES){ + return function($this, el, fromIndex){ + var O = toIObject($this) + , length = toLength(O.length) + , index = toIndex(fromIndex, length) + , value; + // Array#includes uses SameValueZero equality algorithm + if(IS_INCLUDES && el != el)while(length > index){ + value = O[index++]; + if(value != value)return true; + // Array#toIndex ignores holes, Array#includes - not + } else for(;length > index; index++)if(IS_INCLUDES || index in O){ + if(O[index] === el)return IS_INCLUDES || index || 0; + } return !IS_INCLUDES && -1; + }; +}; + +/***/ }), +/* 168 */ +/***/ (function(module, exports, __webpack_require__) { + +var isObject = __webpack_require__(13) + , isArray = __webpack_require__(101) + , SPECIES = __webpack_require__(9)('species'); + +module.exports = function(original){ + var C; + if(isArray(original)){ + C = original.constructor; + // cross-realm fallback + if(typeof C == 'function' && (C === Array || isArray(C.prototype)))C = undefined; + if(isObject(C)){ + C = C[SPECIES]; + if(C === null)C = undefined; + } + } return C === undefined ? Array : C; +}; + +/***/ }), +/* 169 */ +/***/ (function(module, exports, __webpack_require__) { + +// 9.4.2.3 ArraySpeciesCreate(originalArray, length) +var speciesConstructor = __webpack_require__(168); + +module.exports = function(original, length){ + return new (speciesConstructor(original))(length); +}; + +/***/ }), +/* 170 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var redefineAll = __webpack_require__(51) + , getWeak = __webpack_require__(31).getWeak + , anObject = __webpack_require__(16) + , isObject = __webpack_require__(13) + , anInstance = __webpack_require__(44) + , forOf = __webpack_require__(37) + , createArrayMethod = __webpack_require__(64) + , $has = __webpack_require__(20) + , arrayFind = createArrayMethod(5) + , arrayFindIndex = createArrayMethod(6) + , id = 0; + +// fallback for uncaught frozen keys +var uncaughtFrozenStore = function(that){ + return that._l || (that._l = new UncaughtFrozenStore); +}; +var UncaughtFrozenStore = function(){ + this.a = []; +}; +var findUncaughtFrozen = function(store, key){ + return arrayFind(store.a, function(it){ + return it[0] === key; + }); +}; +UncaughtFrozenStore.prototype = { + get: function(key){ + var entry = findUncaughtFrozen(this, key); + if(entry)return entry[1]; + }, + has: function(key){ + return !!findUncaughtFrozen(this, key); + }, + set: function(key, value){ + var entry = findUncaughtFrozen(this, key); + if(entry)entry[1] = value; + else this.a.push([key, value]); + }, + 'delete': function(key){ + var index = arrayFindIndex(this.a, function(it){ + return it[0] === key; + }); + if(~index)this.a.splice(index, 1); + return !!~index; + } +}; + +module.exports = { + getConstructor: function(wrapper, NAME, IS_MAP, ADDER){ + var C = wrapper(function(that, iterable){ + anInstance(that, C, NAME, '_i'); + that._i = id++; // collection id + that._l = undefined; // leak store for uncaught frozen objects + if(iterable != undefined)forOf(iterable, IS_MAP, that[ADDER], that); + }); + redefineAll(C.prototype, { + // 23.3.3.2 WeakMap.prototype.delete(key) + // 23.4.3.3 WeakSet.prototype.delete(value) + 'delete': function(key){ + if(!isObject(key))return false; + var data = getWeak(key); + if(data === true)return uncaughtFrozenStore(this)['delete'](key); + return data && $has(data, this._i) && delete data[this._i]; + }, + // 23.3.3.4 WeakMap.prototype.has(key) + // 23.4.3.4 WeakSet.prototype.has(value) + has: function has(key){ + if(!isObject(key))return false; + var data = getWeak(key); + if(data === true)return uncaughtFrozenStore(this).has(key); + return data && $has(data, this._i); + } + }); + return C; + }, + def: function(that, key, value){ + var data = getWeak(anObject(key), true); + if(data === true)uncaughtFrozenStore(that).set(key, value); + else data[that._i] = value; + return that; + }, + ufstore: uncaughtFrozenStore +}; + +/***/ }), +/* 171 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var $defineProperty = __webpack_require__(14) + , createDesc = __webpack_require__(38); + +module.exports = function(object, index, value){ + if(index in object)$defineProperty.f(object, index, createDesc(0, value)); + else object[index] = value; +}; + +/***/ }), +/* 172 */ +/***/ (function(module, exports, __webpack_require__) { + +// all enumerable object keys, includes symbols +var getKeys = __webpack_require__(32) + , gOPS = __webpack_require__(71) + , pIE = __webpack_require__(49); +module.exports = function(it){ + var result = getKeys(it) + , getSymbols = gOPS.f; + if(getSymbols){ + var symbols = getSymbols(it) + , isEnum = pIE.f + , i = 0 + , key; + while(symbols.length > i)if(isEnum.call(it, key = symbols[i++]))result.push(key); + } return result; +}; + +/***/ }), +/* 173 */ +/***/ (function(module, exports) { + +// fast apply, http://jsperf.lnkit.com/fast-apply/5 +module.exports = function(fn, args, that){ + var un = that === undefined; + switch(args.length){ + case 0: return un ? fn() + : fn.call(that); + case 1: return un ? fn(args[0]) + : fn.call(that, args[0]); + case 2: return un ? fn(args[0], args[1]) + : fn.call(that, args[0], args[1]); + case 3: return un ? fn(args[0], args[1], args[2]) + : fn.call(that, args[0], args[1], args[2]); + case 4: return un ? fn(args[0], args[1], args[2], args[3]) + : fn.call(that, args[0], args[1], args[2], args[3]); + } return fn.apply(that, args); +}; + +/***/ }), +/* 174 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var create = __webpack_require__(48) + , descriptor = __webpack_require__(38) + , setToStringTag = __webpack_require__(39) + , IteratorPrototype = {}; + +// 25.1.2.1.1 %IteratorPrototype%[@@iterator]() +__webpack_require__(21)(IteratorPrototype, __webpack_require__(9)('iterator'), function(){ return this; }); + +module.exports = function(Constructor, NAME, next){ + Constructor.prototype = create(IteratorPrototype, {next: descriptor(1, next)}); + setToStringTag(Constructor, NAME + ' Iterator'); +}; + +/***/ }), +/* 175 */ +/***/ (function(module, exports, __webpack_require__) { + +var getKeys = __webpack_require__(32) + , toIObject = __webpack_require__(22); +module.exports = function(object, el){ + var O = toIObject(object) + , keys = getKeys(O) + , length = keys.length + , index = 0 + , key; + while(length > index)if(O[key = keys[index++]] === el)return key; +}; + +/***/ }), +/* 176 */ +/***/ (function(module, exports, __webpack_require__) { + +var global = __webpack_require__(11) + , macrotask = __webpack_require__(110).set + , Observer = global.MutationObserver || global.WebKitMutationObserver + , process = global.process + , Promise = global.Promise + , isNode = __webpack_require__(36)(process) == 'process'; + +module.exports = function(){ + var head, last, notify; + + var flush = function(){ + var parent, fn; + if(isNode && (parent = process.domain))parent.exit(); + while(head){ + fn = head.fn; + head = head.next; + try { + fn(); + } catch(e){ + if(head)notify(); + else last = undefined; + throw e; + } + } last = undefined; + if(parent)parent.enter(); + }; + + // Node.js + if(isNode){ + notify = function(){ + process.nextTick(flush); + }; + // browsers with MutationObserver + } else if(Observer){ + var toggle = true + , node = document.createTextNode(''); + new Observer(flush).observe(node, {characterData: true}); // eslint-disable-line no-new + notify = function(){ + node.data = toggle = !toggle; + }; + // environments with maybe non-completely correct, but existent Promise + } else if(Promise && Promise.resolve){ + var promise = Promise.resolve(); + notify = function(){ + promise.then(flush); + }; + // for other environments - macrotask based on: + // - setImmediate + // - MessageChannel + // - window.postMessag + // - onreadystatechange + // - setTimeout + } else { + notify = function(){ + // strange IE + webpack dev server bug - use .call(global) + macrotask.call(global, flush); + }; + } + + return function(fn){ + var task = {fn: fn, next: undefined}; + if(last)last.next = task; + if(!head){ + head = task; + notify(); + } last = task; + }; +}; + +/***/ }), +/* 177 */ +/***/ (function(module, exports, __webpack_require__) { + +var dP = __webpack_require__(14) + , anObject = __webpack_require__(16) + , getKeys = __webpack_require__(32); + +module.exports = __webpack_require__(17) ? Object.defineProperties : function defineProperties(O, Properties){ + anObject(O); + var keys = getKeys(Properties) + , length = keys.length + , i = 0 + , P; + while(length > i)dP.f(O, P = keys[i++], Properties[P]); + return O; +}; + +/***/ }), +/* 178 */ +/***/ (function(module, exports, __webpack_require__) { + +// fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window +var toIObject = __webpack_require__(22) + , gOPN = __webpack_require__(106).f + , toString = {}.toString; + +var windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames + ? Object.getOwnPropertyNames(window) : []; + +var getWindowNames = function(it){ + try { + return gOPN(it); + } catch(e){ + return windowNames.slice(); + } +}; + +module.exports.f = function getOwnPropertyNames(it){ + return windowNames && toString.call(it) == '[object Window]' ? getWindowNames(it) : gOPN(toIObject(it)); +}; + + +/***/ }), +/* 179 */ +/***/ (function(module, exports, __webpack_require__) { + +// Works with __proto__ only. Old v8 can't work with null proto objects. +/* eslint-disable no-proto */ +var isObject = __webpack_require__(13) + , anObject = __webpack_require__(16); +var check = function(O, proto){ + anObject(O); + if(!isObject(proto) && proto !== null)throw TypeError(proto + ": can't set as prototype!"); +}; +module.exports = { + set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line + function(test, buggy, set){ + try { + set = __webpack_require__(19)(Function.call, __webpack_require__(70).f(Object.prototype, '__proto__').set, 2); + set(test, []); + buggy = !(test instanceof Array); + } catch(e){ buggy = true; } + return function setPrototypeOf(O, proto){ + check(O, proto); + if(buggy)O.__proto__ = proto; + else set(O, proto); + return O; + }; + }({}, false) : undefined), + check: check +}; + +/***/ }), +/* 180 */ +/***/ (function(module, exports, __webpack_require__) { + +// 7.3.20 SpeciesConstructor(O, defaultConstructor) +var anObject = __webpack_require__(16) + , aFunction = __webpack_require__(63) + , SPECIES = __webpack_require__(9)('species'); +module.exports = function(O, D){ + var C = anObject(O).constructor, S; + return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S); +}; + +/***/ }), +/* 181 */ +/***/ (function(module, exports, __webpack_require__) { + +var toInteger = __webpack_require__(75) + , defined = __webpack_require__(46); +// true -> String#at +// false -> String#codePointAt +module.exports = function(TO_STRING){ + return function(that, pos){ + var s = String(defined(that)) + , i = toInteger(pos) + , l = s.length + , a, b; + if(i < 0 || i >= l)return TO_STRING ? '' : undefined; + a = s.charCodeAt(i); + return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff + ? TO_STRING ? s.charAt(i) : a + : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000; + }; +}; + +/***/ }), +/* 182 */ +/***/ (function(module, exports, __webpack_require__) { + +var toInteger = __webpack_require__(75) + , max = Math.max + , min = Math.min; +module.exports = function(index, length){ + index = toInteger(index); + return index < 0 ? max(index + length, 0) : min(index, length); +}; + +/***/ }), +/* 183 */ +/***/ (function(module, exports, __webpack_require__) { + +var anObject = __webpack_require__(16) + , get = __webpack_require__(79); +module.exports = __webpack_require__(3).getIterator = function(it){ + var iterFn = get(it); + if(typeof iterFn != 'function')throw TypeError(it + ' is not iterable!'); + return anObject(iterFn.call(it)); +}; + +/***/ }), +/* 184 */ +/***/ (function(module, exports, __webpack_require__) { + +var classof = __webpack_require__(45) + , ITERATOR = __webpack_require__(9)('iterator') + , Iterators = __webpack_require__(30); +module.exports = __webpack_require__(3).isIterable = function(it){ + var O = Object(it); + return O[ITERATOR] !== undefined + || '@@iterator' in O + || Iterators.hasOwnProperty(classof(O)); +}; + +/***/ }), +/* 185 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var ctx = __webpack_require__(19) + , $export = __webpack_require__(10) + , toObject = __webpack_require__(33) + , call = __webpack_require__(102) + , isArrayIter = __webpack_require__(100) + , toLength = __webpack_require__(52) + , createProperty = __webpack_require__(171) + , getIterFn = __webpack_require__(79); + +$export($export.S + $export.F * !__webpack_require__(103)(function(iter){ Array.from(iter); }), 'Array', { + // 22.1.2.1 Array.from(arrayLike, mapfn = undefined, thisArg = undefined) + from: function from(arrayLike/*, mapfn = undefined, thisArg = undefined*/){ + var O = toObject(arrayLike) + , C = typeof this == 'function' ? this : Array + , aLen = arguments.length + , mapfn = aLen > 1 ? arguments[1] : undefined + , mapping = mapfn !== undefined + , index = 0 + , iterFn = getIterFn(O) + , length, result, step, iterator; + if(mapping)mapfn = ctx(mapfn, aLen > 2 ? arguments[2] : undefined, 2); + // if object isn't iterable or it's array with default iterator - use simple case + if(iterFn != undefined && !(C == Array && isArrayIter(iterFn))){ + for(iterator = iterFn.call(O), result = new C; !(step = iterator.next()).done; index++){ + createProperty(result, index, mapping ? call(iterator, mapfn, [step.value, index], true) : step.value); + } + } else { + length = toLength(O.length); + for(result = new C(length); length > index; index++){ + createProperty(result, index, mapping ? mapfn(O[index], index) : O[index]); + } + } + result.length = index; + return result; + } +}); + + +/***/ }), +/* 186 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var addToUnscopables = __webpack_require__(165) + , step = __webpack_require__(104) + , Iterators = __webpack_require__(30) + , toIObject = __webpack_require__(22); + +// 22.1.3.4 Array.prototype.entries() +// 22.1.3.13 Array.prototype.keys() +// 22.1.3.29 Array.prototype.values() +// 22.1.3.30 Array.prototype[@@iterator]() +module.exports = __webpack_require__(69)(Array, 'Array', function(iterated, kind){ + this._t = toIObject(iterated); // target + this._i = 0; // next index + this._k = kind; // kind +// 22.1.5.2.1 %ArrayIteratorPrototype%.next() +}, function(){ + var O = this._t + , kind = this._k + , index = this._i++; + if(!O || index >= O.length){ + this._t = undefined; + return step(1); + } + if(kind == 'keys' )return step(0, index); + if(kind == 'values')return step(0, O[index]); + return step(0, [index, O[index]]); +}, 'values'); + +// argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7) +Iterators.Arguments = Iterators.Array; + +addToUnscopables('keys'); +addToUnscopables('values'); +addToUnscopables('entries'); + +/***/ }), +/* 187 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var strong = __webpack_require__(96); + +// 23.1 Map Objects +module.exports = __webpack_require__(65)('Map', function(get){ + return function Map(){ return get(this, arguments.length > 0 ? arguments[0] : undefined); }; +}, { + // 23.1.3.6 Map.prototype.get(key) + get: function get(key){ + var entry = strong.getEntry(this, key); + return entry && entry.v; + }, + // 23.1.3.9 Map.prototype.set(key, value) + set: function set(key, value){ + return strong.def(this, key === 0 ? 0 : key, value); + } +}, strong, true); + +/***/ }), +/* 188 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.1.2.2 Number.isFinite(number) +var $export = __webpack_require__(10) + , _isFinite = __webpack_require__(11).isFinite; + +$export($export.S, 'Number', { + isFinite: function isFinite(it){ + return typeof it == 'number' && _isFinite(it); + } +}); + +/***/ }), +/* 189 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.1.2.4 Number.isNaN(number) +var $export = __webpack_require__(10); + +$export($export.S, 'Number', { + isNaN: function isNaN(number){ + return number != number; + } +}); + +/***/ }), +/* 190 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.3.1 Object.assign(target, source) +var $export = __webpack_require__(10); + +$export($export.S + $export.F, 'Object', {assign: __webpack_require__(105)}); + +/***/ }), +/* 191 */ +/***/ (function(module, exports, __webpack_require__) { + +var $export = __webpack_require__(10) +// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) +$export($export.S, 'Object', {create: __webpack_require__(48)}); + +/***/ }), +/* 192 */ +/***/ (function(module, exports, __webpack_require__) { + +var $export = __webpack_require__(10); +// 19.1.2.4 / 15.2.3.6 Object.defineProperty(O, P, Attributes) +$export($export.S + $export.F * !__webpack_require__(17), 'Object', {defineProperty: __webpack_require__(14).f}); + +/***/ }), +/* 193 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.5 Object.freeze(O) +var isObject = __webpack_require__(13) + , meta = __webpack_require__(31).onFreeze; + +__webpack_require__(50)('freeze', function($freeze){ + return function freeze(it){ + return $freeze && isObject(it) ? $freeze(meta(it)) : it; + }; +}); + +/***/ }), +/* 194 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.6 Object.getOwnPropertyDescriptor(O, P) +var toIObject = __webpack_require__(22) + , $getOwnPropertyDescriptor = __webpack_require__(70).f; + +__webpack_require__(50)('getOwnPropertyDescriptor', function(){ + return function getOwnPropertyDescriptor(it, key){ + return $getOwnPropertyDescriptor(toIObject(it), key); + }; +}); + +/***/ }), +/* 195 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.9 Object.getPrototypeOf(O) +var toObject = __webpack_require__(33) + , $getPrototypeOf = __webpack_require__(107); + +__webpack_require__(50)('getPrototypeOf', function(){ + return function getPrototypeOf(it){ + return $getPrototypeOf(toObject(it)); + }; +}); + +/***/ }), +/* 196 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.14 Object.keys(O) +var toObject = __webpack_require__(33) + , $keys = __webpack_require__(32); + +__webpack_require__(50)('keys', function(){ + return function keys(it){ + return $keys(toObject(it)); + }; +}); + +/***/ }), +/* 197 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.3.19 Object.setPrototypeOf(O, proto) +var $export = __webpack_require__(10); +$export($export.S, 'Object', {setPrototypeOf: __webpack_require__(179).set}); + +/***/ }), +/* 198 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var LIBRARY = __webpack_require__(47) + , global = __webpack_require__(11) + , ctx = __webpack_require__(19) + , classof = __webpack_require__(45) + , $export = __webpack_require__(10) + , isObject = __webpack_require__(13) + , aFunction = __webpack_require__(63) + , anInstance = __webpack_require__(44) + , forOf = __webpack_require__(37) + , speciesConstructor = __webpack_require__(180) + , task = __webpack_require__(110).set + , microtask = __webpack_require__(176)() + , PROMISE = 'Promise' + , TypeError = global.TypeError + , process = global.process + , $Promise = global[PROMISE] + , process = global.process + , isNode = classof(process) == 'process' + , empty = function(){ /* empty */ } + , Internal, GenericPromiseCapability, Wrapper; + +var USE_NATIVE = !!function(){ + try { + // correct subclassing with @@species support + var promise = $Promise.resolve(1) + , FakePromise = (promise.constructor = {})[__webpack_require__(9)('species')] = function(exec){ exec(empty, empty); }; + // unhandled rejections tracking support, NodeJS Promise without it fails @@species test + return (isNode || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise; + } catch(e){ /* empty */ } +}(); + +// helpers +var sameConstructor = function(a, b){ + // with library wrapper special case + return a === b || a === $Promise && b === Wrapper; +}; +var isThenable = function(it){ + var then; + return isObject(it) && typeof (then = it.then) == 'function' ? then : false; +}; +var newPromiseCapability = function(C){ + return sameConstructor($Promise, C) + ? new PromiseCapability(C) + : new GenericPromiseCapability(C); +}; +var PromiseCapability = GenericPromiseCapability = function(C){ + var resolve, reject; + this.promise = new C(function($$resolve, $$reject){ + if(resolve !== undefined || reject !== undefined)throw TypeError('Bad Promise constructor'); + resolve = $$resolve; + reject = $$reject; + }); + this.resolve = aFunction(resolve); + this.reject = aFunction(reject); +}; +var perform = function(exec){ + try { + exec(); + } catch(e){ + return {error: e}; + } +}; +var notify = function(promise, isReject){ + if(promise._n)return; + promise._n = true; + var chain = promise._c; + microtask(function(){ + var value = promise._v + , ok = promise._s == 1 + , i = 0; + var run = function(reaction){ + var handler = ok ? reaction.ok : reaction.fail + , resolve = reaction.resolve + , reject = reaction.reject + , domain = reaction.domain + , result, then; + try { + if(handler){ + if(!ok){ + if(promise._h == 2)onHandleUnhandled(promise); + promise._h = 1; + } + if(handler === true)result = value; + else { + if(domain)domain.enter(); + result = handler(value); + if(domain)domain.exit(); + } + if(result === reaction.promise){ + reject(TypeError('Promise-chain cycle')); + } else if(then = isThenable(result)){ + then.call(result, resolve, reject); + } else resolve(result); + } else reject(value); + } catch(e){ + reject(e); + } + }; + while(chain.length > i)run(chain[i++]); // variable length - can't use forEach + promise._c = []; + promise._n = false; + if(isReject && !promise._h)onUnhandled(promise); + }); +}; +var onUnhandled = function(promise){ + task.call(global, function(){ + var value = promise._v + , abrupt, handler, console; + if(isUnhandled(promise)){ + abrupt = perform(function(){ + if(isNode){ + process.emit('unhandledRejection', value, promise); + } else if(handler = global.onunhandledrejection){ + handler({promise: promise, reason: value}); + } else if((console = global.console) && console.error){ + console.error('Unhandled promise rejection', value); + } + }); + // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should + promise._h = isNode || isUnhandled(promise) ? 2 : 1; + } promise._a = undefined; + if(abrupt)throw abrupt.error; + }); +}; +var isUnhandled = function(promise){ + if(promise._h == 1)return false; + var chain = promise._a || promise._c + , i = 0 + , reaction; + while(chain.length > i){ + reaction = chain[i++]; + if(reaction.fail || !isUnhandled(reaction.promise))return false; + } return true; +}; +var onHandleUnhandled = function(promise){ + task.call(global, function(){ + var handler; + if(isNode){ + process.emit('rejectionHandled', promise); + } else if(handler = global.onrejectionhandled){ + handler({promise: promise, reason: promise._v}); + } + }); +}; +var $reject = function(value){ + var promise = this; + if(promise._d)return; + promise._d = true; + promise = promise._w || promise; // unwrap + promise._v = value; + promise._s = 2; + if(!promise._a)promise._a = promise._c.slice(); + notify(promise, true); +}; +var $resolve = function(value){ + var promise = this + , then; + if(promise._d)return; + promise._d = true; + promise = promise._w || promise; // unwrap + try { + if(promise === value)throw TypeError("Promise can't be resolved itself"); + if(then = isThenable(value)){ + microtask(function(){ + var wrapper = {_w: promise, _d: false}; // wrap + try { + then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1)); + } catch(e){ + $reject.call(wrapper, e); + } + }); + } else { + promise._v = value; + promise._s = 1; + notify(promise, false); + } + } catch(e){ + $reject.call({_w: promise, _d: false}, e); // wrap + } +}; + +// constructor polyfill +if(!USE_NATIVE){ + // 25.4.3.1 Promise(executor) + $Promise = function Promise(executor){ + anInstance(this, $Promise, PROMISE, '_h'); + aFunction(executor); + Internal.call(this); + try { + executor(ctx($resolve, this, 1), ctx($reject, this, 1)); + } catch(err){ + $reject.call(this, err); + } + }; + Internal = function Promise(executor){ + this._c = []; // <- awaiting reactions + this._a = undefined; // <- checked in isUnhandled reactions + this._s = 0; // <- state + this._d = false; // <- done + this._v = undefined; // <- value + this._h = 0; // <- rejection state, 0 - default, 1 - handled, 2 - unhandled + this._n = false; // <- notify + }; + Internal.prototype = __webpack_require__(51)($Promise.prototype, { + // 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected) + then: function then(onFulfilled, onRejected){ + var reaction = newPromiseCapability(speciesConstructor(this, $Promise)); + reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true; + reaction.fail = typeof onRejected == 'function' && onRejected; + reaction.domain = isNode ? process.domain : undefined; + this._c.push(reaction); + if(this._a)this._a.push(reaction); + if(this._s)notify(this, false); + return reaction.promise; + }, + // 25.4.5.1 Promise.prototype.catch(onRejected) + 'catch': function(onRejected){ + return this.then(undefined, onRejected); + } + }); + PromiseCapability = function(){ + var promise = new Internal; + this.promise = promise; + this.resolve = ctx($resolve, promise, 1); + this.reject = ctx($reject, promise, 1); + }; +} + +$export($export.G + $export.W + $export.F * !USE_NATIVE, {Promise: $Promise}); +__webpack_require__(39)($Promise, PROMISE); +__webpack_require__(109)(PROMISE); +Wrapper = __webpack_require__(3)[PROMISE]; + +// statics +$export($export.S + $export.F * !USE_NATIVE, PROMISE, { + // 25.4.4.5 Promise.reject(r) + reject: function reject(r){ + var capability = newPromiseCapability(this) + , $$reject = capability.reject; + $$reject(r); + return capability.promise; + } +}); +$export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, { + // 25.4.4.6 Promise.resolve(x) + resolve: function resolve(x){ + // instanceof instead of internal slot check because we should fix it without replacement native Promise core + if(x instanceof $Promise && sameConstructor(x.constructor, this))return x; + var capability = newPromiseCapability(this) + , $$resolve = capability.resolve; + $$resolve(x); + return capability.promise; + } +}); +$export($export.S + $export.F * !(USE_NATIVE && __webpack_require__(103)(function(iter){ + $Promise.all(iter)['catch'](empty); +})), PROMISE, { + // 25.4.4.1 Promise.all(iterable) + all: function all(iterable){ + var C = this + , capability = newPromiseCapability(C) + , resolve = capability.resolve + , reject = capability.reject; + var abrupt = perform(function(){ + var values = [] + , index = 0 + , remaining = 1; + forOf(iterable, false, function(promise){ + var $index = index++ + , alreadyCalled = false; + values.push(undefined); + remaining++; + C.resolve(promise).then(function(value){ + if(alreadyCalled)return; + alreadyCalled = true; + values[$index] = value; + --remaining || resolve(values); + }, reject); + }); + --remaining || resolve(values); + }); + if(abrupt)reject(abrupt.error); + return capability.promise; + }, + // 25.4.4.4 Promise.race(iterable) + race: function race(iterable){ + var C = this + , capability = newPromiseCapability(C) + , reject = capability.reject; + var abrupt = perform(function(){ + forOf(iterable, false, function(promise){ + C.resolve(promise).then(capability.resolve, reject); + }); + }); + if(abrupt)reject(abrupt.error); + return capability.promise; + } +}); + +/***/ }), +/* 199 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var strong = __webpack_require__(96); + +// 23.2 Set Objects +module.exports = __webpack_require__(65)('Set', function(get){ + return function Set(){ return get(this, arguments.length > 0 ? arguments[0] : undefined); }; +}, { + // 23.2.3.1 Set.prototype.add(value) + add: function add(value){ + return strong.def(this, value = value === 0 ? 0 : value, value); + } +}, strong); + +/***/ }), +/* 200 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +// ECMAScript 6 symbols shim +var global = __webpack_require__(11) + , has = __webpack_require__(20) + , DESCRIPTORS = __webpack_require__(17) + , $export = __webpack_require__(10) + , redefine = __webpack_require__(72) + , META = __webpack_require__(31).KEY + , $fails = __webpack_require__(25) + , shared = __webpack_require__(74) + , setToStringTag = __webpack_require__(39) + , uid = __webpack_require__(53) + , wks = __webpack_require__(9) + , wksExt = __webpack_require__(78) + , wksDefine = __webpack_require__(77) + , keyOf = __webpack_require__(175) + , enumKeys = __webpack_require__(172) + , isArray = __webpack_require__(101) + , anObject = __webpack_require__(16) + , toIObject = __webpack_require__(22) + , toPrimitive = __webpack_require__(76) + , createDesc = __webpack_require__(38) + , _create = __webpack_require__(48) + , gOPNExt = __webpack_require__(178) + , $GOPD = __webpack_require__(70) + , $DP = __webpack_require__(14) + , $keys = __webpack_require__(32) + , gOPD = $GOPD.f + , dP = $DP.f + , gOPN = gOPNExt.f + , $Symbol = global.Symbol + , $JSON = global.JSON + , _stringify = $JSON && $JSON.stringify + , PROTOTYPE = 'prototype' + , HIDDEN = wks('_hidden') + , TO_PRIMITIVE = wks('toPrimitive') + , isEnum = {}.propertyIsEnumerable + , SymbolRegistry = shared('symbol-registry') + , AllSymbols = shared('symbols') + , OPSymbols = shared('op-symbols') + , ObjectProto = Object[PROTOTYPE] + , USE_NATIVE = typeof $Symbol == 'function' + , QObject = global.QObject; +// Don't use setters in Qt Script, https://github.com/zloirock/core-js/issues/173 +var setter = !QObject || !QObject[PROTOTYPE] || !QObject[PROTOTYPE].findChild; + +// fallback for old Android, https://code.google.com/p/v8/issues/detail?id=687 +var setSymbolDesc = DESCRIPTORS && $fails(function(){ + return _create(dP({}, 'a', { + get: function(){ return dP(this, 'a', {value: 7}).a; } + })).a != 7; +}) ? function(it, key, D){ + var protoDesc = gOPD(ObjectProto, key); + if(protoDesc)delete ObjectProto[key]; + dP(it, key, D); + if(protoDesc && it !== ObjectProto)dP(ObjectProto, key, protoDesc); +} : dP; + +var wrap = function(tag){ + var sym = AllSymbols[tag] = _create($Symbol[PROTOTYPE]); + sym._k = tag; + return sym; +}; + +var isSymbol = USE_NATIVE && typeof $Symbol.iterator == 'symbol' ? function(it){ + return typeof it == 'symbol'; +} : function(it){ + return it instanceof $Symbol; +}; + +var $defineProperty = function defineProperty(it, key, D){ + if(it === ObjectProto)$defineProperty(OPSymbols, key, D); + anObject(it); + key = toPrimitive(key, true); + anObject(D); + if(has(AllSymbols, key)){ + if(!D.enumerable){ + if(!has(it, HIDDEN))dP(it, HIDDEN, createDesc(1, {})); + it[HIDDEN][key] = true; + } else { + if(has(it, HIDDEN) && it[HIDDEN][key])it[HIDDEN][key] = false; + D = _create(D, {enumerable: createDesc(0, false)}); + } return setSymbolDesc(it, key, D); + } return dP(it, key, D); +}; +var $defineProperties = function defineProperties(it, P){ + anObject(it); + var keys = enumKeys(P = toIObject(P)) + , i = 0 + , l = keys.length + , key; + while(l > i)$defineProperty(it, key = keys[i++], P[key]); + return it; +}; +var $create = function create(it, P){ + return P === undefined ? _create(it) : $defineProperties(_create(it), P); +}; +var $propertyIsEnumerable = function propertyIsEnumerable(key){ + var E = isEnum.call(this, key = toPrimitive(key, true)); + if(this === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key))return false; + return E || !has(this, key) || !has(AllSymbols, key) || has(this, HIDDEN) && this[HIDDEN][key] ? E : true; +}; +var $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(it, key){ + it = toIObject(it); + key = toPrimitive(key, true); + if(it === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key))return; + var D = gOPD(it, key); + if(D && has(AllSymbols, key) && !(has(it, HIDDEN) && it[HIDDEN][key]))D.enumerable = true; + return D; +}; +var $getOwnPropertyNames = function getOwnPropertyNames(it){ + var names = gOPN(toIObject(it)) + , result = [] + , i = 0 + , key; + while(names.length > i){ + if(!has(AllSymbols, key = names[i++]) && key != HIDDEN && key != META)result.push(key); + } return result; +}; +var $getOwnPropertySymbols = function getOwnPropertySymbols(it){ + var IS_OP = it === ObjectProto + , names = gOPN(IS_OP ? OPSymbols : toIObject(it)) + , result = [] + , i = 0 + , key; + while(names.length > i){ + if(has(AllSymbols, key = names[i++]) && (IS_OP ? has(ObjectProto, key) : true))result.push(AllSymbols[key]); + } return result; +}; + +// 19.4.1.1 Symbol([description]) +if(!USE_NATIVE){ + $Symbol = function Symbol(){ + if(this instanceof $Symbol)throw TypeError('Symbol is not a constructor!'); + var tag = uid(arguments.length > 0 ? arguments[0] : undefined); + var $set = function(value){ + if(this === ObjectProto)$set.call(OPSymbols, value); + if(has(this, HIDDEN) && has(this[HIDDEN], tag))this[HIDDEN][tag] = false; + setSymbolDesc(this, tag, createDesc(1, value)); + }; + if(DESCRIPTORS && setter)setSymbolDesc(ObjectProto, tag, {configurable: true, set: $set}); + return wrap(tag); + }; + redefine($Symbol[PROTOTYPE], 'toString', function toString(){ + return this._k; + }); + + $GOPD.f = $getOwnPropertyDescriptor; + $DP.f = $defineProperty; + __webpack_require__(106).f = gOPNExt.f = $getOwnPropertyNames; + __webpack_require__(49).f = $propertyIsEnumerable; + __webpack_require__(71).f = $getOwnPropertySymbols; + + if(DESCRIPTORS && !__webpack_require__(47)){ + redefine(ObjectProto, 'propertyIsEnumerable', $propertyIsEnumerable, true); + } + + wksExt.f = function(name){ + return wrap(wks(name)); + } +} + +$export($export.G + $export.W + $export.F * !USE_NATIVE, {Symbol: $Symbol}); + +for(var symbols = ( + // 19.4.2.2, 19.4.2.3, 19.4.2.4, 19.4.2.6, 19.4.2.8, 19.4.2.9, 19.4.2.10, 19.4.2.11, 19.4.2.12, 19.4.2.13, 19.4.2.14 + 'hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables' +).split(','), i = 0; symbols.length > i; )wks(symbols[i++]); + +for(var symbols = $keys(wks.store), i = 0; symbols.length > i; )wksDefine(symbols[i++]); + +$export($export.S + $export.F * !USE_NATIVE, 'Symbol', { + // 19.4.2.1 Symbol.for(key) + 'for': function(key){ + return has(SymbolRegistry, key += '') + ? SymbolRegistry[key] + : SymbolRegistry[key] = $Symbol(key); + }, + // 19.4.2.5 Symbol.keyFor(sym) + keyFor: function keyFor(key){ + if(isSymbol(key))return keyOf(SymbolRegistry, key); + throw TypeError(key + ' is not a symbol!'); + }, + useSetter: function(){ setter = true; }, + useSimple: function(){ setter = false; } +}); + +$export($export.S + $export.F * !USE_NATIVE, 'Object', { + // 19.1.2.2 Object.create(O [, Properties]) + create: $create, + // 19.1.2.4 Object.defineProperty(O, P, Attributes) + defineProperty: $defineProperty, + // 19.1.2.3 Object.defineProperties(O, Properties) + defineProperties: $defineProperties, + // 19.1.2.6 Object.getOwnPropertyDescriptor(O, P) + getOwnPropertyDescriptor: $getOwnPropertyDescriptor, + // 19.1.2.7 Object.getOwnPropertyNames(O) + getOwnPropertyNames: $getOwnPropertyNames, + // 19.1.2.8 Object.getOwnPropertySymbols(O) + getOwnPropertySymbols: $getOwnPropertySymbols +}); + +// 24.3.2 JSON.stringify(value [, replacer [, space]]) +$JSON && $export($export.S + $export.F * (!USE_NATIVE || $fails(function(){ + var S = $Symbol(); + // MS Edge converts symbol values to JSON as {} + // WebKit converts symbol values to JSON as null + // V8 throws on boxed symbols + return _stringify([S]) != '[null]' || _stringify({a: S}) != '{}' || _stringify(Object(S)) != '{}'; +})), 'JSON', { + stringify: function stringify(it){ + if(it === undefined || isSymbol(it))return; // IE8 returns string on undefined + var args = [it] + , i = 1 + , replacer, $replacer; + while(arguments.length > i)args.push(arguments[i++]); + replacer = args[1]; + if(typeof replacer == 'function')$replacer = replacer; + if($replacer || !isArray(replacer))replacer = function(key, value){ + if($replacer)value = $replacer.call(this, key, value); + if(!isSymbol(value))return value; + }; + args[1] = replacer; + return _stringify.apply($JSON, args); + } +}); + +// 19.4.3.4 Symbol.prototype[@@toPrimitive](hint) +$Symbol[PROTOTYPE][TO_PRIMITIVE] || __webpack_require__(21)($Symbol[PROTOTYPE], TO_PRIMITIVE, $Symbol[PROTOTYPE].valueOf); +// 19.4.3.5 Symbol.prototype[@@toStringTag] +setToStringTag($Symbol, 'Symbol'); +// 20.2.1.9 Math[@@toStringTag] +setToStringTag(Math, 'Math', true); +// 24.3.3 JSON[@@toStringTag] +setToStringTag(global.JSON, 'JSON', true); + +/***/ }), +/* 201 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var each = __webpack_require__(64)(0) + , redefine = __webpack_require__(72) + , meta = __webpack_require__(31) + , assign = __webpack_require__(105) + , weak = __webpack_require__(170) + , isObject = __webpack_require__(13) + , getWeak = meta.getWeak + , isExtensible = Object.isExtensible + , uncaughtFrozenStore = weak.ufstore + , tmp = {} + , InternalMap; + +var wrapper = function(get){ + return function WeakMap(){ + return get(this, arguments.length > 0 ? arguments[0] : undefined); + }; +}; + +var methods = { + // 23.3.3.3 WeakMap.prototype.get(key) + get: function get(key){ + if(isObject(key)){ + var data = getWeak(key); + if(data === true)return uncaughtFrozenStore(this).get(key); + return data ? data[this._i] : undefined; + } + }, + // 23.3.3.5 WeakMap.prototype.set(key, value) + set: function set(key, value){ + return weak.def(this, key, value); + } +}; + +// 23.3 WeakMap Objects +var $WeakMap = module.exports = __webpack_require__(65)('WeakMap', wrapper, methods, weak, true, true); + +// IE11 WeakMap frozen keys fix +if(new $WeakMap().set((Object.freeze || Object)(tmp), 7).get(tmp) != 7){ + InternalMap = weak.getConstructor(wrapper); + assign(InternalMap.prototype, methods); + meta.NEED = true; + each(['delete', 'has', 'get', 'set'], function(key){ + var proto = $WeakMap.prototype + , method = proto[key]; + redefine(proto, key, function(a, b){ + // store frozen objects on internal weakmap shim + if(isObject(a) && !isExtensible(a)){ + if(!this._f)this._f = new InternalMap; + var result = this._f[key](a, b); + return key == 'set' ? this : result; + // store all the rest on native weakmap + } return method.call(this, a, b); + }); + }); +} + +/***/ }), +/* 202 */ +/***/ (function(module, exports, __webpack_require__) { + +// https://github.com/DavidBruant/Map-Set.prototype.toJSON +var $export = __webpack_require__(10); + +$export($export.P + $export.R, 'Map', {toJSON: __webpack_require__(97)('Map')}); + +/***/ }), +/* 203 */ +/***/ (function(module, exports, __webpack_require__) { + +// https://github.com/DavidBruant/Map-Set.prototype.toJSON +var $export = __webpack_require__(10); + +$export($export.P + $export.R, 'Set', {toJSON: __webpack_require__(97)('Set')}); + +/***/ }), +/* 204 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(77)('asyncIterator'); + +/***/ }), +/* 205 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(77)('observable'); + +/***/ }), +/* 206 */ +/***/ (function(module, exports, __webpack_require__) { + +// This method of obtaining a reference to the global object needs to be +// kept identical to the way it is obtained in runtime.js +var g = (function() { return this })() || Function("return this")(); + +// Use `getOwnPropertyNames` because not all browsers support calling +// `hasOwnProperty` on the global `self` object in a worker. See #183. +var hadRuntime = g.regeneratorRuntime && + Object.getOwnPropertyNames(g).indexOf("regeneratorRuntime") >= 0; + +// Save the old regeneratorRuntime in case it needs to be restored later. +var oldRuntime = hadRuntime && g.regeneratorRuntime; + +// Force reevalutation of runtime.js. +g.regeneratorRuntime = undefined; + +module.exports = __webpack_require__(207); + +if (hadRuntime) { + // Restore the original runtime. + g.regeneratorRuntime = oldRuntime; +} else { + // Remove the global property added by runtime.js. + try { + delete g.regeneratorRuntime; + } catch(e) { + g.regeneratorRuntime = undefined; + } +} + + +/***/ }), +/* 207 */ +/***/ (function(module, exports) { + +/** + * Copyright (c) 2014, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * https://raw.github.com/facebook/regenerator/master/LICENSE file. An + * additional grant of patent rights can be found in the PATENTS file in + * the same directory. + */ + +!(function(global) { + "use strict"; + + var Op = Object.prototype; + var hasOwn = Op.hasOwnProperty; + var undefined; // More compressible than void 0. + var $Symbol = typeof Symbol === "function" ? Symbol : {}; + var iteratorSymbol = $Symbol.iterator || "@@iterator"; + var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator"; + var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag"; + + var inModule = typeof module === "object"; + var runtime = global.regeneratorRuntime; + if (runtime) { + if (inModule) { + // If regeneratorRuntime is defined globally and we're in a module, + // make the exports object identical to regeneratorRuntime. + module.exports = runtime; + } + // Don't bother evaluating the rest of this file if the runtime was + // already defined globally. + return; + } + + // Define the runtime globally (as expected by generated code) as either + // module.exports (if we're in a module) or a new, empty object. + runtime = global.regeneratorRuntime = inModule ? module.exports : {}; + + function wrap(innerFn, outerFn, self, tryLocsList) { + // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator. + var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator; + var generator = Object.create(protoGenerator.prototype); + var context = new Context(tryLocsList || []); + + // The ._invoke method unifies the implementations of the .next, + // .throw, and .return methods. + generator._invoke = makeInvokeMethod(innerFn, self, context); + + return generator; + } + runtime.wrap = wrap; + + // Try/catch helper to minimize deoptimizations. Returns a completion + // record like context.tryEntries[i].completion. This interface could + // have been (and was previously) designed to take a closure to be + // invoked without arguments, but in all the cases we care about we + // already have an existing method we want to call, so there's no need + // to create a new function object. We can even get away with assuming + // the method takes exactly one argument, since that happens to be true + // in every case, so we don't have to touch the arguments object. The + // only additional allocation required is the completion record, which + // has a stable shape and so hopefully should be cheap to allocate. + function tryCatch(fn, obj, arg) { + try { + return { type: "normal", arg: fn.call(obj, arg) }; + } catch (err) { + return { type: "throw", arg: err }; + } + } + + var GenStateSuspendedStart = "suspendedStart"; + var GenStateSuspendedYield = "suspendedYield"; + var GenStateExecuting = "executing"; + var GenStateCompleted = "completed"; + + // Returning this object from the innerFn has the same effect as + // breaking out of the dispatch switch statement. + var ContinueSentinel = {}; + + // Dummy constructor functions that we use as the .constructor and + // .constructor.prototype properties for functions that return Generator + // objects. For full spec compliance, you may wish to configure your + // minifier not to mangle the names of these two functions. + function Generator() {} + function GeneratorFunction() {} + function GeneratorFunctionPrototype() {} + + // This is a polyfill for %IteratorPrototype% for environments that + // don't natively support it. + var IteratorPrototype = {}; + IteratorPrototype[iteratorSymbol] = function () { + return this; + }; + + var getProto = Object.getPrototypeOf; + var NativeIteratorPrototype = getProto && getProto(getProto(values([]))); + if (NativeIteratorPrototype && + NativeIteratorPrototype !== Op && + hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) { + // This environment has a native %IteratorPrototype%; use it instead + // of the polyfill. + IteratorPrototype = NativeIteratorPrototype; + } + + var Gp = GeneratorFunctionPrototype.prototype = + Generator.prototype = Object.create(IteratorPrototype); + GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype; + GeneratorFunctionPrototype.constructor = GeneratorFunction; + GeneratorFunctionPrototype[toStringTagSymbol] = + GeneratorFunction.displayName = "GeneratorFunction"; + + // Helper for defining the .next, .throw, and .return methods of the + // Iterator interface in terms of a single ._invoke method. + function defineIteratorMethods(prototype) { + ["next", "throw", "return"].forEach(function(method) { + prototype[method] = function(arg) { + return this._invoke(method, arg); + }; + }); + } + + runtime.isGeneratorFunction = function(genFun) { + var ctor = typeof genFun === "function" && genFun.constructor; + return ctor + ? ctor === GeneratorFunction || + // For the native GeneratorFunction constructor, the best we can + // do is to check its .name property. + (ctor.displayName || ctor.name) === "GeneratorFunction" + : false; + }; + + runtime.mark = function(genFun) { + if (Object.setPrototypeOf) { + Object.setPrototypeOf(genFun, GeneratorFunctionPrototype); + } else { + genFun.__proto__ = GeneratorFunctionPrototype; + if (!(toStringTagSymbol in genFun)) { + genFun[toStringTagSymbol] = "GeneratorFunction"; + } + } + genFun.prototype = Object.create(Gp); + return genFun; + }; + + // Within the body of any async function, `await x` is transformed to + // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test + // `hasOwn.call(value, "__await")` to determine if the yielded value is + // meant to be awaited. + runtime.awrap = function(arg) { + return { __await: arg }; + }; + + function AsyncIterator(generator) { + function invoke(method, arg, resolve, reject) { + var record = tryCatch(generator[method], generator, arg); + if (record.type === "throw") { + reject(record.arg); + } else { + var result = record.arg; + var value = result.value; + if (value && + typeof value === "object" && + hasOwn.call(value, "__await")) { + return Promise.resolve(value.__await).then(function(value) { + invoke("next", value, resolve, reject); + }, function(err) { + invoke("throw", err, resolve, reject); + }); + } + + return Promise.resolve(value).then(function(unwrapped) { + // When a yielded Promise is resolved, its final value becomes + // the .value of the Promise<{value,done}> result for the + // current iteration. If the Promise is rejected, however, the + // result for this iteration will be rejected with the same + // reason. Note that rejections of yielded Promises are not + // thrown back into the generator function, as is the case + // when an awaited Promise is rejected. This difference in + // behavior between yield and await is important, because it + // allows the consumer to decide what to do with the yielded + // rejection (swallow it and continue, manually .throw it back + // into the generator, abandon iteration, whatever). With + // await, by contrast, there is no opportunity to examine the + // rejection reason outside the generator function, so the + // only option is to throw it from the await expression, and + // let the generator function handle the exception. + result.value = unwrapped; + resolve(result); + }, reject); + } + } + + var previousPromise; + + function enqueue(method, arg) { + function callInvokeWithMethodAndArg() { + return new Promise(function(resolve, reject) { + invoke(method, arg, resolve, reject); + }); + } + + return previousPromise = + // If enqueue has been called before, then we want to wait until + // all previous Promises have been resolved before calling invoke, + // so that results are always delivered in the correct order. If + // enqueue has not been called before, then it is important to + // call invoke immediately, without waiting on a callback to fire, + // so that the async generator function has the opportunity to do + // any necessary setup in a predictable way. This predictability + // is why the Promise constructor synchronously invokes its + // executor callback, and why async functions synchronously + // execute code before the first await. Since we implement simple + // async functions in terms of async generators, it is especially + // important to get this right, even though it requires care. + previousPromise ? previousPromise.then( + callInvokeWithMethodAndArg, + // Avoid propagating failures to Promises returned by later + // invocations of the iterator. + callInvokeWithMethodAndArg + ) : callInvokeWithMethodAndArg(); + } + + // Define the unified helper method that is used to implement .next, + // .throw, and .return (see defineIteratorMethods). + this._invoke = enqueue; + } + + defineIteratorMethods(AsyncIterator.prototype); + AsyncIterator.prototype[asyncIteratorSymbol] = function () { + return this; + }; + runtime.AsyncIterator = AsyncIterator; + + // Note that simple async functions are implemented on top of + // AsyncIterator objects; they just return a Promise for the value of + // the final result produced by the iterator. + runtime.async = function(innerFn, outerFn, self, tryLocsList) { + var iter = new AsyncIterator( + wrap(innerFn, outerFn, self, tryLocsList) + ); + + return runtime.isGeneratorFunction(outerFn) + ? iter // If outerFn is a generator, return the full iterator. + : iter.next().then(function(result) { + return result.done ? result.value : iter.next(); + }); + }; + + function makeInvokeMethod(innerFn, self, context) { + var state = GenStateSuspendedStart; + + return function invoke(method, arg) { + if (state === GenStateExecuting) { + throw new Error("Generator is already running"); + } + + if (state === GenStateCompleted) { + if (method === "throw") { + throw arg; + } + + // Be forgiving, per 25.3.3.3.3 of the spec: + // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume + return doneResult(); + } + + context.method = method; + context.arg = arg; + + while (true) { + var delegate = context.delegate; + if (delegate) { + var delegateResult = maybeInvokeDelegate(delegate, context); + if (delegateResult) { + if (delegateResult === ContinueSentinel) continue; + return delegateResult; + } + } + + if (context.method === "next") { + // Setting context._sent for legacy support of Babel's + // function.sent implementation. + context.sent = context._sent = context.arg; + + } else if (context.method === "throw") { + if (state === GenStateSuspendedStart) { + state = GenStateCompleted; + throw context.arg; + } + + context.dispatchException(context.arg); + + } else if (context.method === "return") { + context.abrupt("return", context.arg); + } + + state = GenStateExecuting; + + var record = tryCatch(innerFn, self, context); + if (record.type === "normal") { + // If an exception is thrown from innerFn, we leave state === + // GenStateExecuting and loop back for another invocation. + state = context.done + ? GenStateCompleted + : GenStateSuspendedYield; + + if (record.arg === ContinueSentinel) { + continue; + } + + return { + value: record.arg, + done: context.done + }; + + } else if (record.type === "throw") { + state = GenStateCompleted; + // Dispatch the exception by looping back around to the + // context.dispatchException(context.arg) call above. + context.method = "throw"; + context.arg = record.arg; + } + } + }; + } + + // Call delegate.iterator[context.method](context.arg) and handle the + // result, either by returning a { value, done } result from the + // delegate iterator, or by modifying context.method and context.arg, + // setting context.delegate to null, and returning the ContinueSentinel. + function maybeInvokeDelegate(delegate, context) { + var method = delegate.iterator[context.method]; + if (method === undefined) { + // A .throw or .return when the delegate iterator has no .throw + // method always terminates the yield* loop. + context.delegate = null; + + if (context.method === "throw") { + if (delegate.iterator.return) { + // If the delegate iterator has a return method, give it a + // chance to clean up. + context.method = "return"; + context.arg = undefined; + maybeInvokeDelegate(delegate, context); + + if (context.method === "throw") { + // If maybeInvokeDelegate(context) changed context.method from + // "return" to "throw", let that override the TypeError below. + return ContinueSentinel; + } + } + + context.method = "throw"; + context.arg = new TypeError( + "The iterator does not provide a 'throw' method"); + } + + return ContinueSentinel; + } + + var record = tryCatch(method, delegate.iterator, context.arg); + + if (record.type === "throw") { + context.method = "throw"; + context.arg = record.arg; + context.delegate = null; + return ContinueSentinel; + } + + var info = record.arg; + + if (! info) { + context.method = "throw"; + context.arg = new TypeError("iterator result is not an object"); + context.delegate = null; + return ContinueSentinel; + } + + if (info.done) { + // Assign the result of the finished delegate to the temporary + // variable specified by delegate.resultName (see delegateYield). + context[delegate.resultName] = info.value; + + // Resume execution at the desired location (see delegateYield). + context.next = delegate.nextLoc; + + // If context.method was "throw" but the delegate handled the + // exception, let the outer generator proceed normally. If + // context.method was "next", forget context.arg since it has been + // "consumed" by the delegate iterator. If context.method was + // "return", allow the original .return call to continue in the + // outer generator. + if (context.method !== "return") { + context.method = "next"; + context.arg = undefined; + } + + } else { + // Re-yield the result returned by the delegate method. + return info; + } + + // The delegate iterator is finished, so forget it and continue with + // the outer generator. + context.delegate = null; + return ContinueSentinel; + } + + // Define Generator.prototype.{next,throw,return} in terms of the + // unified ._invoke helper method. + defineIteratorMethods(Gp); + + Gp[toStringTagSymbol] = "Generator"; + + // A Generator should always return itself as the iterator object when the + // @@iterator function is called on it. Some browsers' implementations of the + // iterator prototype chain incorrectly implement this, causing the Generator + // object to not be returned from this call. This ensures that doesn't happen. + // See https://github.com/facebook/regenerator/issues/274 for more details. + Gp[iteratorSymbol] = function() { + return this; + }; + + Gp.toString = function() { + return "[object Generator]"; + }; + + function pushTryEntry(locs) { + var entry = { tryLoc: locs[0] }; + + if (1 in locs) { + entry.catchLoc = locs[1]; + } + + if (2 in locs) { + entry.finallyLoc = locs[2]; + entry.afterLoc = locs[3]; + } + + this.tryEntries.push(entry); + } + + function resetTryEntry(entry) { + var record = entry.completion || {}; + record.type = "normal"; + delete record.arg; + entry.completion = record; + } + + function Context(tryLocsList) { + // The root entry object (effectively a try statement without a catch + // or a finally block) gives us a place to store values thrown from + // locations where there is no enclosing try statement. + this.tryEntries = [{ tryLoc: "root" }]; + tryLocsList.forEach(pushTryEntry, this); + this.reset(true); + } + + runtime.keys = function(object) { + var keys = []; + for (var key in object) { + keys.push(key); + } + keys.reverse(); + + // Rather than returning an object with a next method, we keep + // things simple and return the next function itself. + return function next() { + while (keys.length) { + var key = keys.pop(); + if (key in object) { + next.value = key; + next.done = false; + return next; + } + } + + // To avoid creating an additional object, we just hang the .value + // and .done properties off the next function object itself. This + // also ensures that the minifier will not anonymize the function. + next.done = true; + return next; + }; + }; + + function values(iterable) { + if (iterable) { + var iteratorMethod = iterable[iteratorSymbol]; + if (iteratorMethod) { + return iteratorMethod.call(iterable); + } + + if (typeof iterable.next === "function") { + return iterable; + } + + if (!isNaN(iterable.length)) { + var i = -1, next = function next() { + while (++i < iterable.length) { + if (hasOwn.call(iterable, i)) { + next.value = iterable[i]; + next.done = false; + return next; + } + } + + next.value = undefined; + next.done = true; + + return next; + }; + + return next.next = next; + } + } + + // Return an iterator with no values. + return { next: doneResult }; + } + runtime.values = values; + + function doneResult() { + return { value: undefined, done: true }; + } + + Context.prototype = { + constructor: Context, + + reset: function(skipTempReset) { + this.prev = 0; + this.next = 0; + // Resetting context._sent for legacy support of Babel's + // function.sent implementation. + this.sent = this._sent = undefined; + this.done = false; + this.delegate = null; + + this.method = "next"; + this.arg = undefined; + + this.tryEntries.forEach(resetTryEntry); + + if (!skipTempReset) { + for (var name in this) { + // Not sure about the optimal order of these conditions: + if (name.charAt(0) === "t" && + hasOwn.call(this, name) && + !isNaN(+name.slice(1))) { + this[name] = undefined; + } + } + } + }, + + stop: function() { + this.done = true; + + var rootEntry = this.tryEntries[0]; + var rootRecord = rootEntry.completion; + if (rootRecord.type === "throw") { + throw rootRecord.arg; + } + + return this.rval; + }, + + dispatchException: function(exception) { + if (this.done) { + throw exception; + } + + var context = this; + function handle(loc, caught) { + record.type = "throw"; + record.arg = exception; + context.next = loc; + + if (caught) { + // If the dispatched exception was caught by a catch block, + // then let that catch block handle the exception normally. + context.method = "next"; + context.arg = undefined; + } + + return !! caught; + } + + for (var i = this.tryEntries.length - 1; i >= 0; --i) { + var entry = this.tryEntries[i]; + var record = entry.completion; + + if (entry.tryLoc === "root") { + // Exception thrown outside of any try block that could handle + // it, so set the completion value of the entire function to + // throw the exception. + return handle("end"); + } + + if (entry.tryLoc <= this.prev) { + var hasCatch = hasOwn.call(entry, "catchLoc"); + var hasFinally = hasOwn.call(entry, "finallyLoc"); + + if (hasCatch && hasFinally) { + if (this.prev < entry.catchLoc) { + return handle(entry.catchLoc, true); + } else if (this.prev < entry.finallyLoc) { + return handle(entry.finallyLoc); + } + + } else if (hasCatch) { + if (this.prev < entry.catchLoc) { + return handle(entry.catchLoc, true); + } + + } else if (hasFinally) { + if (this.prev < entry.finallyLoc) { + return handle(entry.finallyLoc); + } + + } else { + throw new Error("try statement without catch or finally"); + } + } + } + }, + + abrupt: function(type, arg) { + for (var i = this.tryEntries.length - 1; i >= 0; --i) { + var entry = this.tryEntries[i]; + if (entry.tryLoc <= this.prev && + hasOwn.call(entry, "finallyLoc") && + this.prev < entry.finallyLoc) { + var finallyEntry = entry; + break; + } + } + + if (finallyEntry && + (type === "break" || + type === "continue") && + finallyEntry.tryLoc <= arg && + arg <= finallyEntry.finallyLoc) { + // Ignore the finally entry if control is not jumping to a + // location outside the try/catch block. + finallyEntry = null; + } + + var record = finallyEntry ? finallyEntry.completion : {}; + record.type = type; + record.arg = arg; + + if (finallyEntry) { + this.method = "next"; + this.next = finallyEntry.finallyLoc; + return ContinueSentinel; + } + + return this.complete(record); + }, + + complete: function(record, afterLoc) { + if (record.type === "throw") { + throw record.arg; + } + + if (record.type === "break" || + record.type === "continue") { + this.next = record.arg; + } else if (record.type === "return") { + this.rval = this.arg = record.arg; + this.method = "return"; + this.next = "end"; + } else if (record.type === "normal" && afterLoc) { + this.next = afterLoc; + } + + return ContinueSentinel; + }, + + finish: function(finallyLoc) { + for (var i = this.tryEntries.length - 1; i >= 0; --i) { + var entry = this.tryEntries[i]; + if (entry.finallyLoc === finallyLoc) { + this.complete(entry.completion, entry.afterLoc); + resetTryEntry(entry); + return ContinueSentinel; + } + } + }, + + "catch": function(tryLoc) { + for (var i = this.tryEntries.length - 1; i >= 0; --i) { + var entry = this.tryEntries[i]; + if (entry.tryLoc === tryLoc) { + var record = entry.completion; + if (record.type === "throw") { + var thrown = record.arg; + resetTryEntry(entry); + } + return thrown; + } + } + + // The context.catch method must only be called with a location + // argument that corresponds to a known catch block. + throw new Error("illegal catch attempt"); + }, + + delegateYield: function(iterable, resultName, nextLoc) { + this.delegate = { + iterator: values(iterable), + resultName: resultName, + nextLoc: nextLoc + }; + + if (this.method === "next") { + // Deliberately forget the last sent value so that we don't + // accidentally pass it on to the delegate. + this.arg = undefined; + } + + return ContinueSentinel; + } + }; +})( + // In sloppy mode, unbound `this` refers to the global object, fallback to + // Function constructor if we're in global strict mode. That is sadly a form + // of indirect eval which violates Content Security Policy. + (function() { return this })() || Function("return this")() +); + + +/***/ }), +/* 208 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = __webpack_require__(111); + + +/***/ }) +/******/ ]); +}); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay91bml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uIiwid2VicGFjazovLy93ZWJwYWNrL2Jvb3RzdHJhcCAzMmI4YWE2NTUyMmNkMjhjYTUyNyIsIndlYnBhY2s6Ly8vLi9+L2JhYmVsLXJ1bnRpbWUvaGVscGVycy9jbGFzc0NhbGxDaGVjay5qcyIsIndlYnBhY2s6Ly8vLi9+L2JhYmVsLXJ1bnRpbWUvaGVscGVycy9jcmVhdGVDbGFzcy5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvanMvbG9nL2luZGV4LmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2NvcmUuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2pzL2Vudi9icm93c2VyLmpzIiwid2VicGFjazovLy8uL3NyYy9qcy91dGlsL3Byb21pc2UuanMiLCJ3ZWJwYWNrOi8vLy4vfi9iYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L2dldC1wcm90b3R5cGUtb2YuanMiLCJ3ZWJwYWNrOi8vLy4vfi9iYWJlbC1ydW50aW1lL2hlbHBlcnMvaW5oZXJpdHMuanMiLCJ3ZWJwYWNrOi8vLy4vfi9iYWJlbC1ydW50aW1lL2hlbHBlcnMvcG9zc2libGVDb25zdHJ1Y3RvclJldHVybi5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL193a3MuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fZXhwb3J0LmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2dsb2JhbC5qcyIsIndlYnBhY2s6Ly8vLi9+L2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9qc29uL3N0cmluZ2lmeS5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pcy1vYmplY3QuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LWRwLmpzIiwid2VicGFjazovLy8uL3NyYy9qcy9ldmVudC9pbmRleC5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19hbi1vYmplY3QuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fZGVzY3JpcHRvcnMuanMiLCJ3ZWJwYWNrOi8vLy4vfi9iYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L2ZyZWV6ZS5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19jdHguanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9faGFzLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2hpZGUuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fdG8taW9iamVjdC5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvanMvY29yZS9ldmVudC1lbWl0dGVyLmpzIiwid2VicGFjazovLy8uL3NyYy9qcy9zdWJzY3JpYmVyL2NvbnRyb2xzL2luZGV4LmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2ZhaWxzLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2LnN0cmluZy5pdGVyYXRvci5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL3dlYi5kb20uaXRlcmFibGUuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2pzL3V0aWwvb2JqZWN0LmpzIiwid2VicGFjazovLy8uL34vYmFiZWwtcnVudGltZS9oZWxwZXJzL2V4dGVuZHMuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9faXRlcmF0b3JzLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX21ldGEuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LWtleXMuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fdG8tb2JqZWN0LmpzIiwid2VicGFjazovLy8uL3NyYy9qcy9lbnVtL3BsYXliYWNrLmpzIiwid2VicGFjazovLy8uL3NyYy9qcy9zdWJzY3JpYmVyL2NvbnRyb2xzL3N0YXRlLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2NvZi5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19mb3Itb2YuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fcHJvcGVydHktZGVzYy5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19zZXQtdG8tc3RyaW5nLXRhZy5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvanMvYWRhcHRlci93ZWJydGMuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2pzL2FkYXB0ZXIvd2Vic29ja2V0LmpzIiwid2VicGFjazovLy8uL3NyYy9qcy92aWV3L3BsYXliYWNrLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2FuLWluc3RhbmNlLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2NsYXNzb2YuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fZGVmaW5lZC5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19saWJyYXJ5LmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX29iamVjdC1jcmVhdGUuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LXBpZS5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19vYmplY3Qtc2FwLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3JlZGVmaW5lLWFsbC5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL190by1sZW5ndGguanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fdWlkLmpzIiwid2VicGFjazovLy8uL3NyYy9qcy9lbnVtL3B1Ymxpc2guanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2pzL2VudW0vd2VicnRjLmpzIiwid2VicGFjazovLy8uL3NyYy9qcy9ldmVudC9zaGFyZWRvYmplY3QtZXZlbnQuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2pzL2hlbHBlci9zb2NrZXQtaGVscGVyLmpzIiwid2VicGFjazovLy8uL3NyYy9qcy91dGlsL3VybC1lbmRwb2ludC5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvanMvdmlldy9wdWJsaXNoLmpzIiwid2VicGFjazovLy8uL34vYmFiZWwtcnVudGltZS9jb3JlLWpzL29iamVjdC9rZXlzLmpzIiwid2VicGFjazovLy8uL34vYmFiZWwtcnVudGltZS9jb3JlLWpzL3Byb21pc2UuanMiLCJ3ZWJwYWNrOi8vLy4vfi9iYWJlbC1ydW50aW1lL2hlbHBlcnMvdHlwZW9mLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2EtZnVuY3Rpb24uanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fYXJyYXktbWV0aG9kcy5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19jb2xsZWN0aW9uLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2RvbS1jcmVhdGUuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fZW51bS1idWcta2V5cy5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pb2JqZWN0LmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2l0ZXItZGVmaW5lLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX29iamVjdC1nb3BkLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX29iamVjdC1nb3BzLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3JlZGVmaW5lLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3NoYXJlZC1rZXkuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fc2hhcmVkLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3RvLWludGVnZXIuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fdG8tcHJpbWl0aXZlLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3drcy1kZWZpbmUuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fd2tzLWV4dC5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2NvcmUuZ2V0LWl0ZXJhdG9yLW1ldGhvZC5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvanMvZW52L2VtYmVkLmpzIiwid2VicGFjazovLy8uL3NyYy9qcy9lbnYvdHJhbnNsYXRpb24tdXRpbC5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvanMvZXZlbnQvcHVibGlzaGVyLWV2ZW50LmpzIiwid2VicGFjazovLy8uL3NyYy9qcy9ldmVudC9zdWJzY3JpYmVyLWV2ZW50LmpzIiwid2VicGFjazovLy8uL3NyYy9qcy9oZWxwZXIvc2hhcmVkb2JqZWN0LWhlbHBlci1ydG1wLmpzIiwid2VicGFjazovLy8uL3NyYy9qcy9wdWJsaXNoZXIvY29uc3RyYWludC9pbmRleC5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvanMvc3Vic2NyaWJlci9jb250cm9scy9ldmVudC5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvanMvdXRpbC9pbXBsLWZhY3Rvcnktb3JkZXIuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2pzL3V0aWwvaW5kZXguanMiLCJ3ZWJwYWNrOi8vLy4vfi9iYWJlbC1ydW50aW1lL2NvcmUtanMvbWFwLmpzIiwid2VicGFjazovLy8uL34vYmFiZWwtcnVudGltZS9jb3JlLWpzL251bWJlci9pcy1maW5pdGUuanMiLCJ3ZWJwYWNrOi8vLy4vfi9iYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L2RlZmluZS1wcm9wZXJ0eS5qcyIsIndlYnBhY2s6Ly8vLi9+L2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9zZXQuanMiLCJ3ZWJwYWNrOi8vLy4vfi9iYWJlbC1ydW50aW1lL2hlbHBlcnMvZ2V0LmpzIiwid2VicGFjazovLy8uL34vYmFiZWwtcnVudGltZS9oZWxwZXJzL3RvQ29uc3VtYWJsZUFycmF5LmpzIiwid2VicGFjazovLy8uL34vYnJvd3Nlci1idW55YW4vbGliL2J1bnlhbi5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19jb2xsZWN0aW9uLXN0cm9uZy5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19jb2xsZWN0aW9uLXRvLWpzb24uanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9faHRtbC5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pZTgtZG9tLWRlZmluZS5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pcy1hcnJheS1pdGVyLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2lzLWFycmF5LmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2l0ZXItY2FsbC5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pdGVyLWRldGVjdC5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pdGVyLXN0ZXAuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LWFzc2lnbi5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19vYmplY3QtZ29wbi5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19vYmplY3QtZ3BvLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX29iamVjdC1rZXlzLWludGVybmFsLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3NldC1zcGVjaWVzLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3Rhc2suanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2pzL2luZGV4LmpzIiwid2VicGFjazovLy8uL3NyYy9qcy9lbnYvbWV0YWRhdGEtdXRpbC5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvanMvZXhjZXB0aW9uL2Vycm9ycy5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvanMvaGVscGVyL3NvY2tldC1oZWxwZXItcHViLmpzIiwid2VicGFjazovLy8uL3NyYy9qcy9oZWxwZXIvc29ja2V0LWhlbHBlci1zdWIuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2pzL2hlbHBlci93ZWJydGMtaGVscGVyLXB1Yi5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvanMvaGVscGVyL3dlYnJ0Yy1oZWxwZXItc3ViLmpzIiwid2VicGFjazovLy8uL3NyYy9qcy9sb2cvYnVueWFuLXdyaXRlci5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvanMvcHVibGlzaGVyL2luZGV4LmpzIiwid2VicGFjazovLy8uL3NyYy9qcy9wdWJsaXNoZXIvcHViLXNvdXJjZS1oYW5kbGVyLmpzIiwid2VicGFjazovLy8uL3NyYy9qcy9wdWJsaXNoZXIvcmVkNXByby1ydGMuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2pzL3B1Ymxpc2hlci9yZWQ1cHJvLXJ0bXAuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2pzL3NoYXJlZG9iamVjdC9pbmRleC5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvanMvc3Vic2NyaWJlci9jb250cm9scy9zbGlkZXIuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2pzL3N1YnNjcmliZXIvaW5kZXguanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2pzL3N1YnNjcmliZXIvcmVkNXByby1obHMuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2pzL3N1YnNjcmliZXIvcmVkNXByby1ydGMuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2pzL3N1YnNjcmliZXIvcmVkNXByby1ydG1wLmpzIiwid2VicGFjazovLy8uL3NyYy9qcy9zdWJzY3JpYmVyL3JlZDVwcm8tc291cmNlLWhhbmRsZXItaGxzLmpzIiwid2VicGFjazovLy8uL3NyYy9qcy9zdWJzY3JpYmVyL3JlZDVwcm8tc291cmNlLWhhbmRsZXItcnRjLmpzIiwid2VicGFjazovLy8uL3NyYy9qcy9zdWJzY3JpYmVyL3JlZDVwcm8tc291cmNlLWhhbmRsZXItcnRtcC5qcyIsIndlYnBhY2s6Ly8vLi9+L2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9hcnJheS9mcm9tLmpzIiwid2VicGFjazovLy8uL34vYmFiZWwtcnVudGltZS9jb3JlLWpzL2dldC1pdGVyYXRvci5qcyIsIndlYnBhY2s6Ly8vLi9+L2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9pcy1pdGVyYWJsZS5qcyIsIndlYnBhY2s6Ly8vLi9+L2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9udW1iZXIvaXMtbmFuLmpzIiwid2VicGFjazovLy8uL34vYmFiZWwtcnVudGltZS9jb3JlLWpzL29iamVjdC9hc3NpZ24uanMiLCJ3ZWJwYWNrOi8vLy4vfi9iYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L2NyZWF0ZS5qcyIsIndlYnBhY2s6Ly8vLi9+L2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9vYmplY3QvZ2V0LW93bi1wcm9wZXJ0eS1kZXNjcmlwdG9yLmpzIiwid2VicGFjazovLy8uL34vYmFiZWwtcnVudGltZS9jb3JlLWpzL29iamVjdC9zZXQtcHJvdG90eXBlLW9mLmpzIiwid2VicGFjazovLy8uL34vYmFiZWwtcnVudGltZS9jb3JlLWpzL3N5bWJvbC5qcyIsIndlYnBhY2s6Ly8vLi9+L2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9zeW1ib2wvaXRlcmF0b3IuanMiLCJ3ZWJwYWNrOi8vLy4vfi9iYWJlbC1ydW50aW1lL2NvcmUtanMvd2Vhay1tYXAuanMiLCJ3ZWJwYWNrOi8vLy4vfi9iYWJlbC1ydW50aW1lL2hlbHBlcnMvc2xpY2VkVG9BcnJheS5qcyIsIndlYnBhY2s6Ly8vLi9+L2JhYmVsLXJ1bnRpbWUvcmVnZW5lcmF0b3IvaW5kZXguanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vYXJyYXkvZnJvbS5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9mbi9nZXQtaXRlcmF0b3IuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vaXMtaXRlcmFibGUuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vanNvbi9zdHJpbmdpZnkuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vbWFwLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L2ZuL251bWJlci9pcy1maW5pdGUuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vbnVtYmVyL2lzLW5hbi5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9mbi9vYmplY3QvYXNzaWduLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L2ZuL29iamVjdC9jcmVhdGUuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2RlZmluZS1wcm9wZXJ0eS5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9mbi9vYmplY3QvZnJlZXplLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L2ZuL29iamVjdC9nZXQtb3duLXByb3BlcnR5LWRlc2NyaXB0b3IuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2dldC1wcm90b3R5cGUtb2YuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2tleXMuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L3NldC1wcm90b3R5cGUtb2YuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vcHJvbWlzZS5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9mbi9zZXQuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vc3ltYm9sL2luZGV4LmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L2ZuL3N5bWJvbC9pdGVyYXRvci5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9mbi93ZWFrLW1hcC5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19hZGQtdG8tdW5zY29wYWJsZXMuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fYXJyYXktZnJvbS1pdGVyYWJsZS5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19hcnJheS1pbmNsdWRlcy5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19hcnJheS1zcGVjaWVzLWNvbnN0cnVjdG9yLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2FycmF5LXNwZWNpZXMtY3JlYXRlLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2NvbGxlY3Rpb24td2Vhay5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19jcmVhdGUtcHJvcGVydHkuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fZW51bS1rZXlzLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2ludm9rZS5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pdGVyLWNyZWF0ZS5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19rZXlvZi5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19taWNyb3Rhc2suanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LWRwcy5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19vYmplY3QtZ29wbi1leHQuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fc2V0LXByb3RvLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3NwZWNpZXMtY29uc3RydWN0b3IuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fc3RyaW5nLWF0LmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3RvLWluZGV4LmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvY29yZS5nZXQtaXRlcmF0b3IuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9jb3JlLmlzLWl0ZXJhYmxlLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2LmFycmF5LmZyb20uanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYuYXJyYXkuaXRlcmF0b3IuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYubWFwLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2Lm51bWJlci5pcy1maW5pdGUuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYubnVtYmVyLmlzLW5hbi5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5vYmplY3QuYXNzaWduLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2Lm9iamVjdC5jcmVhdGUuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYub2JqZWN0LmRlZmluZS1wcm9wZXJ0eS5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5vYmplY3QuZnJlZXplLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2Lm9iamVjdC5nZXQtb3duLXByb3BlcnR5LWRlc2NyaXB0b3IuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYub2JqZWN0LmdldC1wcm90b3R5cGUtb2YuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYub2JqZWN0LmtleXMuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYub2JqZWN0LnNldC1wcm90b3R5cGUtb2YuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYucHJvbWlzZS5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5zZXQuanMiLCJ3ZWJwYWNrOi8vLy4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYuc3ltYm9sLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2LndlYWstbWFwLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM3Lm1hcC50by1qc29uLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM3LnNldC50by1qc29uLmpzIiwid2VicGFjazovLy8uL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM3LnN5bWJvbC5hc3luYy1pdGVyYXRvci5qcyIsIndlYnBhY2s6Ly8vLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNy5zeW1ib2wub2JzZXJ2YWJsZS5qcyIsIndlYnBhY2s6Ly8vLi9+L3JlZ2VuZXJhdG9yLXJ1bnRpbWUvcnVudGltZS1tb2R1bGUuanMiLCJ3ZWJwYWNrOi8vLy4vfi9yZWdlbmVyYXRvci1ydW50aW1lL3J1bnRpbWUuanMiXSwibmFtZXMiOlsibG9nZ2VyIiwiZm9ybWF0TWVzc2FnZSIsImRpc3BhdGNoZXIiLCJtZXNzYWdlIiwiZGVjb3JhdGUiLCJsZXZlbCIsInNvdXJjZSIsIkxFVkVMUyIsIlRSQUNFIiwiSU5GTyIsIkRFQlVHIiwiV0FSTiIsIkVSUk9SIiwiRkFUQUwiLCJlc3RhYmxpc2hMb2dnZXIiLCJzdHJlYW1MaXN0IiwidW5kZWZpbmVkIiwic3RyZWFtcyIsInB1c2giLCJzdHJlYW0iLCJSYXdTdHJlYW0iLCJ0eXBlIiwibGlzdCIsIm1hcCIsIml0ZW0iLCJjb25jYXQiLCJuYW1lIiwiZ2V0TG9nZ2VyIiwidHJhY2UiLCJpbmZvIiwiZGVidWciLCJ3YXJuIiwiZXJyb3IiLCJmYXRhbCIsInJ0bXBTdWJzY3JpYmVyQXNzaWdubWVudHMiLCJmdWxsc2NyZWVuSGFuZGxlcnMiLCJzY3JlZW5mdWxsSGFuZGxlckFzc2lnbmVkIiwiZW5hYmxlU2NyZWVuZnVsbEhhbmRsZXIiLCJ3aW5kb3ciLCJzY3JlZW5mdWxsIiwiZW5hYmxlZCIsIm9uY2hhbmdlIiwiaSIsImxlbmd0aCIsImlzRnVsbHNjcmVlbiIsIm9yaWVudGF0aW9uSGFuZGxlcnMiLCJvbm9yaWVudGF0aW9uY2hhbmdlIiwiZXZlbnQiLCJzY3JlZW5PcmllbnRhdGlvbiIsInNjcmVlbiIsIm9yaWVudGF0aW9uIiwiYW5nbGUiLCJvcmllbnRhdGlvblZhbHVlIiwibWF0Y2hNZWRpYSIsIm1hdGNoZXMiLCJjbG9zZUhhbmRsZXJzIiwiaGFzT25XaW5kb3dDbG9zZSIsIm9ud2luZG93Y2xvc2UiLCJlIiwiZmxhc2hWZXJzaW9uIiwidmVyc2lvbiIsIkFjdGl2ZVhPYmplY3QiLCJHZXRWYXJpYWJsZSIsInJlcGxhY2UiLCJtYXRjaCIsIm5hdmlnYXRvciIsIm1pbWVUeXBlcyIsImVuYWJsZWRQbHVnaW4iLCJwbHVnaW5zIiwiZGVzY3JpcHRpb24iLCJlcnIiLCJzcGxpdCIsInJlcXVlc3RGcmFtZSIsInRpbWUiLCJyZXF1ZXN0QW5pbWF0aW9uRnJhbWUiLCJtb3pSZXF1ZXN0QW5pbWF0aW9uRnJhbWUiLCJ3ZWJraXRSZXF1ZXN0QW5pbWF0aW9uRnJhbWUiLCJtc1JlcXVlc3RBbmltYXRpb25GcmFtZSIsImZuIiwic2V0VGltZW91dCIsImlzTW96IiwibW96R2V0VXNlck1lZGlhIiwiaXNUb3VjaEVuYWJsZWQiLCJEb2N1bWVudFRvdWNoIiwiZG9jdW1lbnQiLCJhZGFwdGVyIiwiZ2V0VXNlck1lZGlhIiwibWVkaWFEZXZpY2VzIiwid2Via2l0R2V0VXNlck1lZGlhIiwibXNHZXRVc2VyTWVkaWEiLCJnZXRJc01veiIsInN1cHBvcnRzV2ViU29ja2V0IiwiV2ViU29ja2V0Iiwic3VwcG9ydHNITFMiLCJlbCIsImNyZWF0ZUVsZW1lbnQiLCJjYW5QbGF5VHlwZSIsInN1cHBvcnRzRmxhc2hWZXJzaW9uIiwiZGVsaW1pdGVyIiwicmVzb2x2ZUVsZW1lbnQiLCJpZCIsImdldEVsZW1lbnRCeUlkIiwiTm9FbGVtZW50Rm91bmRFcnJvciIsImNyZWF0ZVdlYlNvY2tldCIsInVybCIsInNldFZpZGVvU291cmNlIiwidmlkZW9FbGVtZW50IiwibWVkaWFTdHJlYW0iLCJhdXRvcGxheSIsIm9ubG9hZGVkbWV0YWRhdGEiLCJ2aWRlb1dpZHRoIiwidmlkZW9IZWlnaHQiLCJzcmNPYmplY3QiLCJzcmMiLCJVUkwiLCJjcmVhdGVPYmplY3RVUkwiLCJtYXliZVByb21pc2UiLCJwbGF5IiwidGhlbiIsImNhdGNoIiwic2V0QXR0cmlidXRlIiwicGF1c2UiLCJpbmplY3RTY3JpcHQiLCJkZmQiLCJEZWZlcnJlZFByb21pc2UiLCJzY3JpcHQiLCJvbmxvYWQiLCJyZXNvbHZlIiwib25yZWFkeXN0YXRlY2hhbmdlIiwicmVhZHlTdGF0ZSIsImdldEVsZW1lbnRzQnlUYWdOYW1lIiwiYXBwZW5kQ2hpbGQiLCJwcm9taXNlIiwiZ1VNIiwiY29uc3RyYWludHMiLCJzZXRHbG9iYWwiLCJwcm9wIiwidmFsdWUiLCJnZXRTd2ZPYmplY3QiLCJzd2ZvYmplY3QiLCJnZXRFbWJlZE9iamVjdCIsImdldEVsZW1lbnRJZCIsImdldEF0dHJpYnV0ZSIsImFkZE9yaWVudGF0aW9uQ2hhbmdlSGFuZGxlciIsImhhbmRsZXIiLCJhbmRDYWxsIiwic3VwcG9ydHNPcmllbnRhdGlvbkNoYW5nZSIsImFkZEV2ZW50TGlzdGVuZXIiLCJyZW1vdmVPcmllbnRhdGlvbkNoYW5nZUhhbmRsZXIiLCJzbGljZSIsInJlbW92ZUV2ZW50TGlzdGVuZXIiLCJhZGRDbG9zZUhhbmRsZXIiLCJpbnNlcnRWYWx1ZSIsInNwbGljZSIsInJlbW92ZUNsb3NlSGFuZGxlciIsImludm9rZSIsIm1ldGhvZE5hbWUiLCJkYXRhIiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwidG9nZ2xlRnVsbFNjcmVlbiIsImVsZW1lbnQiLCJ0b2dnbGUiLCJvbkZ1bGxTY3JlZW5TdGF0ZUNoYW5nZSIsImNiIiwib25PcmllbnRhdGlvbk1ldGFkYXRhIiwiaGFzQXR0cmlidXRlRGVmaW5lZCIsImVsZW0iLCJhdHRyaWJ1dGUiLCJhdHQiLCJoYXNDbGFzc0RlZmluZWQiLCJjbGFzc05hbWUiLCJjbGFzc0xpc3QiLCJjb250YWlucyIsInRhZ05hbWUiLCJvcHRzIiwiY3JlYXRlVGV4dE5vZGUiLCJ0b1N0cmluZyIsImFkZFN1YnNjcmlwdGlvbkFzc2lnbm1lbnRIYW5kbGVyIiwic2V0U3Vic2NyaWJlcklkIiwic2hpZnQiLCJnZXRNb3VzZVhGcm9tRXZlbnQiLCJwYWdlWCIsImNsaWVudFgiLCJib2R5Iiwic2Nyb2xsTGVmdCIsImRvY3VtZW50RWxlbWVudCIsImdldFNjcm9sbFgiLCJwYWdlWE9mZnNldCIsInBhcmVudE5vZGUiLCJjcmVhdGVFdmVudCIsIkV2ZW50VHlwZSIsImdldEdsb2JhbCIsIl9EZWZlcnJlZFByb21pc2UiLCJyZWplY3QiLCJfRnV0dXJlIiwiY3JlYXRlSWZOb3RFeGlzdCIsImRlZmVycmVkSWZFeGlzdCIsImYiLCJGdXR1cmUiLCJQdWJsaXNoZXJFdmVudFR5cGVzIiwiUlRDUHVibGlzaGVyRXZlbnRUeXBlcyIsIlJUTVBQdWJsaXNoZXJFdmVudFR5cGVzIiwiRmFpbG92ZXJQdWJsaXNoZXJFdmVudFR5cGVzIiwiU3Vic2NyaWJlckV2ZW50VHlwZXMiLCJSVENTdWJzY3JpYmVyRXZlbnRUeXBlcyIsIlJUTVBTdWJzY3JpYmVyRXZlbnRUeXBlcyIsIkZhaWxvdmVyU3Vic2NyaWJlckV2ZW50VHlwZXMiLCJTaGFyZWRPYmplY3RFdmVudFR5cGVzIiwiRXZlbnQiLCJfdHlwZSIsIl9kYXRhIiwiUHVibGlzaGVyRXZlbnQiLCJwdWJsaXNoZXIiLCJfcHVibGlzaGVyIiwiU3Vic2NyaWJlckV2ZW50Iiwic3Vic2NyaWJlciIsIl9zdWJzY3JpYmVyIiwiU2hhcmVkT2JqZWN0RXZlbnQiLCJzaGFyZWRPYmplY3ROYW1lIiwiX25hbWUiLCJXSUxEQ0FSRCIsIldJTERDQVJEX0tFWSIsIkV2ZW50RW1pdHRlciIsIl9jYWxsYmFja3MiLCJjYWxsYmFja3MiLCJpbmRleE9mIiwiaW5kZXgiLCJfbm90aWZ5IiwiTkFNRSIsIlN1YnNjcmliZXJQbGF5YmFja0NvbnRyb2xsZXIiLCJkdXJhdGlvbiIsIlN1YnNjcmliZXJQbGF5YmFja0NvbnRyb2xzIiwic3RhdGUiLCJTdWJzY3JpYmVyUGxheWJhY2tDb250cm9sc0ltcGwiLCJwbGF5ZXIiLCJjb250YWluZXIiLCJfY29udHJvbGJhciIsIl9wbGF5UGF1c2VCdXR0b24iLCJfbXV0ZUJ1dHRvbiIsIl92b2x1bWVGaWVsZCIsIl9zZWVrVGltZUZpZWxkIiwiX3RpbWVGaWVsZCIsIl9mdWxsU2NyZWVuQnV0dG9uIiwiX3N0YXRlIiwiUGxheWJhY2tTdGF0ZSIsIklETEUiLCJfbXV0ZWRTdGF0ZSIsIl9yZXN1bWVBZnRlclNlZWsiLCJfcGxheWJhY2tEdXJhdGlvbiIsIl92b2x1bWVWYWx1ZSIsIl9vblBsYXlQYXVzZUNsaWNrQm91bmQiLCJfb25QbGF5UGF1c2VDbGljayIsImJpbmQiLCJjb250cm9sYmFyIiwiZW52aXJvbm1lbnQiLCJhZGQiLCJfY3JlYXRlUGxheVBhdXNlQnV0dG9uIiwiX2NyZWF0ZU11dGVCdXR0b24iLCJfY3JlYXRlVm9sdW1lQ29udHJvbCIsIl9jcmVhdGVTZWVrQ29udHJvbCIsIl9jcmVhdGVQbGF5YmFja1RpbWUiLCJfY3JlYXRlRnVsbFNjcmVlblRvZ2dsZSIsInZpZXciLCJyZW1vdmUiLCJzZXRTdGF0ZSIsIm9uRnVsbFNjcmVlbkNoYW5nZSIsInNldFNlZWtUaW1lIiwiZW5hYmxlIiwiZ2V0U3RhdGUiLCJQTEFZSU5HIiwiUEFVU0VEIiwicmVzdW1lIiwiYnV0dG9uIiwic2VsZiIsImdldE11dGVkU3RhdGUiLCJ1bm11dGUiLCJzZXRNdXRlZFN0YXRlIiwibXV0ZSIsInNsaWRlciIsIkNvbnRyb2xTbGlkZXIiLCJvbiIsIlNsaWRlckV2ZW50VHlwZXMiLCJDSEFOR0UiLCJwZXJjZW50YWdlIiwiTnVtYmVyIiwic2V0Vm9sdW1lIiwiQ0hBTkdFX1NUQVJUIiwic2Vla1RvIiwiQ0hBTkdFX0NPTVBMRVRFIiwic3BhbiIsInRleHQiLCJocnMiLCJtaW5zIiwicGFyc2VJbnQiLCJzZWNzIiwiZm9ybWF0dGVkQXJyIiwiam9pbiIsImlubmVyVGV4dCIsImZvcm1hdFRpbWUiLCJNYXRoIiwiZmxvb3IiLCJQbGF5YmFja1N0YXRlUmVhZGFibGUiLCJvblN0YXRlQ2hhbmdlIiwibXV0ZWQiLCJvbk11dGVkU3RhdGVDaGFuZ2UiLCJpc0Z1bGxTY3JlZW4iLCJpc1ZPRCIsImRpc2FibGVkIiwicmVtb3ZlQ2hpbGQiLCJQbGF5YmFja0NvbnRyb2xsZXIiLCJQbGF5YmFja0NvbnRyb2xzIiwiUGxheWJhY2tDb250cm9sc0ltcGwiLCJkZWVwRGVmaW5lIiwib2JqZWN0IiwicGF0aHMiLCJ0YWlsIiwicG9wIiwicGF0aCIsImRlZXBDb3B5Iiwib2JqIiwic3RyIiwiSlNPTiIsInBhcnNlIiwibWV0YWRhdGFSZXNvbHV0aW9uVG9PYmplY3QiLCJkaW1zIiwid2lkdGgiLCJoZWlnaHQiLCJpc09iamVjdEVtcHR5IiwiY29uc3RydWN0b3IiLCJPYmplY3QiLCJQbGF5YmFja1R5cGVzIiwiUlRDIiwiUlRNUCIsIkhMUyIsIlBsYXliYWNrQXVkaW9FbmNvZGVyIiwiT1BVUyIsIlBDTVUiLCJQQ01BIiwiU1BFRVgiLCJOT05FIiwiUGxheWJhY2tWaWRlb0VuY29kZXIiLCJWUDgiLCJIMjY0IiwiVU5BVkFJTEFCTEUiLCJBVkFJTEFCTEUiLCJmb3JtYXRzIiwiaGFzUmVzb2x1dGlvbnNEZWZpbmVkIiwidmlkZW8iLCJnZXRWYWx1ZUZyb21Db25zdHJhaW50QXR0cmlidXRlIiwiZXhhY3QiLCJpZGVhbCIsIm1heCIsIm1pbiIsImlzRXhhY3QiLCJmb3JtYXQiLCJ3IiwiaCIsImNvbmZpcm1lZCIsImlzTG93ZXIiLCJkZXNpcmVkIiwiZGltZW5zaW9ucyIsImhhc01hdGNoaW5nRm9ybWF0IiwiZm9ybWF0c0xpc3QiLCJmaW5kTG93ZXJSZXNvbHV0aW9ucyIsInJlc0lzTG93ZXIiLCJhbGxvd0Jyb3dzZXJUb0RlZmluZVJlc29sdXRpb24iLCJwIiwibWVkaWEiLCJtc2ciLCJmaW5kTmV4dFNlbGVjdGlvbiIsInNlbGVjdGlvbnMiLCJzZWxlY3Rpb24iLCJxdWlja1Jlc29sdXRpb25TdXBwb3J0IiwiZGV0ZXJtaW5lU3VwcG9ydGVkUmVzb2x1dGlvbiIsImRlZmVycmVkIiwiaXNTdXBwb3J0ZWQiLCJfUlRDUGVlckNvbm5lY3Rpb24iLCJfUlRDSWNlQ2FuZGlkYXRlIiwiX1JUQ1Nlc3Npb25EZXNjcmlwdGlvbiIsImlzQXZhaWxhYmxlSW5Gb3JtYXRzIiwiZmFpbG92ZXIiLCJyZXMiLCJhdmFpbGFibGUiLCJmb3JjZVVzZXJNZWRpYSIsInVwZGF0ZUJhbmR3aWR0aCIsIm9wdGlvbnMiLCJzZHAiLCJhX2luZGV4IiwibF9pbmRleCIsImZyb250IiwiYmFjayIsImF1ZGlvIiwiUlRDUGVlckNvbm5lY3Rpb24iLCJtb3pSVENQZWVyQ29ubmVjdGlvbiIsIndlYmtpdFJUQ1BlZXJDb25uZWN0aW9uIiwiUlRDSWNlQ2FuZGlkYXRlIiwibW96UlRDSWNlQ2FuZGlkYXRlIiwid2Via2l0UlRDSWNlQ2FuZGlkYXRlIiwiUlRDU2Vzc2lvbkRlc2NyaXB0aW9uIiwibW96UlRDU2Vzc2lvbkRlc2NyaXB0aW9uIiwid2Via2l0UlRDU2Vzc2lvbkRlc2NyaXB0aW9uIiwiY3JlYXRlIiwicGxheWJhY2tJZCIsIlBsYXliYWNrVmlldyIsImVsZW1lbnRJZCIsIl90YXJnZXRFbGVtZW50Iiwic2V0VmlldyIsImlzQXV0b3BsYXkiLCJQdWJsaXNoVHlwZXMiLCJQdWJsaXNoTW9kZVR5cGVzIiwiTElWRSIsIlJFQ09SRCIsIkFQUEVORCIsIkljZVRyYW5zcG9ydFR5cGVzIiwiVURQIiwiVENQIiwiQ09OTkVDVF9TVUNDRVNTIiwiQ09OTkVDVF9GQUlMVVJFIiwiUFJPUEVSVFlfVVBEQVRFIiwiTUVUSE9EX1VQREFURSIsIndlYnNvY2tldCIsIlNvY2tldEhlbHBlciIsInJlc3BvbmRlciIsIl9yZXNwb25kZXIiLCJfcGVuZGluZ1Bvc3RSZXF1ZXN0cyIsIl93ZWJzb2NrZXQiLCJfY29ubmVjdGlvblByb21pc2UiLCJfcmVzcG9uc2VIYW5kbGVycyIsIl9pc1Rlcm1pbmF0ZWQiLCJfcmV0cnlDb3VudCIsIl9yZXRyeUxpbWl0IiwiX3JlYWR5Q2hlY2tDb3VudCIsIl9yZWFkeUNoZWNrTGltaXQiLCJfb25jbG9zZSIsInRlYXJEb3duIiwiX29ub3BlblRpbWVvdXQiLCJfYXN5bmNUaWNrZXRzIiwid3MiLCJ0aW1lb3V0IiwiY2xlYXJUaW1lb3V0IiwicG9zdCIsIm9uU29ja2V0T3BlbiIsImNsZWFyUmV0cnkiLCJfcmVzZXRPbm9wZW5UaW1lb3V0Iiwib25vcGVuIiwib25tZXNzYWdlIiwib25lcnJvciIsIm9uY2xvc2UiLCJyZXNwb25kIiwiY29kZSIsIm9uU29ja2V0Q2xvc2UiLCJfcmVtb3ZlU29ja2V0SGFuZGxlcnMiLCJkZXRhaWwiLCJzZXR1cFByb21pc2UiLCJfYWRkU29ja2V0SGFuZGxlcnMiLCJzZXRVcCIsImNsb3NlIiwickhhbmRsZXIiLCJzdHJlYW1OYW1lIiwiaGFuZGxlQ2FuZGlkYXRlIiwiY2FuZGlkYXRlIiwic2VuZFJlcXVlc3QiLCJzZW5kIiwicmFuZG9tIiwiYXN5bmMiLCJoYW5kbGVkIiwiaGFuZGxlTWVzc2FnZVJlc3BvbnNlIiwianNvbiIsImdldEpzb25Gcm9tU29ja2V0TWVzc2FnZSIsImlzQXZhaWxhYmxlIiwib25TdHJlYW1BdmFpbGFibGUiLCJvblN0cmVhbVVuYXZhaWxhYmxlIiwidGlja2V0IiwiZmluZCIsIm9uU29ja2V0TWVzc2FnZUVycm9yIiwiX29uVW5leHBlY3RlZFNvY2tldEVycm9yIiwic2hhcmVkT2JqZWN0R2V0UmVtb3RlIiwic2hhcmVkT2JqZWN0Q29ubmVjdCIsImNhbGxOYW1lIiwic2hhcmVkT2JqZWN0U2VuZCIsInBhcmFtcyIsImtleSIsInNoYXJlZE9iamVjdFNldFByb3BlcnR5Iiwic2hhcmVkT2JqZWN0Q2xvc2UiLCJlbmNvZGVLZXlWYWx1ZXMiLCJ2YWx1ZU9iamVjdCIsImVuY29kZWQiLCJmb3JFYWNoIiwiZW5jb2RlVVJJQ29tcG9uZW50IiwicnRjU29ja2V0RW5kcG9pbnRGcm9tT3B0aW9ucyIsInByb3RvY29sIiwid3Nwcm90b2NvbCIsInBvcnQiLCJ3c3BvcnQiLCJhcHBFbmRwb2ludCIsImNvbnRleHQiLCJhcHAiLCJlbmRwb2ludCIsImhvc3QiLCJjb25uZWN0aW9uUGFyYW1zIiwiZW5jb2RlZFBhcmFtcyIsImt2IiwiaGxzU29ja2V0RW5kcG9pbnRGcm9tT3B0aW9ucyIsInNvY2tldFBhcmFtcyIsInB1Ymxpc2hlcklkIiwiUHVibGlzaFZpZXciLCJkZWZpbmVFbWJlZEVsZW1lbnQiLCJ0YXJnZXRFbGVtZW50IiwidGFyZ2V0UGFyZW50Iiwibm9kZU5hbWUiLCJ0b0xvd2VyQ2FzZSIsImRpdiIsInBhcmVudEVsZW1lbnQiLCJlbWJlZFN3Zk9iamVjdCIsImlkTmFtZSIsImZsYXNodmFycyIsInF1YWxpdHkiLCJ3bW9kZSIsImJnY29sb3IiLCJiYWNrZ3JvdW5kQ29sb3IiLCJhbGxvd3NjcmlwdGFjY2VzcyIsImFsbG93ZnVsbHNjcmVlbiIsImFsbG93bmV0d29ya2luZyIsImF0dHJpYnV0ZXMiLCJhbGlnbiIsImhhc0ZsYXNoUGxheWVyVmVyc2lvbiIsIm1pbkZsYXNoVmVyc2lvbiIsImVtYmVkU1dGIiwic3dmIiwiZW1iZWRXaWR0aCIsImVtYmVkSGVpZ2h0IiwicHJvZHVjdEluc3RhbGxVUkwiLCJyZXN1bHQiLCJzdWNjZXNzIiwib3JpZ2luIiwic3R5bGVzIiwidHJhbnNpdGlvbiIsInJvdGF0aW9uVHJhbnNsYXRpb25zIiwidHJhbnNmb3JtIiwidHJhY2tSZXNpemUiLCJyYWYiLCJpc1JvdGF0ZWQiLCJwYXJlbnQiLCJwd2lkdGgiLCJjbGllbnRXaWR0aCIsInBoZWlnaHQiLCJjbGllbnRIZWlnaHQiLCJzdHlsZSIsImV3aWR0aCIsImVoZWlnaHQiLCJtYXJnaW4iLCJwb3NpdGlvbiIsImxlZnQiLCJhcHBseU9yaWVudGF0aW9uIiwicmVzb2x1dGlvbiIsInRyYW5zbGF0aW9ucyIsImF0dGFjaEV2ZW50IiwiUFVCTElTSF9TVEFSVCIsIlBVQkxJU0hfRkFJTCIsIlBVQkxJU0hfSU5WQUxJRF9OQU1FIiwiVU5QVUJMSVNIX1NVQ0NFU1MiLCJQVUJMSVNIX01FVEFEQVRBIiwiQ09OTkVDVElPTl9DTE9TRUQiLCJESU1FTlNJT05fQ0hBTkdFIiwiUFVCTElTSEVSX1JFSkVDVCIsIlBVQkxJU0hFUl9BQ0NFUFQiLCJNRURJQV9TVFJFQU1fQVZBSUxBQkxFIiwiUEVFUl9DT05ORUNUSU9OX0FWQUlMQUJMRSIsIk9GRkVSX1NUQVJUIiwiT0ZGRVJfRU5EIiwiUEVFUl9DQU5ESURBVEVfRU5EIiwiSUNFX1RSSUNLTEVfQ09NUExFVEUiLCJFTUJFRF9TVUNDRVNTIiwiRU1CRURfRkFJTFVSRSIsIlNVQlNDUklCRV9TVEFSVCIsIlNVQlNDUklCRV9TVE9QIiwiU1VCU0NSSUJFX0ZBSUwiLCJTVUJTQ1JJQkVfSU5WQUxJRF9OQU1FIiwiU1VCU0NSSUJFX01FVEFEQVRBIiwiU1VCU0NSSUJFX1NFTkRfSU5WT0tFIiwiUExBWV9VTlBVQkxJU0giLCJPUklFTlRBVElPTl9DSEFOR0UiLCJWT0xVTUVfQ0hBTkdFIiwiUExBWUJBQ0tfVElNRV9VUERBVEUiLCJQTEFZQkFDS19TVEFURV9DSEFOR0UiLCJGVUxMX1NDUkVFTl9TVEFURV9DSEFOR0UiLCJTVUJTQ1JJQkVSX1JFSkVDVCIsIlNVQlNDUklCRVJfQUNDRVBUIiwiQU5TV0VSX1NUQVJUIiwiQU5TV0VSX0VORCIsIkNBTkRJREFURV9TVEFSVCIsIkNBTkRJREFURV9FTkQiLCJPTl9BRERfU1RSRUFNIiwiQUJSX0xFVkVMX0NIQU5HRSIsIlJUTVBTaGFyZWRPYmplY3RIYW5kbGVyIiwiX2VsZW1lbnQiLCJfaGFuZGxlU2hhcmVkT2JqZWN0RXZlbnQiLCJoYW5kbGVTaGFyZWRPYmplY3RFdmVudCIsImVsSWQiLCJoYW5kbGVyTmFtZSIsInNldFNoYXJlZE9iamVjdFJlc3BvbmRlciIsInN3ZklkIiwic2hhcmVkT2JqZWN0U2VuZFByb3BlcnR5IiwiYXNzaWduU2hhcmVkT2JqZWN0UmVzcG9uZGVyIiwiZ2V0UmVtb3RlU2hhcmVkT2JqZWN0IiwiY29ubmVjdFRvU2hhcmVkT2JqZWN0IiwiZGlzY29ubmVjdEZyb21TaGFyZWRPYmplY3QiLCJpbmZsYXRlIiwid3JpdGFibGUiLCJlbnVtZXJhYmxlIiwiUlRDTWVkaWFWaWRlb0NvbnN0cmFpbnQiLCJSVE1QTWVkaWFWaWRlb0NvbnN0cmFpbnQiLCJSVENNZWRpYUNvbnN0cmFpbnQiLCJSVE1QTWVkaWFDb25zdHJhaW50IiwiU2xpZGVyRXZlbnQiLCJjb250cm9sIiwiX2NvbnRyb2wiLCJwdnQiLCJjdHgiLCJoYXMiLCJzZXQiLCJnZXQiLCJJbXBsRmFjdG9yeU9yZGVyIiwibGlzdG9yZGVyIiwiaXRlcmF0b3IiLCJpbml0Rm4iLCJsYXN0RXJyb3IiLCJuZXh0IiwiSW1wbCIsImNvbmNyZXRlIiwib3JkZXIiLCJkb25lIiwiY3VycnkiLCJmeCIsImFyaXR5IiwiZjEiLCJhcmdzIiwiQXJyYXkiLCJwcm90b3R5cGUiLCJhcmd1bWVudHMiLCJhcHBseSIsImYyIiwiYXJnczIiLCJmaWx0ZXIiLCJpZHgiLCJsZW4iLCJ0b0ludCIsInJvdW5kIiwiZ2V0T3JFbHNlIiwiZGVmYXVsdFZhbHVlIiwiZ2V0SW50T3JFbHNlIiwiaXNOYU4iLCJzdWJzY3JpYmVyTGliIiwicHVibGlzaGVyTGliIiwic2hhcmVkT2JqZWN0TGliIiwicGxheWJhY2tFbnVtIiwid2VicnRjRW51bSIsInB1Ymxpc2hlckV2ZW50Iiwic3Vic2NyaWJlckV2ZW50Iiwic2hhcmVkb2JqZWN0RXZlbnQiLCJSZWQ1UHJvU3Vic2NyaWJlciIsIlJUQ1N1YnNjcmliZXIiLCJSVE1QU3Vic2NyaWJlciIsIkhMU1N1YnNjcmliZXIiLCJSZWQ1UHJvUHVibGlzaGVyIiwiUlRDUHVibGlzaGVyIiwiUlRNUFB1Ymxpc2hlciIsIlB1Ymxpc2hlclZpZXciLCJSZWQ1UHJvU2hhcmVkT2JqZWN0Iiwic2V0TG9nTGV2ZWwiLCJ0b1VwcGVyQ2FzZSIsImNvbnNvbGUiLCJsb2ciLCJMT0dfTEVWRUxTIiwiX2dldExvZ2dlciIsImpzb25BdHRyIiwianNvblZhbCIsInJlYWRVVEYiLCJzdGFydCIsIm9mZnNldCIsImVuZCIsIlN0cmluZyIsImZyb21DaGFyQ29kZSIsInBhcnNlSlNPTkZvck9yaWVudGF0aW9uIiwiZXhlYyIsIm1hdGNoMiIsImNhbGxiYWNrIiwidGV4dFRyYWNrcyIsImFkZFRleHRUcmFjayIsInRyYWNrIiwiYWRkVHJhY2tFdmVudCIsIm1vZGUiLCJjdWVzIiwiY3VlQ2hhbmdlRXZlbnQiLCJjdXJyZW50VGFyZ2V0IiwiYWN0aXZlQ3VlcyIsInNpemUiLCJOb1N1cHBvcnRlZENhbWVyYVJlc29sdXRpb25zRXJyb3IiLCJQdWJsaXNoZXJTb2NrZXRIZWxwZXIiLCJvblNEUEFuc3dlciIsIm9uRW1wdHlDYW5kaWRhdGUiLCJvbkFkZEljZUNhbmRpZGF0ZSIsIm9uU29ja2V0SWNlQ2FuZGlkYXRlRW5kIiwib25QdWJsaXNoZXJTdGF0dXMiLCJTdWJzY3JpcHRpb25Tb2NrZXRIZWxwZXIiLCJvblNEUE9mZmVyIiwib25VbnB1Ymxpc2giLCJvbkNvbm5lY3Rpb25DbG9zZWQiLCJvblN1YnNjcmliZXJTdGF0dXMiLCJzdGF0dXMiLCJtZXRob2QiLCJvblNlbmRSZWNlaXZlZCIsIm9uTWV0YURhdGEiLCJtZXRhZGF0YSIsIndlYnJ0YyIsIlB1Ymxpc2hlclBlZXJIZWxwZXIiLCJfcGVlckNvbm5lY3Rpb24iLCJjb25uZWN0aW9uIiwib25jb25uZWN0aW9uc3RhdGVjaGFuZ2UiLCJvbmljZWNvbm5lY3Rpb25zdGF0ZWNoYW5nZSIsIm9uaWNlY2FuZGlkYXRlIiwicmVjb25uZWN0VGltZW91dCIsInRpbWVvdXRMaW1pdCIsImNvbm5lY3Rpb25TdGF0ZSIsIm9uSWNlQ2FuZGlkYXRlIiwiaWNlQ29ubmVjdGlvblN0YXRlIiwib25QZWVyQ29ubmVjdGlvbkNsb3NlIiwib25zaWduYWxpbmdzdGF0ZWNoYW5nZSIsInNpZ25hbGluZ1N0YXRlIiwib25pY2VnYXRoZXJpbmdzdGF0ZWNoYW5nZSIsImljZUdhdGhlcmluZ1N0YXRlIiwib25QZWVyR2F0aGVyaW5nQ29tcGxldGUiLCJvbnJlbW92ZXN0cmVhbSIsImJhbmR3aWR0aCIsIm9mZmVyUHJvbWlzZSIsImNyZWF0ZU9mZmVyIiwic2Vzc2lvbkRlc2NyaXB0aW9uIiwic2V0TG9jYWxEZXNjcmlwdGlvbiIsIm9uU0RQU3VjY2VzcyIsIm9uU0RQRXJyb3IiLCJzZXRSZW1vdGVEZXNjcmlwdGlvbiIsImFkZEljZUNhbmRpZGF0ZSIsImljZVNlcnZlcnMiLCJzZXRVcFByb21pc2UiLCJydGNwTXV4UG9saWN5IiwicGVlckNvbmZpZyIsImljZUNhbmRpZGF0ZVBvb2xTaXplIiwiYnVuZGxlUG9saWN5IiwicGVlciIsIm9wdGlvbmFsIiwiUnRwRGF0YUNoYW5uZWxzIiwiZ29vZ0NwdU92ZXJ1c2VEZXRlY3Rpb24iLCJfYWRkQ29ubmVjdGlvbkhhbmRsZXJzIiwiX3JlbW92ZUNvbm5lY3Rpb25IYW5kbGVycyIsImlzRW1wdHlDYW5kaWRhdGUiLCJTdWJzY3JpcHRpb25QZWVySGVscGVyIiwiX3BlbmRpbmdNZWRpYVN0cmVhbSIsIm9udHJhY2siLCJvbkljZUNhbmRpZGF0ZVRyaWNrbGVFbmQiLCJvbkFuc3dlck1lZGlhU3RyZWFtIiwiY3JlYXRlQW5zd2VyIiwiaWNlQ2FuZGlkYXRlIiwic2RwTUxpbmVJbmRleCIsInJlYyIsInRvSVNPU3RyaW5nIiwibmFtZUZyb21MZXZlbCIsInB1Ymxpc2hGYWN0b3J5IiwicHVibGlzaGVySW1wbCIsIl9vcHRpb25zIiwiX29yZGVyIiwidCIsImVudHJ5IiwiX2dldFB1Ymxpc2hlckZyb21PcmRlciIsImVtYmVkIiwiY29udmVydERpbWVuc2lvbk9wdGlvbnMiLCJ2byIsIm1lZGlhQ29uc3RyYWludHNUb0ZsYXNodmFycyIsImZ2IiwiUHVibGlzaGVyU291cmNlSGFuZGxlciIsInNvUmVzcG9uZGVyIiwiY2xvbmUiLCJjbG9uZU5vZGUiLCJob2xkZXIiLCJfcHVibGlzaGVyVHlwZSIsIl9zd2ZJZCIsIl9lbWJlZEZ1dHVyZSIsIl9zb1Jlc3BvbmRlciIsInN3ZlVybCIsImJ1ZmZlciIsInN0cmVhbU1vZGUiLCJhcHBOYW1lIiwicm9vbU5hbWUiLCJhdXRvc2l6ZSIsIm1lZGlhQ29uc3RyYWludHMiLCJwdWJsaXNoT3B0aW9ucyIsImNvbm5lY3QiLCJkaXNjb25uZWN0IiwiY2xlYW5VcCIsImFkZFJlc3BvbnNlSGFuZGxlciIsInJlbW92ZVJlc3BvbnNlSGFuZGxlciIsInNlbmRUb1NoYXJlZE9iamVjdCIsInNlbmRQcm9wZXJ0eVRvU2hhcmVkT2JqZWN0IiwiY2xvc2VTaGFyZWRPYmplY3QiLCJ1cGRhdGVSZXNvbHV0aW9uIiwicHViU3RhcnRSZWdleCIsInB1YlN0b3BSZWdleCIsImRlZmF1bHRPcHRpb25zIiwibWVkaWFFbGVtZW50SWQiLCJ1cmxzIiwiaWNlVHJhbnNwb3J0Iiwib25HZXRVc2VyTWVkaWEiLCJfdmlldyIsIl9wZWVySGVscGVyIiwiX3NvY2tldEhlbHBlciIsIl9tZWRpYVN0cmVhbSIsIl9zdHJlYW1GdXR1cmUiLCJfYXZhaWxhYmxlRnV0dXJlIiwiX3BlZXJGdXR1cmUiLCJfb2ZmZXJGdXR1cmUiLCJfc2VuZE9mZmVyRnV0dXJlIiwiX3RyaWNrbGVFbmRGdXR1cmUiLCJfcHVibGlzaEZ1dHVyZSIsIl91bnB1Ymxpc2hGdXR1cmUiLCJfb25PcmllbnRhdGlvbkNoYW5nZSIsInRyaWdnZXIiLCJyZWoiLCJfZ3VtIiwiZGV2aWNlT3JpZW50YXRpb24iLCJwcmV2aWV3IiwiY3VycmVudFZpZXciLCJhdHRhY2hQdWJsaXNoZXIiLCJidW5kbGUiLCJ0cmFuc3BvcnQiLCJfc2VuZE9mZkZ1dHVyZSIsImhhbmRsZU9mZmVyIiwicHVibGlzaCIsInVucHVibGlzaCIsIl9nZXRNZWRpYVN0cmVhbSIsIl9vbk1lZGlhU3RyZWFtUmVjZWl2ZWQiLCJfc2V0Vmlld0lmTm90RXhpc3QiLCJzb2NrZXRQcm9taXNlIiwic29ja2V0dXJsIiwiX2dldFRyaWNrbGVFbmQiLCJfcmVxdWVzdEF2YWlsYWJpbGl0eSIsInN0cmVhbVR5cGUiLCJfY3JlYXRlUGVlckNvbm5lY3Rpb24iLCJhZGRTdHJlYW0iLCJfY3JlYXRlT2ZmZXIiLCJfc2VuZE9mZmVyIiwiX3NldFJlbW90ZURlc2NyaXB0aW9uIiwiX3JlcXVlc3RQdWJsaXNoIiwiY2xlYXJIZWxwZXJzIiwiX3JlcXVlc3RVbnB1Ymxpc2giLCJtdXRlQXVkaW8iLCJ1bm11dGVBdWRpbyIsIm11dGVWaWRlbyIsInBvc3RBc3luYyIsImNhbGxBZGFwdGVyIiwicmVjZWlwdCIsImNsb3NlRXZlbnQiLCJfc2VuZENhbmRpZGF0ZSIsInBvc3RFbmRPZkNhbmRpZGF0ZXMiLCJzdG9wUmVzdWx0Iiwic3RhcnRSZXN1bHQiLCJuZXdPcHRpb25zIiwic3dmb2JqZWN0VVJMIiwiX3NvdXJjZUhhbmRsZXIiLCJfZWxlbWVudElkIiwiX2Nvbm5lY3RGdXR1cmUiLCJnZXRUeXBlIiwiYWRkU291cmNlIiwic2V0QWN0aXZlSWQiLCJzdWNjZXNzSWQiLCJfdGVhckRvd25Db25uZWN0Q2FsbGJhY2siLCJpbnZva2VGbiIsImxhYmVsIiwiX3NldFVwQ29ubmVjdENhbGxiYWNrIiwic3JjSGFuZGxlciIsImdldEVtYmVkT3BlcmF0aW9uIiwiX2VzdGFibGlzaEV4dEludEhhbmRsZXJzIiwiY291bnQiLCJsaW1pdCIsInRyeUNvbm5lY3QiLCJzZXRNZWRpYVF1YWxpdHkiLCJTT19TVUJUWVBFX1BST1BFUlRZIiwiU09fU1VCVFlQRV9NRVRIT0QiLCJzb05hbWUiLCJkZWNvZGVNZXNzYWdlSWZKU09OU3RyaW5nIiwiUHJvcGVydHlEYXRhIiwiTWV0aG9kRGF0YSIsIm1lc3NhZ2VMaXN0IiwiX3NvY2tldCIsImdldENvbm5lY3Rpb24iLCJhZGRTaGFyZWRPYmplY3RSZXNwb25zZUhhbmRsZXIiLCJ0b09iamVjdCIsImV2ZW50cyIsInN1YnR5cGUiLCJfZ2V0SnNvbkZyb21Tb2NrZXRNZXNzYWdlIiwiX25vdGlmeU9mRXZlbnRzIiwiX25vdGlmeU9mUHJvcGVydHlWYWx1ZXMiLCJtZXNzYWdlTmFtZSIsInJlbW92ZVNoYXJlZE9iamVjdFJlc3BvbnNlSGFuZGxlciIsIl9jb250YWluZXIiLCJfYnV0dG9uIiwiY3JlYXRlQnV0dG9uIiwiX3RyYWNrIiwiY3JlYXRlVHJhY2siLCJfcHJvZ3Jlc3NCYXIiLCJjcmVhdGVQcm9ncmVzc0JhciIsIl92YWx1ZSIsIl9kaXNhYmxlZCIsIl9ldmVudFN0YXJ0UG9zaXRpb24iLCJfbGF5b3V0IiwiX21vdXNldXBIYW5kbGVyIiwiX21vdXNldXAiLCJfbW91c2Vkb3duSGFuZGxlciIsIl9tb3VzZWRvd24iLCJfbW91c2Vtb3ZlSGFuZGxlciIsIl9tb3VzZW1vdmUiLCJfdG91Y2h1cEhhbmRsZXIiLCJfdG91Y2hwcm94eSIsIl90b3VjaGRvd25IYW5kbGVyIiwiX3RvdWNobW92ZUhhbmRsZXIiLCJfdXBkYXRlSGFuZGxlcnMiLCJwcmV2ZW50RGVmYXVsdCIsInRvdWNoZXMiLCJldnQiLCJ0b3VjaCIsIm9yaWdpbmFsVGFyZ2V0IiwidGFyZ2V0IiwiY2hhbmdlZFRvdWNoZXMiLCJpbml0TW91c2VFdmVudCIsIm93bmVyRG9jdW1lbnQiLCJkZWZhdWx0VmlldyIsInNjcmVlblgiLCJzY3JlZW5ZIiwiY2xpZW50WSIsImN0cmxLZXkiLCJhbHRLZXkiLCJzaGlmdEtleSIsIm1ldGFLZXkiLCJkaXNwYXRjaEV2ZW50IiwicG9zaXRpb25PZmZzZXQiLCJyZWN0IiwiZ2V0Qm91bmRpbmdDbGllbnRSZWN0IiwiaXNEaXNhYmxlZCIsInBlcmNlbnRWYWx1ZSIsImJvb2wiLCJwbGF5YmFja0ZhY3RvcnkiLCJwbGF5YmFja0ltcGwiLCJfZ2V0UGxheWJhY2tGcm9tT3JkZXIiLCJnZW5lcmF0ZVN1YnNjcmlwdGlvbklkIiwibWltZVR5cGUiLCJhdXRvTGF5b3V0T3JpZW50YXRpb24iLCJzdWJzY3JpcHRpb25JZCIsIm9wdGlvbnNUb0hsc1VSTCIsImhsc3Byb3RvY29sIiwiaGxzcG9ydCIsIl92aWV3UmVzb2x2ZXIiLCJfc3Vic2NyaXB0aW9uUmVzb2x2ZXIiLCJfYm91bmRCdWJibGVTdWJzY3JpYmVyRXZlbnRzIiwiYnViYmxlU3Vic2NyaWJlckV2ZW50cyIsInN0b3AiLCJhdHRhY2hTdWJzY3JpYmVyIiwidXJsUmVnZXgiLCJfZ2V0Vmlld1Jlc29sdmVyUHJvbWlzZSIsIkhMU1NvdXJjZUhhbmRsZXIiLCJfZ2xvbVNvdXJjZUhhbmRsZXJBUEkiLCJfaW5pdEhhbmRsZXIiLCJfZ2V0U3Vic2NyaXB0aW9uUmVzb2x2ZXJQcm9taXNlIiwiZ2V0Q29udHJvbHMiLCJzdWJTdGFydFJlZ2V4IiwibWFpbnRhaW5Db25uZWN0aW9uT25TdWJzY3JpYmVFcnJvcnMiLCJfY29ubmVjdGlvbkNsb3NlZCIsIl9hdmFpbGFiaWxpdHlSZXNvbHZlciIsIl9vcmllbnRhdGlvbiIsInZFbmNvZGluZyIsImFFbmNvZGluZyIsIm9mZmVyIiwicmVxdWVzdE9mZmVyIiwicmVxdWVzdElkIiwidmlkZW9FbmNvZGluZyIsImF1ZGlvRW5jb2RpbmciLCJfc2VuZEFuc3dlciIsImhhbmRsZUFuc3dlciIsIl9yZXF1ZXN0T2ZmZXIiLCJzdWJzY3JpYmUiLCJfZGlzY29ubmVjdCIsIlJUQ1NvdXJjZUhhbmRsZXIiLCJfZ2V0QXZhaWxhYmlsaXR5UmVzb2x2ZXJQcm9taXNlIiwiX2Nvbm5lY3QiLCJfcmVxdWVzdEFuc3dlciIsImF0dGFjaFN0cmVhbSIsIl9zZW5kU3Vic2NyaWJlIiwiX3BsYXlJZkF1dG9wbGF5U2V0IiwiaGFuZGxlT3JpZW50YXRpb25DaGFuZ2UiLCJ2aWV3RWxlbWVudCIsInN0YW5kYnkiLCJwcm9kdWN0SW5zdGFsbFVybCIsInVzZUFkYXB0aXZlQml0cmF0ZUNvbnRyb2xsZXIiLCJhYnJWYXJpYW50cyIsImFiclZhcmlhbnRVcGdyYWRlU2V0dGluZ3MiLCJtaW5pbXVtRG93bmdyYWRlUGxheWJhY2tTcGFuIiwidXBncmFkZSIsInJldHJ5VGltZW91dCIsIl9lbWJlZFByb21pc2UiLCJfZ2V0RW1iZWRQcm9taXNlIiwib25FbWJlZENvbXBsZXRlIiwib25FbWJlZEZhaWx1cmUiLCJzZXRBQlJMZXZlbCIsInNldEFCUlZhcmlhbnRzIiwic3RvcEFCUkNvbnRyb2xsZXIiLCJzdGFydEFCUkNvbnRyb2xsZXIiLCJzZXRBQlJWYXJpYW50VXBncmFkZVNldHRpbmdzIiwicGF5bG9hZCIsInZvbHVtZSIsInNldHRpbmdzIiwiZGVjb2RlVVJJQ29tcG9uZW50IiwiZXN0YWJsaXNoU291cmNlSGFuZGxlciIsIlJUTVBTb3VyY2VIYW5kbGVyIiwic3Vic2NyaWJlcklkIiwiZW1iZWREZmQiLCJnZXRFbWJlZGRlZFZpZXciLCJfZGV0ZXJtaW5lSG9sZGVyIiwicGxheWVyVHlwZSIsIl9pc1ZPRCIsIl9jb250cm9scyIsIl9wbGF5YmFja05vdGlmaWNhdGlvbkNlbnRlciIsIl9oYW5kbGVGdWxsU2NyZWVuQ2hhbmdlIiwiaW5zZXJ0QmVmb3JlIiwiZWxQYXJlbnQiLCJtZWRpYUhvbGRlciIsImRldGFjaCIsIm5vdGlmaWVyIiwiY29udHJvbHMiLCJoYXNDb250cm9scyIsIm9uY2FucGxheSIsIm9uZHVyYXRpb25jaGFuZ2UiLCJzZXRQbGF5YmFja0R1cmF0aW9uIiwib25lbmRlZCIsIm9udGltZXVwZGF0ZSIsImN1cnJlbnRUaW1lIiwib25zZWVrZWQiLCJvbnNlZWtpbmciLCJvbnBsYXkiLCJvbnBhdXNlIiwib252b2x1bWVjaGFuZ2UiLCJnZXRWb2x1bWUiLCJvbmVuY3J5cHRlZCIsIm9uZW1wdGllZCIsIm9ubG9hZGVkZGF0YSIsIm9ubG9hZHN0YXJ0Iiwib25zdGFsbGVkIiwib25zdXNwZW5kIiwib253YWl0aW5nIiwiZmlyc3RDaGlsZCIsImhhc0RlZmluZWRDb250cm9scyIsImlzTXV0ZWQiLCJ1c2VQbGF5YmFja0NvbnRyb2xzIiwiX2VtYmVkTWVkaWFTb3VyY2UiLCJzZXRBc1ZPRCIsIl9hZGRQbGF5YmFja0hhbmRsZXJzIiwiX2NsZWFuVXAiLCJpc1ZPRFN0cmVhbU5hbWUiLCJ0ZXN0Iiwibm90aWZpY2F0aW9uQ2VudGVyIiwiX3RlYXJEb3duSW5pdENhbGxiYWNrIiwiX3NldFVwSW5pdENhbGxiYWNrIiwiZW1iZWRkZWQiLCJjbGF6eiIsImZpcm0iLCJhYnJWYXJpYW50VXBncmFkZXMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNELE87QUNWQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsbURBQTJDLGNBQWM7O0FBRXpEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsbUNBQTJCLDBCQUEwQixFQUFFO0FBQ3ZELHlDQUFpQyxlQUFlO0FBQ2hEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDhEQUFzRCwrREFBK0Q7O0FBRXJIO0FBQ0E7O0FBRUE7QUFDQTs7Ozs7Ozs7QUNoRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFOzs7Ozs7O0FDUkE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUEsc0NBQXNDLHVDQUF1QyxnQkFBZ0I7O0FBRTdGO0FBQ0E7QUFDQSxtQkFBbUIsa0JBQWtCO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLEc7Ozs7Ozs7QUMxQkQ7Ozs7Ozs7QUFFQTs7QUFDQTs7QUFFQSxJQUFJQSxlQUFKOztBQUVBLElBQU1DLGdCQUFnQixTQUFoQkEsYUFBZ0IsQ0FBQ0MsVUFBRCxFQUFnQjtBQUNwQyxTQUFPLG1CQUFXO0FBQ2hCLGlCQUFXQSxVQUFYLFVBQTBCQyxPQUExQjtBQUNELEdBRkQ7QUFHRCxD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QUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLE9BQU87QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUIsNkJBQTZCO0FBQ2hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJB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LEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0EsV0FBVztBQUNYOztBQUVBO0FBQ0E7QUFDQSx3Q0FBd0MsV0FBVztBQUNuRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwyQkFBMkI7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLG9DQUFvQyxjQUFjO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxpQ0FBaUMsa0JBQWtCO0FBQ25EO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxpQkFBaUI7O0FBRWpCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QixpQkFBaUI7QUFDekM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxZQUFZO0FBQ1o7QUFDQTs7QUFFQTtBQUNBLFlBQVk7QUFDWjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLDhDQUE4QyxRQUFRO0FBQ3REO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTs7QUFFQSxXQUFXO0FBQ1g7QUFDQTtBQUNBOztBQUVBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7O0FBRUEsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBLDhDQUE4QyxRQUFRO0FBQ3REO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQSxLQUFLOztBQUVMO0FBQ0EsOENBQThDLFFBQVE7QUFDdEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0EsOENBQThDLFFBQVE7QUFDdEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0EsZUFBZSxjQUFjO0FBQzdCIiwiZmlsZSI6InJlZDVwcm8tc2RrLmpzIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIHdlYnBhY2tVbml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uKHJvb3QsIGZhY3RvcnkpIHtcblx0aWYodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnKVxuXHRcdG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSgpO1xuXHRlbHNlIGlmKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZClcblx0XHRkZWZpbmUoW10sIGZhY3RvcnkpO1xuXHRlbHNlIGlmKHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0Jylcblx0XHRleHBvcnRzW1wicmVkNXByb3Nka1wiXSA9IGZhY3RvcnkoKTtcblx0ZWxzZVxuXHRcdHJvb3RbXCJyZWQ1cHJvc2RrXCJdID0gZmFjdG9yeSgpO1xufSkodGhpcywgZnVuY3Rpb24oKSB7XG5yZXR1cm4gXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIHdlYnBhY2svdW5pdmVyc2FsTW9kdWxlRGVmaW5pdGlvbiIsIiBcdC8vIFRoZSBtb2R1bGUgY2FjaGVcbiBcdHZhciBpbnN0YWxsZWRNb2R1bGVzID0ge307XG5cbiBcdC8vIFRoZSByZXF1aXJlIGZ1bmN0aW9uXG4gXHRmdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG5cbiBcdFx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG4gXHRcdGlmKGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdKSB7XG4gXHRcdFx0cmV0dXJuIGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdLmV4cG9ydHM7XG4gXHRcdH1cbiBcdFx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcbiBcdFx0dmFyIG1vZHVsZSA9IGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdID0ge1xuIFx0XHRcdGk6IG1vZHVsZUlkLFxuIFx0XHRcdGw6IGZhbHNlLFxuIFx0XHRcdGV4cG9ydHM6IHt9XG4gXHRcdH07XG5cbiBcdFx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG4gXHRcdG1vZHVsZXNbbW9kdWxlSWRdLmNhbGwobW9kdWxlLmV4cG9ydHMsIG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xuXG4gXHRcdC8vIEZsYWcgdGhlIG1vZHVsZSBhcyBsb2FkZWRcbiBcdFx0bW9kdWxlLmwgPSB0cnVlO1xuXG4gXHRcdC8vIFJldHVybiB0aGUgZXhwb3J0cyBvZiB0aGUgbW9kdWxlXG4gXHRcdHJldHVybiBtb2R1bGUuZXhwb3J0cztcbiBcdH1cblxuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZXMgb2JqZWN0IChfX3dlYnBhY2tfbW9kdWxlc19fKVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5tID0gbW9kdWxlcztcblxuIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGUgY2FjaGVcbiBcdF9fd2VicGFja19yZXF1aXJlX18uYyA9IGluc3RhbGxlZE1vZHVsZXM7XG5cbiBcdC8vIGlkZW50aXR5IGZ1bmN0aW9uIGZvciBjYWxsaW5nIGhhcm1vbnkgaW1wb3J0cyB3aXRoIHRoZSBjb3JyZWN0IGNvbnRleHRcbiBcdF9fd2VicGFja19yZXF1aXJlX18uaSA9IGZ1bmN0aW9uKHZhbHVlKSB7IHJldHVybiB2YWx1ZTsgfTtcblxuIFx0Ly8gZGVmaW5lIGdldHRlciBmdW5jdGlvbiBmb3IgaGFybW9ueSBleHBvcnRzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSBmdW5jdGlvbihleHBvcnRzLCBuYW1lLCBnZXR0ZXIpIHtcbiBcdFx0aWYoIV9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBuYW1lKSkge1xuIFx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBuYW1lLCB7XG4gXHRcdFx0XHRjb25maWd1cmFibGU6IGZhbHNlLFxuIFx0XHRcdFx0ZW51bWVyYWJsZTogdHJ1ZSxcbiBcdFx0XHRcdGdldDogZ2V0dGVyXG4gXHRcdFx0fSk7XG4gXHRcdH1cbiBcdH07XG5cbiBcdC8vIGdldERlZmF1bHRFeHBvcnQgZnVuY3Rpb24gZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBub24taGFybW9ueSBtb2R1bGVzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm4gPSBmdW5jdGlvbihtb2R1bGUpIHtcbiBcdFx0dmFyIGdldHRlciA9IG1vZHVsZSAmJiBtb2R1bGUuX19lc01vZHVsZSA/XG4gXHRcdFx0ZnVuY3Rpb24gZ2V0RGVmYXVsdCgpIHsgcmV0dXJuIG1vZHVsZVsnZGVmYXVsdCddOyB9IDpcbiBcdFx0XHRmdW5jdGlvbiBnZXRNb2R1bGVFeHBvcnRzKCkgeyByZXR1cm4gbW9kdWxlOyB9O1xuIFx0XHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQoZ2V0dGVyLCAnYScsIGdldHRlcik7XG4gXHRcdHJldHVybiBnZXR0ZXI7XG4gXHR9O1xuXG4gXHQvLyBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGxcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubyA9IGZ1bmN0aW9uKG9iamVjdCwgcHJvcGVydHkpIHsgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIHByb3BlcnR5KTsgfTtcblxuIFx0Ly8gX193ZWJwYWNrX3B1YmxpY19wYXRoX19cbiBcdF9fd2VicGFja19yZXF1aXJlX18ucCA9IFwiXCI7XG5cbiBcdC8vIExvYWQgZW50cnkgbW9kdWxlIGFuZCByZXR1cm4gZXhwb3J0c1xuIFx0cmV0dXJuIF9fd2VicGFja19yZXF1aXJlX18oX193ZWJwYWNrX3JlcXVpcmVfXy5zID0gMjA4KTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyB3ZWJwYWNrL2Jvb3RzdHJhcCAzMmI4YWE2NTUyMmNkMjhjYTUyNyIsIlwidXNlIHN0cmljdFwiO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5leHBvcnRzLmRlZmF1bHQgPSBmdW5jdGlvbiAoaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7XG4gIGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTtcbiAgfVxufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vYmFiZWwtcnVudGltZS9oZWxwZXJzL2NsYXNzQ2FsbENoZWNrLmpzXG4vLyBtb2R1bGUgaWQgPSAwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIlwidXNlIHN0cmljdFwiO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG52YXIgX2RlZmluZVByb3BlcnR5ID0gcmVxdWlyZShcIi4uL2NvcmUtanMvb2JqZWN0L2RlZmluZS1wcm9wZXJ0eVwiKTtcblxudmFyIF9kZWZpbmVQcm9wZXJ0eTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9kZWZpbmVQcm9wZXJ0eSk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmV4cG9ydHMuZGVmYXVsdCA9IGZ1bmN0aW9uICgpIHtcbiAgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTtcbiAgICAgIGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTtcbiAgICAgIGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTtcbiAgICAgIGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7XG4gICAgICAoMCwgX2RlZmluZVByb3BlcnR5Mi5kZWZhdWx0KSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykge1xuICAgIGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7XG4gICAgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7XG4gICAgcmV0dXJuIENvbnN0cnVjdG9yO1xuICB9O1xufSgpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9iYWJlbC1ydW50aW1lL2hlbHBlcnMvY3JlYXRlQ2xhc3MuanNcbi8vIG1vZHVsZSBpZCA9IDFcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiJ3VzZSBzdHJpY3QnXG5cbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gJ2Jyb3dzZXItYnVueWFuJ1xuaW1wb3J0IHsgUmF3U3RyZWFtIH0gZnJvbSAnLi9idW55YW4td3JpdGVyJ1xuXG5sZXQgbG9nZ2VyXG5cbmNvbnN0IGZvcm1hdE1lc3NhZ2UgPSAoZGlzcGF0Y2hlcikgPT4ge1xuICByZXR1cm4gbWVzc2FnZSA9PiB7XG4gICAgcmV0dXJuIGAoJHtkaXNwYXRjaGVyfSkgJHttZXNzYWdlfWBcbiAgfVxufVxuXG5jb25zdCBkZWNvcmF0ZSA9IChsZXZlbCkgPT4ge1xuICByZXR1cm4gKHNvdXJjZSwgbWVzc2FnZSkgPT4ge1xuICAgIGxvZ2dlcltsZXZlbF0oZm9ybWF0TWVzc2FnZShzb3VyY2UpKG1lc3NhZ2UpKVxuICB9XG59XG5cbi8qXG4gKiBUaGUgbG9nIGxldmVscyBzdXBwb3J0ZWQuXG4gKi9cbmV4cG9ydCBjb25zdCBMRVZFTFMgPSB7XG4gIFRSQUNFOiAndHJhY2UnLFxuICBJTkZPOiAnaW5mbycsXG4gIERFQlVHOiAnZGVidWcnLFxuICBXQVJOOiAnd2FybicsXG4gIEVSUk9SOiAnZXJyb3InLFxuICBGQVRBTDogJ2ZhdGFsJ1xufVxuXG4vKipcbiAqIEVzdGFibGlzaCBsb2dnZXIgdG8gdXNlIGF0IGxldmVsLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBsZXZlbFxuICogICAgICAgIFRoZSBsZXZlbCB0eXBlIGZyb20gYExFVkVMU2AuXG4gKiBAcGFyYW0ge0FycmF5fSBzdHJlYW1MaXN0XG4gKiAgICAgICAgVGhlIHN0cmVhbUxpc3QgdG8gdXNlIGluIGNyZWF0aW5nIGJ1bnlvbi1iYXNlZCBsb2dnZXIuXG4gKlxuICogQHByaXZhdGVcbiAqL1xuZXhwb3J0IGNvbnN0IGVzdGFibGlzaExvZ2dlciA9IChsZXZlbCwgc3RyZWFtTGlzdCA9IHVuZGVmaW5lZCkgPT4ge1xuICBsZXQgc3RyZWFtcyA9IFtdXG4gIHN0cmVhbXMucHVzaCh7XG4gICAgbGV2ZWw6IGxldmVsLFxuICAgIHN0cmVhbTogbmV3IFJhd1N0cmVhbSgpLFxuICAgIHR5cGU6ICdyYXcnXG4gIH0pXG4gIGlmIChzdHJlYW1MaXN0KSB7XG4gICAgY29uc3QgbGlzdCA9IHN0cmVhbUxpc3QubWFwKGl0ZW0gPT4ge1xuICAgICAgaXRlbS5sZXZlbCA9IGxldmVsXG4gICAgfSlcbiAgICBzdHJlYW1zID0gc3RyZWFtcy5jb25jYXQobGlzdClcbiAgfVxuICBsb2dnZXIgPSBjcmVhdGVMb2dnZXIoe1xuICAgIGxldmVsOiBsZXZlbCxcbiAgICBuYW1lOiAncmVkNXByby1zZGsnLFxuICAgIHN0cmVhbXM6IHN0cmVhbXNcbiAgfSlcbn1cblxuLyoqXG4gKiBSZXR1cm4gdGhlIGRldGVybWluZWQgbG9nZ2VyIGluc3RhbmNlLlxuICpcbiAqIEByZXR1cm4ge09iamVjdH1cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5leHBvcnQgY29uc3QgZ2V0TG9nZ2VyID0gKCkgPT4ge1xuICByZXR1cm4gbG9nZ2VyXG59XG5cbi8qIFF1aWNrIGFjY2VzcyB0byBsb2dnZXIgbGV2ZWwgdHlwZXMuICovXG5leHBvcnQgY29uc3QgdHJhY2UgPSBkZWNvcmF0ZShMRVZFTFMuVFJBQ0UpXG5leHBvcnQgY29uc3QgaW5mbyA9IGRlY29yYXRlKExFVkVMUy5JTkZPKVxuZXhwb3J0IGNvbnN0IGRlYnVnID0gZGVjb3JhdGUoTEVWRUxTLkRFQlVHKVxuZXhwb3J0IGNvbnN0IHdhcm4gPSBkZWNvcmF0ZShMRVZFTFMuV0FSTilcbmV4cG9ydCBjb25zdCBlcnJvciA9IGRlY29yYXRlKExFVkVMUy5FUlJPUilcbmV4cG9ydCBjb25zdCBmYXRhbCA9IGRlY29yYXRlKExFVkVMUy5GQVRBTClcblxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2pzL2xvZy9pbmRleC5qcyIsInZhciBjb3JlID0gbW9kdWxlLmV4cG9ydHMgPSB7dmVyc2lvbjogJzIuNC4wJ307XG5pZih0eXBlb2YgX19lID09ICdudW1iZXInKV9fZSA9IGNvcmU7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2NvcmUuanNcbi8vIG1vZHVsZSBpZCA9IDNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiaW1wb3J0IHsgRGVmZXJyZWRQcm9taXNlIH0gZnJvbSAnLi4vdXRpbC9wcm9taXNlJ1xuaW1wb3J0IHsgTm9FbGVtZW50Rm91bmRFcnJvciB9IGZyb20gJy4uL2V4Y2VwdGlvbi9lcnJvcnMnXG5pbXBvcnQgeyBvbk9yaWVudGF0aW9uTWV0YWRhdGEgfSBmcm9tICcuL21ldGFkYXRhLXV0aWwnXG5pbXBvcnQgeyBkZWJ1ZywgZXJyb3IsIHdhcm4gfSBmcm9tICcuLi9sb2cnXG5cbmxldCBydG1wU3Vic2NyaWJlckFzc2lnbm1lbnRzID0gW11cblxuLyogUHJvcGVydGllcyBhbmQgbWV0aG9kcyByZWxhdGVkIHRvIGludGVyYWN0aW9uIHdpdGggdGhlIHNjcmVlbmZ1bGwuanMgbGlicmFyeS4gKi9cbmxldCBmdWxsc2NyZWVuSGFuZGxlcnMgPSBbXVxubGV0IHNjcmVlbmZ1bGxIYW5kbGVyQXNzaWduZWQgPSBmYWxzZVxuZnVuY3Rpb24gZW5hYmxlU2NyZWVuZnVsbEhhbmRsZXIgKCkge1xuICBpZiAoIXNjcmVlbmZ1bGxIYW5kbGVyQXNzaWduZWQgJiYgd2luZG93LnNjcmVlbmZ1bGwgJiYgd2luZG93LnNjcmVlbmZ1bGwuZW5hYmxlZCkge1xuICAgICAgc2NyZWVuZnVsbEhhbmRsZXJBc3NpZ25lZCA9IHRydWVcbiAgICAgIHdpbmRvdy5zY3JlZW5mdWxsLm9uY2hhbmdlKCgpID0+IHtcbiAgICAgICAgbGV0IGksIGxlbmd0aCA9IGZ1bGxzY3JlZW5IYW5kbGVycy5sZW5ndGhcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgZnVsbHNjcmVlbkhhbmRsZXJzW2ldKHdpbmRvdy5zY3JlZW5mdWxsLmlzRnVsbHNjcmVlbilcbiAgICAgICAgfVxuICAgICAgfSlcbiAgfVxufVxuXG4vKiBQcm9wZXJ0aWVzIGFuZCBtZXRob2RzIHJlbGF0ZWQgdG8gZGV2aWNlIGJyb3dzZXIgb3JpZW50YXRpb24gY2hhbmdlLiAqL1xubGV0IG9yaWVudGF0aW9uSGFuZGxlcnMgPSBbXVxuZnVuY3Rpb24gb25vcmllbnRhdGlvbmNoYW5nZSAoZXZlbnQpIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuICBjb25zdCBzY3JlZW5PcmllbnRhdGlvbiA9IHNjcmVlbi5vcmllbnRhdGlvbiA/IHNjcmVlbi5vcmllbnRhdGlvbi5hbmdsZSA6IHVuZGVmaW5lZDtcbiAgY29uc3Qgb3JpZW50YXRpb25WYWx1ZSA9ICh0eXBlb2Ygc2NyZWVuT3JpZW50YXRpb24gPT09ICd1bmRlZmluZWQnKSBcbiAgICA/ICh3aW5kb3cubWF0Y2hNZWRpYShcIihvcmllbnRhdGlvbjogcG9ydHJhaXQpXCIpLm1hdGNoZXMgPyAwIDogOTApIFxuICAgIDogc2NyZWVuT3JpZW50YXRpb247XG4gIGxldCBpLCBsZW5ndGggPSBvcmllbnRhdGlvbkhhbmRsZXJzLmxlbmd0aFxuICBkZWJ1ZyhgW3dpbmRvdzpvbm9yaWVudGF0aW9uY2hhbmdlXWAsICBgb3JpZW50YXRpb24oJHtvcmllbnRhdGlvblZhbHVlfSkuYClcbiAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgb3JpZW50YXRpb25IYW5kbGVyc1tpXSgob3JpZW50YXRpb25WYWx1ZSArIDkwKSAlIDM2MClcbiAgfVxufVxuXG4vKiBQcm9wZXJpZXMgYW5kIG1ldGhvZHMgcmVsYXRlZCB0byB3aW5kb3cgY2xvc2Ugb3BlcmF0aW9uLiAqL1xubGV0IGNsb3NlSGFuZGxlcnMgPSBbXVxubGV0IGhhc09uV2luZG93Q2xvc2UgPSBmYWxzZVxuZnVuY3Rpb24gb253aW5kb3djbG9zZSAoZSkgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gIC8vICBjbG9zZUhhbmRsZXJzLmZvckVhY2goaCA9PiBoKCkpXG4gIGxldCBpLCBsZW5ndGggPSBjbG9zZUhhbmRsZXJzLmxlbmd0aFxuICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICBjbG9zZUhhbmRsZXJzW2ldKClcbiAgfVxuICBoYXNPbldpbmRvd0Nsb3NlID0gdHJ1ZVxuICAvLyBSZXR1cm5pbmcgYSBzdHJpbmcgdmFsdWUgZm9yY2VzIGEgbGVhdmluZyBjb25maXJtYXRpb24gcG9wdXAgb24gdGhlIGJyb3dzZXIuXG4gIC8vICBlLnJldHVyblZhbHVlID0gJ2dvb2RieWUnXG4gIC8vICByZXR1cm4gJ2dvb2RieWUnXG59XG5cbi8qIENoZWNrIHRvIHNlZSB3aGF0IHRoZSBjdXJyZW50IGZsYXNoIHZlcnNpb24gaXMsIGlmIHBsdWdpbiBpcyBlbmFibGVkLiAqL1xuLy8gaHR0cHM6Ly9naXRodWIuY29tL3ZpZGVvanMvdmlkZW8uanMvYmxvYi9tYXN0ZXIvc3JjL2pzL3RlY2gvZmxhc2guanMjTDQ3NlxuY29uc3QgZmxhc2hWZXJzaW9uID0gZnVuY3Rpb24gKCkge1xuICBsZXQgdmVyc2lvbiA9ICcwLDAsMCdcbiAgLy8gSUVcbiAgdHJ5IHtcbiAgICB2ZXJzaW9uID0gbmV3IHdpbmRvdy5BY3RpdmVYT2JqZWN0KCdTaG9ja3dhdmVGbGFzaC5TaG9ja3dhdmVGbGFzaCcpLkdldFZhcmlhYmxlKCckdmVyc2lvbicpLnJlcGxhY2UoL1xcRCsvZywgJywnKS5tYXRjaCgvXiw/KC4rKSw/JC8pWzFdXG5cbiAgLy8gb3RoZXIgYnJvd3NlcnNcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRyeSB7XG4gICAgICBpZiAobmF2aWdhdG9yLm1pbWVUeXBlc1snYXBwbGljYXRpb24veC1zaG9ja3dhdmUtZmxhc2gnXS5lbmFibGVkUGx1Z2luKSB7XG4gICAgICAgIHZlcnNpb24gPSAobmF2aWdhdG9yLnBsdWdpbnNbJ1Nob2Nrd2F2ZSBGbGFzaCAyLjAnXSB8fCBuYXZpZ2F0b3IucGx1Z2luc1snU2hvY2t3YXZlIEZsYXNoJ10pLmRlc2NyaXB0aW9uLnJlcGxhY2UoL1xcRCsvZywgJywnKS5tYXRjaCgvXiw/KC4rKSw/JC8pWzFdXG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAvLyBuYWRhXG4gICAgfVxuICB9XG4gIHJldHVybiB2ZXJzaW9uLnNwbGl0KCcsJylcbn1cblxuLyogU2hpbSBmb3IgYHJlcXVlc3RBbmltYXRpb25GcmFtZWAgb2YgYnJvd3Nlci4gKi9cbmNvbnN0IHJlcXVlc3RGcmFtZSA9ICgodGltZSkgPT4ge1xuICByZXR1cm4gd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSB8fFxuICAgICAgICAgd2luZG93Lm1velJlcXVlc3RBbmltYXRpb25GcmFtZSB8fFxuICAgICAgICAgd2luZG93LndlYmtpdFJlcXVlc3RBbmltYXRpb25GcmFtZSB8fFxuICAgICAgICAgd2luZG93Lm1zUmVxdWVzdEFuaW1hdGlvbkZyYW1lIHx8XG4gICAgICAgICBmdW5jdGlvbiAoZm4pIHtcbiAgICAgICAgICAgcmV0dXJuIHdpbmRvdy5zZXRUaW1lb3V0KGZuLCB0aW1lKVxuICAgICAgICAgfVxufSkoMTAwMCk7XG5cbi8qIEJyb3dzZXIgdGVzdCB0byBzZWUgaWYgTW96aWxsYS1iYXNlZC4gKi9cbmNvbnN0IGlzTW96ID0gISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhXG5cbi8qIERldGVybWluZSBpZiBjdXJyZW50IGJyb3dzZXIgaGFzIHRvdWNoIGNhcGFiaWxpdGllcy4gKi9cbmNvbnN0IGlzVG91Y2hFbmFibGVkID0gJ29udG91Y2hzdGFydCcgaW4gd2luZG93IHx8XG4gIHdpbmRvdy5Eb2N1bWVudFRvdWNoICYmXG4gIHdpbmRvdy5kb2N1bWVudCBpbnN0YW5jZW9mIHdpbmRvdy5Eb2N1bWVudFRvdWNoXG5cbi8vIElmIGRldmVsb3BlciBoYXMgbm90IHVzZWQgYWRhcHRlci5qcy5cbmlmICghd2luZG93LmFkYXB0ZXIpIHtcbiAgbmF2aWdhdG9yLmdldFVzZXJNZWRpYSA9IChuYXZpZ2F0b3IubWVkaWFEZXZpY2VzICYmIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKSB8fCBuYXZpZ2F0b3IuZ2V0VXNlck1lZGlhIHx8IG5hdmlnYXRvci5tb3pHZXRVc2VyTWVkaWEgfHwgbmF2aWdhdG9yLndlYmtpdEdldFVzZXJNZWRpYSB8fCBuYXZpZ2F0b3IubXNHZXRVc2VyTWVkaWFcbn1cblxuLyogUHJveHkgdG8gYnJvd3Nlci1iYXNlZCwgc3BlY2lmaWMgZnVuY3Rpb25zLiAqL1xuZXhwb3J0IGRlZmF1bHQge1xuXG4gIHJlcXVlc3RGcmFtZTogcmVxdWVzdEZyYW1lLFxuXG4gIGdldElzTW96OiAoKSA9PiB7XG4gICAgcmV0dXJuIGlzTW96XG4gIH0sXG5cbiAgaXNUb3VjaEVuYWJsZWQ6ICgpID0+IHtcbiAgICByZXR1cm4gaXNUb3VjaEVuYWJsZWRcbiAgfSxcblxuICBzdXBwb3J0c1dlYlNvY2tldDogKCkgPT4ge1xuICAgIHJldHVybiAhIXdpbmRvdy5XZWJTb2NrZXRcbiAgfSxcblxuICBzdXBwb3J0c0hMUzogKCkgPT4ge1xuICAgIGxldCBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJylcbiAgICByZXR1cm4gZWwuY2FuUGxheVR5cGUoJ2FwcGxpY2F0aW9uL3ZuZC5hcHBsZS5tcGVnVVJMJykubGVuZ3RoID4gMCB8fFxuICAgICAgZWwuY2FuUGxheVR5cGUoJ2FwcGxpY2F0aW9uL3gtbXBlZ1VSTCcpLmxlbmd0aCA+IDAgfHxcbiAgICAgIGVsLmNhblBsYXlUeXBlKCdhdWRpby9tcGVndXJsJykubGVuZ3RoID4gMCB8fFxuICAgICAgZWwuY2FuUGxheVR5cGUoJ2F1ZGlvL3gtbXBlZ3VybCcpLmxlbmd0aCA+IDBcbiAgfSxcblxuICBzdXBwb3J0c0ZsYXNoVmVyc2lvbjogKHZlcnNpb24sIGRlbGltaXRlciA9ICcuJykgPT4ge1xuICAgIHJldHVybiBmbGFzaFZlcnNpb24oKVswXSA+PSB2ZXJzaW9uLnNwbGl0KGRlbGltaXRlcilbMF1cbiAgfSxcblxuICByZXNvbHZlRWxlbWVudDogKGlkKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGVsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpXG4gICAgICBpZiAoIWVsKSB7XG4gICAgICAgIHRocm93IG5ldyBOb0VsZW1lbnRGb3VuZEVycm9yKGBFbGVtZW50IHdpdGggaWQoJHtpZH0pIGNvdWxkIG5vdCBiZSBmb3VuZC5gKVxuICAgICAgfVxuICAgICAgcmV0dXJuIGVsXG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhyb3cgbmV3IE5vRWxlbWVudEZvdW5kRXJyb3IoYEVycm9yIGluIGFjY2Vzc2luZyBlbGVtZW50IHdpdGggaWQoJHtpZH0pLiAke2UubWVzc2FnZX1gKVxuICAgIH1cbiAgfSxcblxuICBjcmVhdGVXZWJTb2NrZXQ6ICh1cmwpID0+IHtcbiAgICByZXR1cm4gbmV3IFdlYlNvY2tldCh1cmwpXG4gIH0sXG5cbiAgc2V0VmlkZW9Tb3VyY2U6ICh2aWRlb0VsZW1lbnQsIG1lZGlhU3RyZWFtLCBhdXRvcGxheSA9IGZhbHNlKSA9PiB7XG4gICAgdmlkZW9FbGVtZW50Lm9ubG9hZGVkbWV0YWRhdGEgPSAoKSA9PiB7XG4gICAgICBkZWJ1ZygnW3ZpZGVvZWxlbWVudDpldmVudF0nLCAnbG9hZGVkbWV0YWRhdGEnKVxuICAgICAgZGVidWcoJ1t2aWRlbzpjb25zdHJhaW50c10nLCBgVmlkZW8gYWN0dWFsIGRpbWVuc2lvbnMgYXJlOiAke3ZpZGVvRWxlbWVudC52aWRlb1dpZHRofSwgJHt2aWRlb0VsZW1lbnQudmlkZW9IZWlnaHR9YClcbiAgICB9XG4gICAgaWYgKCdzcmNPYmplY3QnIGluIHZpZGVvRWxlbWVudCkge1xuICAgICAgdmlkZW9FbGVtZW50LnNyY09iamVjdCA9IG1lZGlhU3RyZWFtO1xuICAgIH1cbiAgICBlbHNlIGlmIChpc01veikge1xuICAgICAgdmlkZW9FbGVtZW50Wydtb3pTcmNPYmplY3QnXSA9IG1lZGlhU3RyZWFtXG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgdmlkZW9FbGVtZW50LnNyYyA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKG1lZGlhU3RyZWFtKVxuICAgIH1cbiAgICBpZiAoYXV0b3BsYXkpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGxldCBtYXliZVByb21pc2UgPSB2aWRlb0VsZW1lbnQucGxheSgpXG4gICAgICAgIGlmIChtYXliZVByb21pc2UpIHtcbiAgICAgICAgICBtYXliZVByb21pc2UudGhlbigoKSA9PiBkZWJ1ZygnW3NldFZpZGVvU291cmNlOmFjdGlvbl0nLCAncGxheSAoU1RBUlQpJykpXG4gICAgICAgICAgICAgICAgICAgICAuY2F0Y2goKGVycikgPT4gd2FybignW3NldFZpZGVvU291cmNlOmFjdGlvbl0nLCAncGxheSAoRkFVTFQpICcgKyAoZXJyLm1lc3NhZ2UgPyBlcnIubWVzc2FnZSA6IGVycikpKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjYXRjaCAoZSkge1xuICAgICAgICAvLyBNb2JpbGUgQnJvd3NlcnM6IFVuY2F1Z2h0IChpbiBwcm9taXNlKSBET01FeGNlcHRpb246IHBsYXkoKSBjYW4gb25seSBiZSBpbml0aWF0ZWQgYnkgYSB1c2VyIGdlc3R1cmUuXG4gICAgICAgIHdhcm4oJ1tzZXRWaWRlb1NvdXJjZTphY3Rpb25dJywgJ3BsYXkgKENBVENIOjpGQVVMVCkgJyArIGUubWVzc2FnZSlcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICB2aWRlb0VsZW1lbnQuc2V0QXR0cmlidXRlKCdhdXRvcGxheScsIGZhbHNlKVxuICAgICAgICAgIHZpZGVvRWxlbWVudC5wYXVzZSgpXG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIHdhcm4oJ1tzZXRWaWRlb1NvdXJjZTphY3Rpb25dJywgJ3BhdXNlIChDQVRDSDo6RkFVTFQpICcgKyBlcnIubWVzc2FnZSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHZpZGVvRWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2F1dG9wbGF5JywgZmFsc2UpXG4gICAgICAgIHZpZGVvRWxlbWVudC5wYXVzZSgpXG4gICAgICB9XG4gICAgICBjYXRjaCAoZSkge1xuICAgICAgICAvLyBuYWRhLlxuICAgICAgfVxuICAgIH1cbiAgfSxcblxuICBpbmplY3RTY3JpcHQ6ICh1cmwpID0+IHtcbiAgICBsZXQgZGZkID0gbmV3IERlZmVycmVkUHJvbWlzZSgpXG4gICAgbGV0IHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NjcmlwdCcpXG4gICAgc2NyaXB0LnR5cGUgPSAndGV4dC9qYXZhc2NyaXB0J1xuICAgIHNjcmlwdC5vbmxvYWQgPSAoKSA9PiB7XG4gICAgICBkZmQucmVzb2x2ZSgpXG4gICAgfVxuICAgIHNjcmlwdC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICBpZiAoc2NyaXB0LnJlYWR5U3RhdGUgPT09ICdsb2FkZWQnIHx8IHNjcmlwdC5yZWFkeVN0YXRlID09PSAnY29tcGxldGUnKSB7XG4gICAgICAgIHNjcmlwdC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBudWxsXG4gICAgICAgIGRmZC5yZXNvbHZlKClcbiAgICAgIH1cbiAgICB9XG4gICAgc2NyaXB0LnNyYyA9IHVybFxuICAgIGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdoZWFkJylbMF0uYXBwZW5kQ2hpbGQoc2NyaXB0KVxuICAgIHJldHVybiBkZmQucHJvbWlzZVxuICB9LFxuXG4gIGdVTTogKGNvbnN0cmFpbnRzKSA9PiB7XG4gICAgcmV0dXJuIChuYXZpZ2F0b3IubWVkaWFEZXZpY2VzIHx8IG5hdmlnYXRvcikuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzKVxuICB9LFxuXG4gIHNldEdsb2JhbDogKHByb3AsIHZhbHVlKSA9PiB7XG4gICAgd2luZG93W3Byb3BdID0gdmFsdWVcbiAgfSxcblxuICBnZXRTd2ZPYmplY3Q6ICgpID0+IHtcbiAgICByZXR1cm4gd2luZG93LnN3Zm9iamVjdFxuICB9LFxuXG4gIGdldEVtYmVkT2JqZWN0OiAoaWQpID0+IHtcbiAgICByZXR1cm4gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpXG4gIH0sXG5cbiAgZ2V0RWxlbWVudElkOiAoZWwpID0+IHtcbiAgICByZXR1cm4gZWwuZ2V0QXR0cmlidXRlKCdpZCcpO1xuICB9LFxuXG4gIGFkZE9yaWVudGF0aW9uQ2hhbmdlSGFuZGxlcjogKGhhbmRsZXIsIGFuZENhbGwgPSB0cnVlKSA9PiB7XG4gICAgY29uc3Qgc3VwcG9ydHNPcmllbnRhdGlvbkNoYW5nZSA9ICdvbm9yaWVudGF0aW9uY2hhbmdlJyBpbiB3aW5kb3dcbiAgICBpZiAoc3VwcG9ydHNPcmllbnRhdGlvbkNoYW5nZSkge1xuICAgICAgZGVidWcoJ1t3aW5kb3c6b3JpZW50YXRpb25dJywgJ1thZGRPcmllbnRhdGlvbkNoYW5nZUhhbmRsZXJdJywgJ2FkZGluZyByZXNwb25kZXIuJylcbiAgICAgIG9yaWVudGF0aW9uSGFuZGxlcnMucHVzaChoYW5kbGVyKVxuICAgICAgaWYgKGFuZENhbGwpIHtcbiAgICAgICAgb25vcmllbnRhdGlvbmNoYW5nZSgpXG4gICAgICB9XG4gICAgfVxuICAgIGlmIChvcmllbnRhdGlvbkhhbmRsZXJzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgZGVidWcoJ1t3aW5kb3c6b3JpZW50YXRpb25dJywgJ1thZGRPcmllbnRhdGlvbkNoYW5nZUhhbmRsZXJdJywgJ29ub3JpZW50YXRpb25jaGFuZ2UgYWRkZWQuJylcbiAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdvcmllbnRhdGlvbmNoYW5nZScsIG9ub3JpZW50YXRpb25jaGFuZ2UpXG4gICAgfVxuICB9LFxuXG4gIHJlbW92ZU9yaWVudGF0aW9uQ2hhbmdlSGFuZGxlcjogKGhhbmRsZXIpID0+IHtcbiAgICBsZXQgaSA9IG9yaWVudGF0aW9uSGFuZGxlcnMubGVuZ3RoXG4gICAgd2hpbGUoIC0taSA+IC0xKSB7XG4gICAgICBpZiAob3JpZW50YXRpb25IYW5kbGVyc1tpXSA9PT0gaGFuZGxlcikge1xuICAgICAgICBvcmllbnRhdGlvbkhhbmRsZXJzLnNsaWNlKGksIDEpXG4gICAgICAgIGJyZWFrXG4gICAgICB9XG4gICAgfSBcbiAgICBpZiAob3JpZW50YXRpb25IYW5kbGVycy5sZW5ndGggPT09IDApIHtcbiAgICAgIGRlYnVnKCdbd2luZG93Om9yaWVudGF0aW9uXScsICdbcmVtb3ZlT3JpZW50YXRpb25DaGFuZ2VIYW5kbGVyXTo6IG9ub3JpZW50YXRpb25jaGFuZ2UgcmVtb3ZlZC4nKVxuICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ29ub3JpZW50YXRpb25jaGFuZ2UnLCBvbm9yaWVudGF0aW9uY2hhbmdlKVxuICAgIH1cbiAgfSxcblxuICBhZGRDbG9zZUhhbmRsZXI6IChoYW5kbGVyLCBpbnNlcnRWYWx1ZSA9IC0xKSA9PiB7XG4gICAgY2xvc2VIYW5kbGVycy5zcGxpY2UoaW5zZXJ0VmFsdWUgPT09IC0xID8gY2xvc2VIYW5kbGVycy5sZW5ndGggOiBpbnNlcnRWYWx1ZSwgMCwgaGFuZGxlcilcbiAgICAvLyBOT1RFOiBSZW1vdmVkIG9uYmVmb3JldW5sb2FkIGluIGZhdm9yIG9mIGRldmVsb3BlcnMgcHJvcGVybHkgaGFuZGxpbmcgc2h1dGRvd24uXG4gICAgLy8gICAgaWYgKHdpbmRvdy5vbmJlZm9yZXVubG9hZCAhPT0gb253aW5kb3djbG9zZSkge1xuICAgIC8vIHdpbmRvdy5vbmJlZm9yZXVubG9hZCA9IG9ud2luZG93Y2xvc2VcbiAgICBpZiAoIWhhc09uV2luZG93Q2xvc2UpIHtcbiAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCd1bmxvYWQnLCBvbndpbmRvd2Nsb3NlKVxuICAgIH1cbiAgICAvLyB9XG4gIH0sXG5cbiAgcmVtb3ZlQ2xvc2VIYW5kbGVyOiAoaGFuZGxlcikgPT4ge1xuICAgIGxldCBpID0gY2xvc2VIYW5kbGVycy5sZW5ndGhcbiAgICB3aGlsZSggLS1pID4gLTEpIHtcbiAgICAgIGlmIChjbG9zZUhhbmRsZXJzW2ldID09PSBoYW5kbGVyKSB7XG4gICAgICAgIGNsb3NlSGFuZGxlcnMuc2xpY2UoaSwgMSlcbiAgICAgICAgYnJlYWtcbiAgICAgIH1cbiAgICB9XG4gIH0sXG5cbiAgaW52b2tlOiAobWV0aG9kTmFtZSwgZGF0YSkgPT4ge1xuICAgIGlmICh3aW5kb3cuaGFzT3duUHJvcGVydHkobWV0aG9kTmFtZSkpIHtcbiAgICAgIHdpbmRvd1ttZXRob2ROYW1lXS5jYWxsKHdpbmRvdywgZGF0YSlcbiAgICB9XG4gIH0sXG5cbiAgLy8gcmVxdWlyZXMgPHNjcmlwdCBzcmM9XCJsaWIvc2NyZWVuZnVsbC9zY3JlZW5mdWxsLm1pbi5qc1wiPjwvc2NyaXB0PlxuICB0b2dnbGVGdWxsU2NyZWVuOiAoZWxlbWVudCkgPT4ge1xuICAgIGlmICh3aW5kb3cuc2NyZWVuZnVsbCAmJiB3aW5kb3cuc2NyZWVuZnVsbC5lbmFibGVkKSB7XG4gICAgICB3aW5kb3cuc2NyZWVuZnVsbC50b2dnbGUoZWxlbWVudClcbiAgICB9XG4gIH0sXG5cbiAgb25GdWxsU2NyZWVuU3RhdGVDaGFuZ2U6IChjYikgPT4ge1xuICAgIGZ1bGxzY3JlZW5IYW5kbGVycy5wdXNoKGNiKVxuICAgIGVuYWJsZVNjcmVlbmZ1bGxIYW5kbGVyKHdpbmRvdy5zY3JlZW5mdWxsKVxuICB9LFxuXG4gIG9uT3JpZW50YXRpb25NZXRhZGF0YTogb25PcmllbnRhdGlvbk1ldGFkYXRhLFxuXG4gIGhhc0F0dHJpYnV0ZURlZmluZWQ6IChlbGVtLCBhdHRyaWJ1dGUpID0+IHtcbiAgICBjb25zdCBhdHQgPSBlbGVtLmdldEF0dHJpYnV0ZShhdHRyaWJ1dGUpXG4gICAgcmV0dXJuIChhdHQgIT09IG51bGwgJiYgdHlwZW9mIGF0dCAhPT0gdW5kZWZpbmVkKSAmJlxuICAgICAgICAgICh0eXBlb2YgYXR0ID09PSAnc3RyaW5nJyAmJiAoYXR0ID09PSAnJyB8fCBhdHQgPT09ICd0cnVlJyB8fCBhdHQgPT09IGF0dHJpYnV0ZSkpXG4gIH0sXG5cbiAgaGFzQ2xhc3NEZWZpbmVkOiAoZWxlbSwgY2xhc3NOYW1lKSA9PiB7XG4gICAgcmV0dXJuIGVsZW0uY2xhc3NMaXN0LmNvbnRhaW5zKGNsYXNzTmFtZSlcbiAgfSxcblxuICBjcmVhdGVFbGVtZW50OiAodGFnTmFtZSwgb3B0cykgPT4ge1xuICAgIGlmICh0YWdOYW1lID09PSAndGV4dCcpIHtcbiAgICAgIHJldHVybiBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShvcHRzLnRvU3RyaW5nKCkpXG4gICAgfVxuICAgIHJldHVybiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KHRhZ05hbWUsIG9wdHMpXG4gIH0sXG5cbiAgYWRkU3Vic2NyaXB0aW9uQXNzaWdubWVudEhhbmRsZXI6IChmbikgPT4ge1xuICAgIHJ0bXBTdWJzY3JpYmVyQXNzaWdubWVudHMucHVzaChmbilcbiAgICBpZiAod2luZG93LnNldFN1YnNjcmliZXJJZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB3aW5kb3cuc2V0U3Vic2NyaWJlcklkID0gKGlkKSA9PiB7XG4gICAgICAgIHJ0bXBTdWJzY3JpYmVyQXNzaWdubWVudHMuc2hpZnQoKShpZClcbiAgICAgIH1cbiAgICB9XG4gIH0sXG5cbiAgZ2V0TW91c2VYRnJvbUV2ZW50OiAoZXZlbnQpID0+IHtcbiAgICBpZiAoIWV2ZW50KSB7XG4gICAgICBldmVudCA9IHdpbmRvdy5ldmVudFxuICAgIH1cblxuICAgIGlmIChldmVudC5wYWdlWCkge1xuICAgICAgcmV0dXJuIGV2ZW50LnBhZ2VYXG4gICAgfVxuICAgIGVsc2UgaWYgKGV2ZW50LmNsaWVudFgpIHtcbiAgICAgIHJldHVybiBldmVudC5jbGllbnRYICsgZG9jdW1lbnQuYm9keS5zY3JvbGxMZWZ0ICsgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbExlZnRcbiAgICB9XG5cbiAgICByZXR1cm4gMFxuICB9LFxuXG4gIGdldFNjcm9sbFg6ICgpID0+IHtcbiAgICByZXR1cm4gKHdpbmRvdy5wYWdlWE9mZnNldCAhPT0gdW5kZWZpbmVkKVxuICAgICAgICAgICAgPyB3aW5kb3cucGFnZVhPZmZzZXRcbiAgICAgICAgICAgIDogKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCB8fCBkb2N1bWVudC5ib2R5LnBhcmVudE5vZGUgfHwgZG9jdW1lbnQuYm9keSkuc2Nyb2xsTGVmdFxuICB9LFxuXG4gIGNyZWF0ZUV2ZW50OiAoRXZlbnRUeXBlKSA9PiB7XG4gICAgcmV0dXJuIGRvY3VtZW50LmNyZWF0ZUV2ZW50KEV2ZW50VHlwZSlcbiAgfSxcblxuICBnZXRHbG9iYWw6ICgpID0+IHdpbmRvd1xuXG59XG5cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9qcy9lbnYvYnJvd3Nlci5qcyIsIid1c2Ugc3RyaWN0J1xuXG4vKipcbiAqIEEgRGVmZXJyZWRQcm9taXNlIGFsbG93cyBmb3IgY29uc3RydWN0aW9uIGFuZCBhc3NpZ25tZW50IG9mIGEgZnV0dXJlIGZ1bGxmaWxtZW50IG9mIGEgYFByb21pc2VgLlxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmNsYXNzIF9EZWZlcnJlZFByb21pc2Uge1xuICBjb25zdHJ1Y3RvciAoKSB7XG4gICAgdGhpcy5yZXNvbHZlID0gdW5kZWZpbmVkXG4gICAgdGhpcy5yZWplY3QgPSB1bmRlZmluZWRcbiAgICB0aGlzLnByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLnJlc29sdmUgPSByZXNvbHZlXG4gICAgICB0aGlzLnJlamVjdCA9IHJlamVjdFxuICAgIH0pXG4gIH1cbn1cblxuLyoqXG4gKiBBIEZ1dHVyZSBkZXRlcm1pbmVzIGlmIGV4aXN0YW50IERlZmVycmVkUHJvbWlzZSBpcyBhdmFpbGFibGUgb3IgY3JlYXRlcyBhbmQgcmV0dXJucyBhIG5ldyBvbmUuXG4gKlxuICogQHBhcmFtIHtEZWZlcnJlZFByb21pc2V9IGRlZmVycmVkSWZFeGlzdFxuICogICAgICAgIEFuIG9iamVjdCB0ZXN0ZWQgZm9yIHRydXRoeS1uZXNzLlxuICogQHJldHVybiB7RGVmZXJyZWRQcm9taXNlfVxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmNvbnN0IF9GdXR1cmUgPSB7XG4gIGNyZWF0ZUlmTm90RXhpc3Q6IChkZWZlcnJlZElmRXhpc3QpID0+IHtcbiAgICBsZXQgZiA9IGRlZmVycmVkSWZFeGlzdFxuICAgIGlmICghZikge1xuICAgICAgZiA9IG5ldyBfRGVmZXJyZWRQcm9taXNlKClcbiAgICB9XG4gICAgcmV0dXJuIGZcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgRGVmZXJyZWRQcm9taXNlID0gX0RlZmVycmVkUHJvbWlzZVxuZXhwb3J0IGNvbnN0IEZ1dHVyZSA9IF9GdXR1cmVcblxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2pzL3V0aWwvcHJvbWlzZS5qcyIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9vYmplY3QvZ2V0LXByb3RvdHlwZS1vZlwiKSwgX19lc01vZHVsZTogdHJ1ZSB9O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9iYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L2dldC1wcm90b3R5cGUtb2YuanNcbi8vIG1vZHVsZSBpZCA9IDZcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbnZhciBfc2V0UHJvdG90eXBlT2YgPSByZXF1aXJlKFwiLi4vY29yZS1qcy9vYmplY3Qvc2V0LXByb3RvdHlwZS1vZlwiKTtcblxudmFyIF9zZXRQcm90b3R5cGVPZjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9zZXRQcm90b3R5cGVPZik7XG5cbnZhciBfY3JlYXRlID0gcmVxdWlyZShcIi4uL2NvcmUtanMvb2JqZWN0L2NyZWF0ZVwiKTtcblxudmFyIF9jcmVhdGUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfY3JlYXRlKTtcblxudmFyIF90eXBlb2YyID0gcmVxdWlyZShcIi4uL2hlbHBlcnMvdHlwZW9mXCIpO1xuXG52YXIgX3R5cGVvZjMgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF90eXBlb2YyKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZXhwb3J0cy5kZWZhdWx0ID0gZnVuY3Rpb24gKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7XG4gIGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gXCJmdW5jdGlvblwiICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCBcIiArICh0eXBlb2Ygc3VwZXJDbGFzcyA9PT0gXCJ1bmRlZmluZWRcIiA/IFwidW5kZWZpbmVkXCIgOiAoMCwgX3R5cGVvZjMuZGVmYXVsdCkoc3VwZXJDbGFzcykpKTtcbiAgfVxuXG4gIHN1YkNsYXNzLnByb3RvdHlwZSA9ICgwLCBfY3JlYXRlMi5kZWZhdWx0KShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7XG4gICAgY29uc3RydWN0b3I6IHtcbiAgICAgIHZhbHVlOiBzdWJDbGFzcyxcbiAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9XG4gIH0pO1xuICBpZiAoc3VwZXJDbGFzcykgX3NldFByb3RvdHlwZU9mMi5kZWZhdWx0ID8gKDAsIF9zZXRQcm90b3R5cGVPZjIuZGVmYXVsdCkoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIDogc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzcztcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2JhYmVsLXJ1bnRpbWUvaGVscGVycy9pbmhlcml0cy5qc1xuLy8gbW9kdWxlIGlkID0gN1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJcInVzZSBzdHJpY3RcIjtcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxudmFyIF90eXBlb2YyID0gcmVxdWlyZShcIi4uL2hlbHBlcnMvdHlwZW9mXCIpO1xuXG52YXIgX3R5cGVvZjMgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF90eXBlb2YyKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZXhwb3J0cy5kZWZhdWx0ID0gZnVuY3Rpb24gKHNlbGYsIGNhbGwpIHtcbiAgaWYgKCFzZWxmKSB7XG4gICAgdGhyb3cgbmV3IFJlZmVyZW5jZUVycm9yKFwidGhpcyBoYXNuJ3QgYmVlbiBpbml0aWFsaXNlZCAtIHN1cGVyKCkgaGFzbid0IGJlZW4gY2FsbGVkXCIpO1xuICB9XG5cbiAgcmV0dXJuIGNhbGwgJiYgKCh0eXBlb2YgY2FsbCA9PT0gXCJ1bmRlZmluZWRcIiA/IFwidW5kZWZpbmVkXCIgOiAoMCwgX3R5cGVvZjMuZGVmYXVsdCkoY2FsbCkpID09PSBcIm9iamVjdFwiIHx8IHR5cGVvZiBjYWxsID09PSBcImZ1bmN0aW9uXCIpID8gY2FsbCA6IHNlbGY7XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9iYWJlbC1ydW50aW1lL2hlbHBlcnMvcG9zc2libGVDb25zdHJ1Y3RvclJldHVybi5qc1xuLy8gbW9kdWxlIGlkID0gOFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJ2YXIgc3RvcmUgICAgICA9IHJlcXVpcmUoJy4vX3NoYXJlZCcpKCd3a3MnKVxuICAsIHVpZCAgICAgICAgPSByZXF1aXJlKCcuL191aWQnKVxuICAsIFN5bWJvbCAgICAgPSByZXF1aXJlKCcuL19nbG9iYWwnKS5TeW1ib2xcbiAgLCBVU0VfU1lNQk9MID0gdHlwZW9mIFN5bWJvbCA9PSAnZnVuY3Rpb24nO1xuXG52YXIgJGV4cG9ydHMgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKG5hbWUpe1xuICByZXR1cm4gc3RvcmVbbmFtZV0gfHwgKHN0b3JlW25hbWVdID1cbiAgICBVU0VfU1lNQk9MICYmIFN5bWJvbFtuYW1lXSB8fCAoVVNFX1NZTUJPTCA/IFN5bWJvbCA6IHVpZCkoJ1N5bWJvbC4nICsgbmFtZSkpO1xufTtcblxuJGV4cG9ydHMuc3RvcmUgPSBzdG9yZTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3drcy5qc1xuLy8gbW9kdWxlIGlkID0gOVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJ2YXIgZ2xvYmFsICAgID0gcmVxdWlyZSgnLi9fZ2xvYmFsJylcbiAgLCBjb3JlICAgICAgPSByZXF1aXJlKCcuL19jb3JlJylcbiAgLCBjdHggICAgICAgPSByZXF1aXJlKCcuL19jdHgnKVxuICAsIGhpZGUgICAgICA9IHJlcXVpcmUoJy4vX2hpZGUnKVxuICAsIFBST1RPVFlQRSA9ICdwcm90b3R5cGUnO1xuXG52YXIgJGV4cG9ydCA9IGZ1bmN0aW9uKHR5cGUsIG5hbWUsIHNvdXJjZSl7XG4gIHZhciBJU19GT1JDRUQgPSB0eXBlICYgJGV4cG9ydC5GXG4gICAgLCBJU19HTE9CQUwgPSB0eXBlICYgJGV4cG9ydC5HXG4gICAgLCBJU19TVEFUSUMgPSB0eXBlICYgJGV4cG9ydC5TXG4gICAgLCBJU19QUk9UTyAgPSB0eXBlICYgJGV4cG9ydC5QXG4gICAgLCBJU19CSU5EICAgPSB0eXBlICYgJGV4cG9ydC5CXG4gICAgLCBJU19XUkFQICAgPSB0eXBlICYgJGV4cG9ydC5XXG4gICAgLCBleHBvcnRzICAgPSBJU19HTE9CQUwgPyBjb3JlIDogY29yZVtuYW1lXSB8fCAoY29yZVtuYW1lXSA9IHt9KVxuICAgICwgZXhwUHJvdG8gID0gZXhwb3J0c1tQUk9UT1RZUEVdXG4gICAgLCB0YXJnZXQgICAgPSBJU19HTE9CQUwgPyBnbG9iYWwgOiBJU19TVEFUSUMgPyBnbG9iYWxbbmFtZV0gOiAoZ2xvYmFsW25hbWVdIHx8IHt9KVtQUk9UT1RZUEVdXG4gICAgLCBrZXksIG93biwgb3V0O1xuICBpZihJU19HTE9CQUwpc291cmNlID0gbmFtZTtcbiAgZm9yKGtleSBpbiBzb3VyY2Upe1xuICAgIC8vIGNvbnRhaW5zIGluIG5hdGl2ZVxuICAgIG93biA9ICFJU19GT1JDRUQgJiYgdGFyZ2V0ICYmIHRhcmdldFtrZXldICE9PSB1bmRlZmluZWQ7XG4gICAgaWYob3duICYmIGtleSBpbiBleHBvcnRzKWNvbnRpbnVlO1xuICAgIC8vIGV4cG9ydCBuYXRpdmUgb3IgcGFzc2VkXG4gICAgb3V0ID0gb3duID8gdGFyZ2V0W2tleV0gOiBzb3VyY2Vba2V5XTtcbiAgICAvLyBwcmV2ZW50IGdsb2JhbCBwb2xsdXRpb24gZm9yIG5hbWVzcGFjZXNcbiAgICBleHBvcnRzW2tleV0gPSBJU19HTE9CQUwgJiYgdHlwZW9mIHRhcmdldFtrZXldICE9ICdmdW5jdGlvbicgPyBzb3VyY2Vba2V5XVxuICAgIC8vIGJpbmQgdGltZXJzIHRvIGdsb2JhbCBmb3IgY2FsbCBmcm9tIGV4cG9ydCBjb250ZXh0XG4gICAgOiBJU19CSU5EICYmIG93biA/IGN0eChvdXQsIGdsb2JhbClcbiAgICAvLyB3cmFwIGdsb2JhbCBjb25zdHJ1Y3RvcnMgZm9yIHByZXZlbnQgY2hhbmdlIHRoZW0gaW4gbGlicmFyeVxuICAgIDogSVNfV1JBUCAmJiB0YXJnZXRba2V5XSA9PSBvdXQgPyAoZnVuY3Rpb24oQyl7XG4gICAgICB2YXIgRiA9IGZ1bmN0aW9uKGEsIGIsIGMpe1xuICAgICAgICBpZih0aGlzIGluc3RhbmNlb2YgQyl7XG4gICAgICAgICAgc3dpdGNoKGFyZ3VtZW50cy5sZW5ndGgpe1xuICAgICAgICAgICAgY2FzZSAwOiByZXR1cm4gbmV3IEM7XG4gICAgICAgICAgICBjYXNlIDE6IHJldHVybiBuZXcgQyhhKTtcbiAgICAgICAgICAgIGNhc2UgMjogcmV0dXJuIG5ldyBDKGEsIGIpO1xuICAgICAgICAgIH0gcmV0dXJuIG5ldyBDKGEsIGIsIGMpO1xuICAgICAgICB9IHJldHVybiBDLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICB9O1xuICAgICAgRltQUk9UT1RZUEVdID0gQ1tQUk9UT1RZUEVdO1xuICAgICAgcmV0dXJuIEY7XG4gICAgLy8gbWFrZSBzdGF0aWMgdmVyc2lvbnMgZm9yIHByb3RvdHlwZSBtZXRob2RzXG4gICAgfSkob3V0KSA6IElTX1BST1RPICYmIHR5cGVvZiBvdXQgPT0gJ2Z1bmN0aW9uJyA/IGN0eChGdW5jdGlvbi5jYWxsLCBvdXQpIDogb3V0O1xuICAgIC8vIGV4cG9ydCBwcm90byBtZXRob2RzIHRvIGNvcmUuJUNPTlNUUlVDVE9SJS5tZXRob2RzLiVOQU1FJVxuICAgIGlmKElTX1BST1RPKXtcbiAgICAgIChleHBvcnRzLnZpcnR1YWwgfHwgKGV4cG9ydHMudmlydHVhbCA9IHt9KSlba2V5XSA9IG91dDtcbiAgICAgIC8vIGV4cG9ydCBwcm90byBtZXRob2RzIHRvIGNvcmUuJUNPTlNUUlVDVE9SJS5wcm90b3R5cGUuJU5BTUUlXG4gICAgICBpZih0eXBlICYgJGV4cG9ydC5SICYmIGV4cFByb3RvICYmICFleHBQcm90b1trZXldKWhpZGUoZXhwUHJvdG8sIGtleSwgb3V0KTtcbiAgICB9XG4gIH1cbn07XG4vLyB0eXBlIGJpdG1hcFxuJGV4cG9ydC5GID0gMTsgICAvLyBmb3JjZWRcbiRleHBvcnQuRyA9IDI7ICAgLy8gZ2xvYmFsXG4kZXhwb3J0LlMgPSA0OyAgIC8vIHN0YXRpY1xuJGV4cG9ydC5QID0gODsgICAvLyBwcm90b1xuJGV4cG9ydC5CID0gMTY7ICAvLyBiaW5kXG4kZXhwb3J0LlcgPSAzMjsgIC8vIHdyYXBcbiRleHBvcnQuVSA9IDY0OyAgLy8gc2FmZVxuJGV4cG9ydC5SID0gMTI4OyAvLyByZWFsIHByb3RvIG1ldGhvZCBmb3IgYGxpYnJhcnlgIFxubW9kdWxlLmV4cG9ydHMgPSAkZXhwb3J0O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fZXhwb3J0LmpzXG4vLyBtb2R1bGUgaWQgPSAxMFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyBodHRwczovL2dpdGh1Yi5jb20vemxvaXJvY2svY29yZS1qcy9pc3N1ZXMvODYjaXNzdWVjb21tZW50LTExNTc1OTAyOFxudmFyIGdsb2JhbCA9IG1vZHVsZS5leHBvcnRzID0gdHlwZW9mIHdpbmRvdyAhPSAndW5kZWZpbmVkJyAmJiB3aW5kb3cuTWF0aCA9PSBNYXRoXG4gID8gd2luZG93IDogdHlwZW9mIHNlbGYgIT0gJ3VuZGVmaW5lZCcgJiYgc2VsZi5NYXRoID09IE1hdGggPyBzZWxmIDogRnVuY3Rpb24oJ3JldHVybiB0aGlzJykoKTtcbmlmKHR5cGVvZiBfX2cgPT0gJ251bWJlcicpX19nID0gZ2xvYmFsOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19nbG9iYWwuanNcbi8vIG1vZHVsZSBpZCA9IDExXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9qc29uL3N0cmluZ2lmeVwiKSwgX19lc01vZHVsZTogdHJ1ZSB9O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9iYWJlbC1ydW50aW1lL2NvcmUtanMvanNvbi9zdHJpbmdpZnkuanNcbi8vIG1vZHVsZSBpZCA9IDEyXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaXQpe1xuICByZXR1cm4gdHlwZW9mIGl0ID09PSAnb2JqZWN0JyA/IGl0ICE9PSBudWxsIDogdHlwZW9mIGl0ID09PSAnZnVuY3Rpb24nO1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2lzLW9iamVjdC5qc1xuLy8gbW9kdWxlIGlkID0gMTNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwidmFyIGFuT2JqZWN0ICAgICAgID0gcmVxdWlyZSgnLi9fYW4tb2JqZWN0JylcbiAgLCBJRThfRE9NX0RFRklORSA9IHJlcXVpcmUoJy4vX2llOC1kb20tZGVmaW5lJylcbiAgLCB0b1ByaW1pdGl2ZSAgICA9IHJlcXVpcmUoJy4vX3RvLXByaW1pdGl2ZScpXG4gICwgZFAgICAgICAgICAgICAgPSBPYmplY3QuZGVmaW5lUHJvcGVydHk7XG5cbmV4cG9ydHMuZiA9IHJlcXVpcmUoJy4vX2Rlc2NyaXB0b3JzJykgPyBPYmplY3QuZGVmaW5lUHJvcGVydHkgOiBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0eShPLCBQLCBBdHRyaWJ1dGVzKXtcbiAgYW5PYmplY3QoTyk7XG4gIFAgPSB0b1ByaW1pdGl2ZShQLCB0cnVlKTtcbiAgYW5PYmplY3QoQXR0cmlidXRlcyk7XG4gIGlmKElFOF9ET01fREVGSU5FKXRyeSB7XG4gICAgcmV0dXJuIGRQKE8sIFAsIEF0dHJpYnV0ZXMpO1xuICB9IGNhdGNoKGUpeyAvKiBlbXB0eSAqLyB9XG4gIGlmKCdnZXQnIGluIEF0dHJpYnV0ZXMgfHwgJ3NldCcgaW4gQXR0cmlidXRlcyl0aHJvdyBUeXBlRXJyb3IoJ0FjY2Vzc29ycyBub3Qgc3VwcG9ydGVkIScpO1xuICBpZigndmFsdWUnIGluIEF0dHJpYnV0ZXMpT1tQXSA9IEF0dHJpYnV0ZXMudmFsdWU7XG4gIHJldHVybiBPO1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX29iamVjdC1kcC5qc1xuLy8gbW9kdWxlIGlkID0gMTRcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyoqXG4gKiBCYXNlIGNsYXNzIGZvciBhbGwgZXZlbnRzLlxuICovXG5jbGFzcyBFdmVudCB7XG5cbiAgY29uc3RydWN0b3IgKHR5cGUsIGRhdGEgPSB1bmRlZmluZWQpIHtcbiAgICB0aGlzLl90eXBlID0gdHlwZVxuICAgIHRoaXMuX2RhdGEgPSBkYXRhXG4gIH1cblxuICAvKipcbiAgICogVHlwZSBhY2Nlc3Nvci5cbiAgICpcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICovXG4gIGdldCB0eXBlICgpIHtcbiAgICByZXR1cm4gdGhpcy5fdHlwZVxuICB9XG5cbiAgLyoqXG4gICAqIERhdGEgcmVsYXRlZCB0byBldmVudC5cbiAgICpcbiAgICogQHR5cGUge09iamVjdH1cbiAgICovXG4gIGdldCBkYXRhICgpIHtcbiAgICByZXR1cm4gdGhpcy5fZGF0YVxuICB9XG5cbn1cblxuLyoqXG4gKiBCYXNlIFB1Ymxpc2hlci1yZWxhdGVkIEV2ZW50LlxuICpcbiAqIEBleHRlbmRzIEV2ZW50XG4gKi9cbmNsYXNzIFB1Ymxpc2hlckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gIGNvbnN0cnVjdG9yICh0eXBlLCBwdWJsaXNoZXIsIGRhdGEpIHtcbiAgICBzdXBlcih0eXBlLCBkYXRhKVxuICAgIHRoaXMuX3B1Ymxpc2hlciA9IHB1Ymxpc2hlclxuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBQdWJsaXNoZXIgaW5zdGFuY2UgdGhhdCBkaXNwYXRjaGVkIHRoZSBldmVudC5cbiAgICpcbiAgICogQHR5cGUge09iamVjdH1cbiAgICpcbiAgICogQHNlZSBSZWQ1UHJvUHVibGlzaGVyXG4gICAqIEBzZWUgUlRDUHVibGlzaGVyXG4gICAqIEBzZWUgUlRNUFB1Ymxpc2hlclxuICAgKi9cbiAgZ2V0IHB1Ymxpc2hlciAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3B1Ymxpc2hlclxuICB9XG5cbn1cblxuLyoqXG4gKiBCYXNlIFN1YnNjcmliZXItcmVsYXRlZCBFdmVudC5cbiAqXG4gKiBAZXh0ZW5kcyBFdmVudFxuICovXG5jbGFzcyBTdWJzY3JpYmVyRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgY29uc3RydWN0b3IgKHR5cGUsIHN1YnNjcmliZXIsIGRhdGEpIHtcbiAgICBzdXBlcih0eXBlLCBkYXRhKVxuICAgIHRoaXMuX3N1YnNjcmliZXIgPSBzdWJzY3JpYmVyXG4gIH1cblxuICAvKipcbiAgICogVGhlIFN1YnNjcmliZXIgaW5zdGFuY2UgdGhhdCBkaXNwYXRjaGVkIHRoZSBldmVudC5cbiAgICpcbiAgICogQHR5cGUge09iamVjdH1cbiAgICpcbiAgICogQHNlZSBSZWQ1UHJvU3Vic2NyaWJlclxuICAgKiBAc2VlIFJUQ1N1YnNjcmliZXJcbiAgICogQHNlZSBSVE1QU3Vic2NyaWJlclxuICAgKiBAc2VlIEhMU3Vic2NyaWJlclxuICAgKi9cbiAgZ2V0IHN1YnNjcmliZXIgKCkge1xuICAgIHJldHVybiB0aGlzLl9zdWJzY3JpYmVyXG4gIH1cblxufVxuXG4vKipcbiAqIEJhc2UgU2hhcmVkT2JqZWN0LXJlbGF0ZWQgRXZlbnQuXG4gKlxuICogQGV4dGVuZHMgRXZlbnRcbiAqL1xuY2xhc3MgU2hhcmVkT2JqZWN0RXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgY29uc3RydWN0b3IgKHR5cGUsIHNoYXJlZE9iamVjdE5hbWUsIGRhdGEpIHtcbiAgICBzdXBlcih0eXBlLCBkYXRhKVxuICAgIHRoaXMuX25hbWUgPSBzaGFyZWRPYmplY3ROYW1lXG4gIH1cblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIFNoYXJlZCBPYmplY3QuXG4gICAqXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqXG4gICAqIEBzZWUge1JlZDVQcm9TaGFyZWRPYmplY3R9XG4gICAqL1xuICBnZXQgbmFtZSAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX25hbWVcbiAgfVxuXG59XG5cbmV4cG9ydCB7IEV2ZW50IGFzIEV2ZW50IH1cbmV4cG9ydCB7IFB1Ymxpc2hlckV2ZW50IGFzIFB1Ymxpc2hlckV2ZW50IH1cbmV4cG9ydCB7IFN1YnNjcmliZXJFdmVudCBhcyBTdWJzY3JpYmVyRXZlbnQgfVxuZXhwb3J0IHsgU2hhcmVkT2JqZWN0RXZlbnQgYXMgU2hhcmVkT2JqZWN0RXZlbnQgfVxuZXhwb3J0IHsgUHVibGlzaGVyRXZlbnRUeXBlcyBhcyBQdWJsaXNoZXJFdmVudFR5cGVzIH0gZnJvbSAnLi9wdWJsaXNoZXItZXZlbnQnXG5leHBvcnQgeyBSVENQdWJsaXNoZXJFdmVudFR5cGVzIGFzIFJUQ1B1Ymxpc2hlckV2ZW50VHlwZXMgfSBmcm9tICcuL3B1Ymxpc2hlci1ldmVudCdcbmV4cG9ydCB7IFJUTVBQdWJsaXNoZXJFdmVudFR5cGVzIGFzIFJUTVBQdWJsaXNoZXJFdmVudFR5cGVzIH0gZnJvbSAnLi9wdWJsaXNoZXItZXZlbnQnXG5leHBvcnQgeyBGYWlsb3ZlclB1Ymxpc2hlckV2ZW50VHlwZXMgYXMgRmFpbG92ZXJQdWJsaXNoZXJFdmVudFR5cGVzIH0gZnJvbSAnLi9wdWJsaXNoZXItZXZlbnQnXG5leHBvcnQgeyBTdWJzY3JpYmVyRXZlbnRUeXBlcyBhcyBTdWJzY3JpYmVyRXZlbnRUeXBlcyB9IGZyb20gJy4vc3Vic2NyaWJlci1ldmVudCdcbmV4cG9ydCB7IFJUQ1N1YnNjcmliZXJFdmVudFR5cGVzIGFzIFJUQ1N1YnNjcmliZXJFdmVudFR5cGVzIH0gZnJvbSAnLi9zdWJzY3JpYmVyLWV2ZW50J1xuZXhwb3J0IHsgUlRNUFN1YnNjcmliZXJFdmVudFR5cGVzIGFzIFJUTVBTdWJzY3JpYmVyRXZlbnRUeXBlcyB9IGZyb20gJy4vc3Vic2NyaWJlci1ldmVudCdcbmV4cG9ydCB7IEZhaWxvdmVyU3Vic2NyaWJlckV2ZW50VHlwZXMgYXMgRmFpbG92ZXJTdWJzY3JpYmVyRXZlbnRUeXBlcyB9IGZyb20gJy4vc3Vic2NyaWJlci1ldmVudCdcbmV4cG9ydCB7IFNoYXJlZE9iamVjdEV2ZW50VHlwZXMgYXMgU2hhcmVkT2JqZWN0RXZlbnRUeXBlcyB9IGZyb20gJy4vc2hhcmVkb2JqZWN0LWV2ZW50J1xuXG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvanMvZXZlbnQvaW5kZXguanMiLCJ2YXIgaXNPYmplY3QgPSByZXF1aXJlKCcuL19pcy1vYmplY3QnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaXQpe1xuICBpZighaXNPYmplY3QoaXQpKXRocm93IFR5cGVFcnJvcihpdCArICcgaXMgbm90IGFuIG9iamVjdCEnKTtcbiAgcmV0dXJuIGl0O1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2FuLW9iamVjdC5qc1xuLy8gbW9kdWxlIGlkID0gMTZcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8gVGhhbmsncyBJRTggZm9yIGhpcyBmdW5ueSBkZWZpbmVQcm9wZXJ0eVxubW9kdWxlLmV4cG9ydHMgPSAhcmVxdWlyZSgnLi9fZmFpbHMnKShmdW5jdGlvbigpe1xuICByZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCAnYScsIHtnZXQ6IGZ1bmN0aW9uKCl7IHJldHVybiA3OyB9fSkuYSAhPSA3O1xufSk7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19kZXNjcmlwdG9ycy5qc1xuLy8gbW9kdWxlIGlkID0gMTdcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSB7IFwiZGVmYXVsdFwiOiByZXF1aXJlKFwiY29yZS1qcy9saWJyYXJ5L2ZuL29iamVjdC9mcmVlemVcIiksIF9fZXNNb2R1bGU6IHRydWUgfTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vYmFiZWwtcnVudGltZS9jb3JlLWpzL29iamVjdC9mcmVlemUuanNcbi8vIG1vZHVsZSBpZCA9IDE4XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIG9wdGlvbmFsIC8gc2ltcGxlIGNvbnRleHQgYmluZGluZ1xudmFyIGFGdW5jdGlvbiA9IHJlcXVpcmUoJy4vX2EtZnVuY3Rpb24nKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZm4sIHRoYXQsIGxlbmd0aCl7XG4gIGFGdW5jdGlvbihmbik7XG4gIGlmKHRoYXQgPT09IHVuZGVmaW5lZClyZXR1cm4gZm47XG4gIHN3aXRjaChsZW5ndGgpe1xuICAgIGNhc2UgMTogcmV0dXJuIGZ1bmN0aW9uKGEpe1xuICAgICAgcmV0dXJuIGZuLmNhbGwodGhhdCwgYSk7XG4gICAgfTtcbiAgICBjYXNlIDI6IHJldHVybiBmdW5jdGlvbihhLCBiKXtcbiAgICAgIHJldHVybiBmbi5jYWxsKHRoYXQsIGEsIGIpO1xuICAgIH07XG4gICAgY2FzZSAzOiByZXR1cm4gZnVuY3Rpb24oYSwgYiwgYyl7XG4gICAgICByZXR1cm4gZm4uY2FsbCh0aGF0LCBhLCBiLCBjKTtcbiAgICB9O1xuICB9XG4gIHJldHVybiBmdW5jdGlvbigvKiAuLi5hcmdzICovKXtcbiAgICByZXR1cm4gZm4uYXBwbHkodGhhdCwgYXJndW1lbnRzKTtcbiAgfTtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19jdHguanNcbi8vIG1vZHVsZSBpZCA9IDE5XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsInZhciBoYXNPd25Qcm9wZXJ0eSA9IHt9Lmhhc093blByb3BlcnR5O1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdCwga2V5KXtcbiAgcmV0dXJuIGhhc093blByb3BlcnR5LmNhbGwoaXQsIGtleSk7XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9faGFzLmpzXG4vLyBtb2R1bGUgaWQgPSAyMFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJ2YXIgZFAgICAgICAgICA9IHJlcXVpcmUoJy4vX29iamVjdC1kcCcpXG4gICwgY3JlYXRlRGVzYyA9IHJlcXVpcmUoJy4vX3Byb3BlcnR5LWRlc2MnKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9fZGVzY3JpcHRvcnMnKSA/IGZ1bmN0aW9uKG9iamVjdCwga2V5LCB2YWx1ZSl7XG4gIHJldHVybiBkUC5mKG9iamVjdCwga2V5LCBjcmVhdGVEZXNjKDEsIHZhbHVlKSk7XG59IDogZnVuY3Rpb24ob2JqZWN0LCBrZXksIHZhbHVlKXtcbiAgb2JqZWN0W2tleV0gPSB2YWx1ZTtcbiAgcmV0dXJuIG9iamVjdDtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19oaWRlLmpzXG4vLyBtb2R1bGUgaWQgPSAyMVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyB0byBpbmRleGVkIG9iamVjdCwgdG9PYmplY3Qgd2l0aCBmYWxsYmFjayBmb3Igbm9uLWFycmF5LWxpa2UgRVMzIHN0cmluZ3NcbnZhciBJT2JqZWN0ID0gcmVxdWlyZSgnLi9faW9iamVjdCcpXG4gICwgZGVmaW5lZCA9IHJlcXVpcmUoJy4vX2RlZmluZWQnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaXQpe1xuICByZXR1cm4gSU9iamVjdChkZWZpbmVkKGl0KSk7XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fdG8taW9iamVjdC5qc1xuLy8gbW9kdWxlIGlkID0gMjJcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiY29uc3QgV0lMRENBUkQgPSAnKidcbmNvbnN0IFdJTERDQVJEX0tFWSA9ICdSRUQ1UFJPJ1xuXG4vKipcbiAqIEJhc2UgY2xhc3MgZm9yIGFuIEV2ZW50IEVtaXR0ZXIuXG4gKi9cbmNsYXNzIEV2ZW50RW1pdHRlciB7XG5cbiAgY29uc3RydWN0b3IgKCkge1xuICAgIHRoaXMuX2NhbGxiYWNrcyA9IHt9XG4gICAgdGhpcy5fY2FsbGJhY2tzW1dJTERDQVJEX0tFWV0gPSBbXVxuICB9XG5cbiAgLyoqXG4gICAqIEludm9rZXMgZXZlbnQgaGFuZGxlcnMuXG4gICAqXG4gICAqIEBwYXJhbSB7QXJyYXl9IGNhbGxiYWNrc1xuICAgKiBAcGFyYW0ge0V2ZW50fSBldmVudFxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX25vdGlmeSAoY2FsbGJhY2tzLCBldmVudCkge1xuICAgICAgbGV0IGksIGxlbmd0aCA9IGNhbGxiYWNrcy5sZW5ndGhcbiAgICAgIGZvcihpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNhbGxiYWNrc1tpXShldmVudClcbiAgICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBc3NpZ24gYSBjYWxsYmFjayBoYW5kbGVyIHRvIGFuIGV2ZW50IHR5cGUuXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuXG4gICAqL1xuICBvbiAodHlwZSwgZm4pIHtcbiAgICBpZiAodHlwZW9mIGZuICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBpZiAodHlwZSA9PT0gV0lMRENBUkQpIHtcbiAgICAgIHRoaXMuX2NhbGxiYWNrc1tXSUxEQ0FSRF9LRVldLnB1c2goZm4pXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBpZiAodGhpcy5fY2FsbGJhY2tzW3R5cGVdID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuX2NhbGxiYWNrc1t0eXBlXSA9IFtdXG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX2NhbGxiYWNrc1t0eXBlXS5pbmRleE9mKGZuKSA9PT0gLTEpIHtcbiAgICAgIHRoaXMuX2NhbGxiYWNrc1t0eXBlXS5wdXNoKGZuKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgYSBjYWxsYmFjayBoYW5kbGVyIGZvciBhbiBldmVudCB0eXBlLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gdHlwZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmblxuICAgKi9cbiAgb2ZmICh0eXBlLCBmbikge1xuICAgIGxldCBtYXAgPSB0aGlzLl9jYWxsYmFja3NbdHlwZV1cbiAgICBpZiAodHlwZSA9PT0gV0lMRENBUkQpIHtcbiAgICAgIG1hcCA9IHRoaXMuX2NhbGxiYWNrc1tXSUxEQ0FSRF9LRVldXG4gICAgfVxuICAgIGlmIChtYXApIHtcbiAgICAgIGNvbnN0IGluZGV4ID0gbWFwLmluZGV4T2YoZm4pXG4gICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgIG1hcC5zcGxpY2UoaW5kZXgsIDEpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERpc3BhdGNoIGFuIGV2ZW50IHRvIGJlIGhhbmRsZWQgYnkgYW55IGFzc2lnbmVkIGNhbGxiYWNrcy5cbiAgICpcbiAgICogQHBhcmFtIHtFdmVudH0gZXZlbnRcbiAgICovXG4gIHRyaWdnZXIgKGV2ZW50KSB7XG4gICAgY29uc3QgdHlwZSA9IGV2ZW50LnR5cGVcbiAgICBpZiAodGhpcy5fY2FsbGJhY2tzW3R5cGVdKSB7XG4gICAgICB0aGlzLl9ub3RpZnkodGhpcy5fY2FsbGJhY2tzW3R5cGVdLCBldmVudClcbiAgICB9XG4gICAgdGhpcy5fbm90aWZ5KHRoaXMuX2NhbGxiYWNrc1tXSUxEQ0FSRF9LRVldLCBldmVudClcbiAgfVxuXG59XG5cbmV4cG9ydCBkZWZhdWx0IEV2ZW50RW1pdHRlclxuXG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvanMvY29yZS9ldmVudC1lbWl0dGVyLmpzIiwiJ3VzZSBzdHJpY3QnXG5cbmltcG9ydCBFdmVudEVtaXR0ZXIgZnJvbSAnLi4vLi4vY29yZS9ldmVudC1lbWl0dGVyJ1xuaW1wb3J0IGVudmlyb25tZW50IGZyb20gJy4uLy4uL2Vudi9icm93c2VyJ1xuaW1wb3J0IENvbnRyb2xTbGlkZXIgZnJvbSAnLi9zbGlkZXInXG5pbXBvcnQgeyBTbGlkZXJFdmVudFR5cGVzIH0gZnJvbSAnLi9ldmVudCdcbmltcG9ydCB7IFBsYXliYWNrU3RhdGUsIFBsYXliYWNrU3RhdGVSZWFkYWJsZSB9IGZyb20gJy4vc3RhdGUnXG5pbXBvcnQgeyBkZWJ1ZyB9IGZyb20gJy4uLy4uL2xvZydcblxuY29uc3QgTkFNRSA9ICdQbGF5YmFja0NvbnRyb2xzJ1xuXG4vKipcbiAqIEludGVyZmFjZSBjb250cmFjdCBmb3IgcGxheWJhY2sgY29udHJvbGxlciBhY3Rpb25zLlxuICpcbiAqIEBleHRlbmRzIEV2ZW50RW1pdHRlclxuICovXG5jbGFzcyBTdWJzY3JpYmVyUGxheWJhY2tDb250cm9sbGVyIGV4dGVuZHMgRXZlbnRFbWl0dGVyIHtcblxuICBjb25zdHJ1Y3RvciAoKSB7XG4gICAgc3VwZXIoKVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gc3RhcnQgcGxheWluZyB0aGUgc3RyZWFtLlxuICAgKi9cbiAgcGxheSAoKSB7fVxuICAgIC8qKlxuICAgICAqIFJlcXVlc3QgdG8gcGF1c2UgcGxheWJhY2sgb2Ygc3RyZWFtLlxuICAgICAqL1xuICBwYXVzZSAoKSB7fVxuICAgIC8qKlxuICAgICAqIFJlcXVlc3QgdG8gcmVzdW1lIHBsYXliYWNrIG9kIHN0cmVhbS5cbiAgICAgKi9cbiAgcmVzdW1lICgpIHt9XG4gICAgLyoqXG4gICAgICogUmVxdWVzdCB0byBzdG9wIHBsYXliYWNrIG9mIHN0cmVhbS5cbiAgICAgKi9cbiAgc3RvcCAoKSB7fVxuICAvKipcbiAgICogUmVxdWVzdCB0byBtdXRlIHRoZSBhdWRpbyBvZiB0aGUgc3RyZWFtLlxuICAgKi9cbiAgbXV0ZSAoKSB7fVxuICAvKipcbiAgICogUmVxdWVzdCB0byB1bm11dGUgdGhlIGF1ZGlvIG9mIHRoZSBzdHJlYW0uXG4gICAqL1xuICB1bm11dGUgKCkge31cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gc2V0IHZvbHVtZSBvZiBhdWRpbyBvZiBzdHJlYW0uXG4gICAqXG4gICAqIEBwYXJhbSB7TnVtYmVyfSB2YWx1ZVxuICAgKiAgICAgICAgRnJvbSAwLi4xLlxuICAgKi9cbiAgc2V0Vm9sdW1lICh2YWx1ZSkge30gLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuICAvKipcbiAgICogUmVxdWVzdCB0byBzZXQgcGxheWJhY2sgcG9pbnQgaW4gdGltZS5cbiAgICpcbiAgICogQHBhcmFtIHtOdW1iZXJ9IHZhbHVlXG4gICAqICAgICAgICBFaXRoZXIgdGhlIHBlcmNlbnRhZ2Ugb2YgdGhlIGR1cmF0aW9uIChpZiBwcm92aWRlZCkgb3IgdGhlIHRpbWUgaW4gc2Vjb25kcy5cbiAgICogQHBhcmFtIHtOdW1iZXJ9IGR1cmF0aW9uXG4gICAqICAgICAgICBPcHRpb25hbCBkdXJhdGlvbiBvZiB2aWRlbyAod2hlbiBrbm93biB0aHJvdWdoIFZPRCkgdG8gdXNlIHRvIGRldGVybWluZSB0aW1lIGJhc2VkIG9uIGZpcnN0IHBhcmFtIHBhc3NlZCBhcyBwZXJjZW50YWdlLlxuICAgKi9cbiAgc2Vla1RvICh2YWx1ZSwgZHVyYXRpb24gPSB1bmRlZmluZWQpIHt9IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW51c2VkLXZhcnNcbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gdG9nZ2xlIGZ1bGxzY3JlZW4gc3RhdGUuXG4gICAqL1xuICB0b2dnbGVGdWxsU2NyZWVuICgpIHt9XG5cbn1cblxuLyoqXG4gKiBJbnRlcmZhY2UgZm9yIFBsYXliYWNrQ29udHJvbHMgdXNlZCBieSBTdWJzY3JpYmVycyB3aXRoIGBjb250cm9sc2AgYW5kIGBjbGFzcz1cInJlZDVwcm8tbWVkaWFgIGRlZmluZWQgb24gdGFyZ2V0IGVsZW1lbnRzLiBUaGlzIGludGVyZmFjZSBzZXJ2ZXMgYXMgYSBwcmVzZW50YXRpb24gY29udHJvbGxlciBhbmQgcGxheWJhY2sgQVBJIGZvciB0YXJnZXQgRE9NIGVsZW1lbnRzLlxuICpcbiAqIFlvdSBjYW4gdXNlIHRoaXMgYXMgYSBwcm90b3R5cGUgZm9yIGNyZWF0aW5nIGFuZCBwcm92aWRpbmcgeW91ciBvd24gY3VzdG9tIFBsYXliYWNrIENvbnRyb2xzLiBUbyBkbyBzbzogcHJvdmlkZSBhbiBpbXBsZW1lbnRhdGlvbiBvZiB0aGlzIENsYXNzIGFzIHRoZSBgY29udHJvbHNgIHByb3BlcnR5IG9uIHRoZSBpbml0aWFsaXphdGlvbiBjb25maWd1cmF0aW9uIG1hcCBwcm92aWRlZCBpbiB0aGUgYGluaXQoKWAgY2FsbCBvZiBhIFN1YnNjcmliZXIuXG4gKlxuICogVE9ETzogRnVsbHkgdmV0IHRoZSB2aWFiaWxpdHkgb2YgZGV2ZWxvcGVycyBiZWluZyBhZGhlcmUgdG8gdGhpcyBjb250cmFjdCBmb3IgY3VzdG9tIGNvbnRyb2xzLlxuICogQHByaXZhdGVcbiAqL1xuY2xhc3MgU3Vic2NyaWJlclBsYXliYWNrQ29udHJvbHMge1xuXG4gIGNvbnN0cnVjdG9yICgpIHt9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHZvbHVtZSBsZXZlbC5cbiAgICpcbiAgICogQHJldHVybiB7TnVtYmVyfSAwLi4xXG4gICAqL1xuICBnZXRWb2x1bWUgKCkge31cblxuICAvKipcbiAgICogU2V0cyB0aGUgdm9sdW1lIGxldmVsIG9mIHBsYXliYWNrLlxuICAgKlxuICAgKiBAcGFyYW0ge051bWJlcn0gdmFsdWVcbiAgICogICAgICAgIDAuLjFcbiAgICovXG4gIHNldFZvbHVtZSAodmFsdWUpIHt9IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW51c2VkLXZhcnNcblxuICAvKipcbiAgICogUmVxdWVzdCB0byBzZXQgcGxheWJhY2sgcG9pbnQgaW4gdGltZS5cbiAgICpcbiAgICogQHBhcmFtIHtOdW1iZXJ9IHZhbHVlXG4gICAqICAgICAgICBFaXRoZXIgdGhlIHBlcmNlbnRhZ2Ugb2YgdGhlIGR1cmF0aW9uIChpZiBwcm92aWRlZCkgb3IgdGhlIHRpbWUgaW4gc2Vjb25kcy5cbiAgICogQHBhcmFtIHtOdW1iZXJ9IGR1cmF0aW9uXG4gICAqICAgICAgICBPcHRpb25hbCBkdXJhdGlvbiBvZiB2aWRlbyAod2hlbiBrbm93biB0aHJvdWdoIFZPRCkgdG8gdXNlIHRvIGRldGVybWluZSB0aW1lIGJhc2VkIG9uIGZpcnN0IHBhcmFtIHBhc3NlZCBhcyBwZXJjZW50YWdlLlxuICAgKi9cbiAgc2V0U2Vla1RpbWUgKHZhbHVlLCBkdXJhdGlvbiA9IDApIHt9IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW51c2VkLXZhcnNcblxuICAvKipcbiAgICogU2V0cyB0aGUgcGxheWJhY2sgZHVyYXRpb24gb2YgdGhlIHN0cmVhbSwgaWYgYXZhaWxhYmxlIGZyb20gVk9EIChWaWRlbyBPbiBEZW1hbmQpLlxuICAgKlxuICAgKiBAcGFyYW0ge051bWJlcn0gdmFsdWVcbiAgICogICAgICAgIEluIHNlY29uZHMuXG4gICAqL1xuICBzZXRQbGF5YmFja0R1cmF0aW9uICh2YWx1ZSkge30gLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHBsYXliYWNrIHN0YXRlLlxuICAgKlxuICAgKiBAcmV0dXJuIHtOdW1iZXJ9XG4gICAqIEBzZWUge1BsYXliYWNrU3RhdGV9XG4gICAqL1xuICBnZXRTdGF0ZSAoKSB7fVxuXG4gIC8qKlxuICAgKiBTZXQgdGhlIGN1cnJlbnQgcGxheWJhY2sgc3RhdGUuXG4gICAqXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBzdGF0ZVxuICAgKiBAc2VlIHtQbGF5YmFja1N0YXRlfVxuICAgKi9cbiAgc2V0U3RhdGUgKHN0YXRlKSB7fSAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG5cbiAgLyoqXG4gICAqIFNldHMgcGxheWJhY2sgYXMgVk9EIChWaWRlbyBPbiBEZW1hbmQpIHR5cGUuXG4gICAqXG4gICAqIEBwYXJhbSB7Qm9vbGVhbn0gdmFsdWVcbiAgICovXG4gIHNldEFzVk9EICh2YWx1ZSkge30gLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuXG4gICAgLyoqXG4gICAqIEVuYWJsZXMgY29udHJvbHMgYW5kIGV2ZW50IGhhbmRsZXJzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgZW5hYmxlICh2YWx1ZSkge30gLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuXG59XG5cbi8qKlxuICogRGVmYXVsdCBpbXBsZW1lbnRhdGlvbiBvZiBgU3Vic2NyaWJlclBsYXliYWNrQ29udHJvbHNgIHVzZWQgaW50ZXJuYWxseSBpbiB0aGUgU0RLLlxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmNsYXNzIFN1YnNjcmliZXJQbGF5YmFja0NvbnRyb2xzSW1wbCBleHRlbmRzIFN1YnNjcmliZXJQbGF5YmFja0NvbnRyb2xzIHtcblxuICBjb25zdHJ1Y3RvciAocGxheWVyLCBjb250YWluZXIpIHtcbiAgICBzdXBlcigpXG4gICAgdGhpcy5wbGF5ZXIgPSBwbGF5ZXJcbiAgICB0aGlzLmNvbnRhaW5lciA9IGNvbnRhaW5lclxuICAgIHRoaXMuX2NvbnRyb2xiYXIgPSB1bmRlZmluZWRcbiAgICB0aGlzLl9wbGF5UGF1c2VCdXR0b24gPSB1bmRlZmluZWRcbiAgICB0aGlzLl9tdXRlQnV0dG9uID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fdm9sdW1lRmllbGQgPSB1bmRlZmluZWRcbiAgICB0aGlzLl9zZWVrVGltZUZpZWxkID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fdGltZUZpZWxkID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fZnVsbFNjcmVlbkJ1dHRvbiA9IHVuZGVmaW5lZFxuICAgIHRoaXMuX3N0YXRlID0gUGxheWJhY2tTdGF0ZS5JRExFXG4gICAgdGhpcy5fbXV0ZWRTdGF0ZSA9IGZhbHNlXG4gICAgdGhpcy5fcmVzdW1lQWZ0ZXJTZWVrID0gZmFsc2VcbiAgICB0aGlzLl9wbGF5YmFja0R1cmF0aW9uID0gMFxuICAgIHRoaXMuX3ZvbHVtZVZhbHVlID0gMVxuICAgIHRoaXMuX29uUGxheVBhdXNlQ2xpY2tCb3VuZCA9IHRoaXMuX29uUGxheVBhdXNlQ2xpY2suYmluZCh0aGlzKVxuICAgIHRoaXMuZGVjb3JhdGUodGhpcy5jb250YWluZXIpXG4gIH1cblxuICAvKipcbiAgICogRGVjb3JhdGVzIHRhcmdldCBjb250YWluZXIgd2l0aCBwbGF5YmFjayBjb250cm9sIGVsZW1lbnRzLlxuICAgKlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IGNvbnRhaW5lclxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgZGVjb3JhdGUgKGNvbnRhaW5lcikge1xuICAgIGRlYnVnKE5BTUUsICdbZGVjb3JhdGVdJylcbiAgICBsZXQgY29udHJvbGJhciA9IGVudmlyb25tZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpXG4gICAgY29udHJvbGJhci5jbGFzc0xpc3QuYWRkKCdyZWQ1cHJvLW1lZGlhLWNvbnRyb2wtYmFyJylcbiAgICB0aGlzLl9wbGF5UGF1c2VCdXR0b24gPSB0aGlzLl9jcmVhdGVQbGF5UGF1c2VCdXR0b24oKVxuICAgIHRoaXMuX211dGVCdXR0b24gPSB0aGlzLl9jcmVhdGVNdXRlQnV0dG9uKClcbiAgICB0aGlzLl92b2x1bWVGaWVsZCA9IHRoaXMuX2NyZWF0ZVZvbHVtZUNvbnRyb2woKVxuICAgIHRoaXMuX3NlZWtUaW1lRmllbGQgPSB0aGlzLl9jcmVhdGVTZWVrQ29udHJvbCgpXG4gICAgdGhpcy5fdGltZUZpZWxkID0gdGhpcy5fY3JlYXRlUGxheWJhY2tUaW1lKClcbiAgICB0aGlzLl9mdWxsU2NyZWVuQnV0dG9uID0gdGhpcy5fY3JlYXRlRnVsbFNjcmVlblRvZ2dsZSgpXG4gICAgY29udHJvbGJhci5hcHBlbmRDaGlsZCh0aGlzLl9wbGF5UGF1c2VCdXR0b24pXG4gICAgY29udHJvbGJhci5hcHBlbmRDaGlsZCh0aGlzLl90aW1lRmllbGQpXG4gICAgY29udHJvbGJhci5hcHBlbmRDaGlsZCh0aGlzLl9zZWVrVGltZUZpZWxkLnZpZXcpXG4gICAgY29udHJvbGJhci5hcHBlbmRDaGlsZCh0aGlzLl9tdXRlQnV0dG9uKVxuICAgIGNvbnRyb2xiYXIuYXBwZW5kQ2hpbGQodGhpcy5fdm9sdW1lRmllbGQudmlldylcbiAgICBjb250cm9sYmFyLmFwcGVuZENoaWxkKHRoaXMuX2Z1bGxTY3JlZW5CdXR0b24pXG4gICAgY29udGFpbmVyLmFwcGVuZENoaWxkKGNvbnRyb2xiYXIpXG4gICAgdGhpcy5fY29udHJvbGJhciA9IGNvbnRyb2xiYXJcblxuICAgIGlmIChlbnZpcm9ubWVudC5pc1RvdWNoRW5hYmxlZCgpKSB7XG4gICAgICAgIGNvbnRyb2xiYXIuY2xhc3NMaXN0LmFkZCgncmVkNXByby1tZWRpYS1jb250cm9sLWJhci1zaG93JylcbiAgICAvLyAgICB0aGlzLmNvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHtcbiAgICAvLyAgICAgIGNvbnRyb2xiYXIuY2xhc3NMaXN0LnRvZ2dsZSgncmVkNXByby1tZWRpYS1jb250cm9sLWJhci1zaG93JylcbiAgICAvLyAgICB9KVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHRoaXMuY29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlb3ZlcicsICgpID0+IHtcbiAgICAgICAgY29udHJvbGJhci5jbGFzc0xpc3QuYWRkKCdyZWQ1cHJvLW1lZGlhLWNvbnRyb2wtYmFyLXNob3cnKVxuICAgICAgfSlcbiAgICAgIHRoaXMuY29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlb3V0JywgKCkgPT4ge1xuICAgICAgICBjb250cm9sYmFyLmNsYXNzTGlzdC5yZW1vdmUoJ3JlZDVwcm8tbWVkaWEtY29udHJvbC1iYXItc2hvdycpXG4gICAgICB9KVxuICAgIH1cblxuICAgIHRoaXMuc2V0U3RhdGUoUGxheWJhY2tTdGF0ZS5JRExFKVxuICAgICAgLm9uRnVsbFNjcmVlbkNoYW5nZShmYWxzZSlcbiAgICAgIC5zZXRTZWVrVGltZSgwKVxuICAgICAgLmVuYWJsZShmYWxzZSlcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGljayBoYW5kbGVyIGZvciBwbGF5L3BhdXNlIGNvbnRyb2wuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfb25QbGF5UGF1c2VDbGljayAoKSB7XG4gICAgaWYgKHRoaXMuZ2V0U3RhdGUoKSA9PT0gUGxheWJhY2tTdGF0ZS5QTEFZSU5HKSB7XG4gICAgICB0aGlzLnBsYXllci5wYXVzZSgpXG4gICAgfVxuICAgIGVsc2UgaWYgKHRoaXMuZ2V0U3RhdGUoKSA9PT0gUGxheWJhY2tTdGF0ZS5QQVVTRUQpIHtcbiAgICAgIHRoaXMucGxheWVyLnJlc3VtZSgpXG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgdGhpcy5wbGF5ZXIucGxheSgpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgcGxheS9wYXVzZSBjb250cm9sLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX2NyZWF0ZVBsYXlQYXVzZUJ1dHRvbiAoKSB7XG4gICAgbGV0IGJ1dHRvbiA9IGVudmlyb25tZW50LmNyZWF0ZUVsZW1lbnQoJ2J1dHRvbicpXG4gICAgYnV0dG9uLnNldEF0dHJpYnV0ZSgnYXJpYS1sYWJlbCcsICdUb2dnbGUgUGxheWJhY2snKVxuICAgIGJ1dHRvbi5jbGFzc0xpc3QuYWRkKCdyZWQ1cHJvLW1lZGlhLWNvbnRyb2wtZWxlbWVudCcpXG4gICAgYnV0dG9uLmNsYXNzTGlzdC5hZGQoJ3JlZDVwcm8tbWVkaWEtZWxlbWVudC1idXR0b24nKVxuICAgIGJ1dHRvbi5jbGFzc0xpc3QuYWRkKCdyZWQ1cHJvLW1lZGlhLXBsYXlwYXVzZS1idXR0b24nKVxuICAgIHJldHVybiBidXR0b25cbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIG11dGUvdW5tdXRlIGNvbnRyb2wuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfY3JlYXRlTXV0ZUJ1dHRvbiAoKSB7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXNcbiAgICBsZXQgYnV0dG9uID0gZW52aXJvbm1lbnQuY3JlYXRlRWxlbWVudCgnYnV0dG9uJylcbiAgICBidXR0b24uc2V0QXR0cmlidXRlKCdhcmlhLWxhYmVsJywgJ1RvZ2dsZSBNdXRlIEF1ZGlvJylcbiAgICBidXR0b24uY2xhc3NMaXN0LmFkZCgncmVkNXByby1tZWRpYS1jb250cm9sLWVsZW1lbnQnKVxuICAgIGJ1dHRvbi5jbGFzc0xpc3QuYWRkKCdyZWQ1cHJvLW1lZGlhLWVsZW1lbnQtYnV0dG9uJylcbiAgICBidXR0b24uY2xhc3NMaXN0LmFkZCgncmVkNXByby1tZWRpYS1tdXRldW5tdXRlLWJ1dHRvbicpXG4gICAgYnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4ge1xuICAgICAgaWYgKHNlbGYuZ2V0TXV0ZWRTdGF0ZSgpKSB7XG4gICAgICAgIHNlbGYucGxheWVyLnVubXV0ZSgpXG4gICAgICAgIHNlbGYuc2V0TXV0ZWRTdGF0ZShmYWxzZSlcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBzZWxmLnBsYXllci5tdXRlKClcbiAgICAgICAgc2VsZi5zZXRNdXRlZFN0YXRlKHRydWUpXG4gICAgICB9XG4gICAgfSlcbiAgICByZXR1cm4gYnV0dG9uXG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyB2b2x1bWUgY29udHJvbC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9jcmVhdGVWb2x1bWVDb250cm9sICgpIHtcbiAgICBjb25zdCBzZWxmID0gdGhpc1xuICAgIGxldCBzbGlkZXIgPSBuZXcgQ29udHJvbFNsaWRlcigndm9sdW1lJylcbiAgICBzbGlkZXIudmlldy5jbGFzc0xpc3QuYWRkKCdyZWQ1cHJvLW1lZGlhLWNvbnRyb2wtZWxlbWVudCcpXG4gICAgc2xpZGVyLnZpZXcuY2xhc3NMaXN0LmFkZCgncmVkNXByby1tZWRpYS12b2x1bWUtc2xpZGVyJylcbiAgICBzbGlkZXIudmlldy5jbGFzc0xpc3QuYWRkKCdyZWQ1cHJvLW1lZGlhLXNsaWRlcicpXG4gICAgc2xpZGVyLm9uKFNsaWRlckV2ZW50VHlwZXMuQ0hBTkdFLCAoZXZlbnQpID0+IHtcbiAgICAgIGNvbnN0IHBlcmNlbnRhZ2UgPSBOdW1iZXIoZXZlbnQuZGF0YSlcbiAgICAgIHNlbGYucGxheWVyLnNldFZvbHVtZShwZXJjZW50YWdlKVxuICAgIH0pXG4gICAgcmV0dXJuIHNsaWRlclxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgc2VlayBjb250cm9sLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX2NyZWF0ZVNlZWtDb250cm9sICgpIHtcbiAgICBjb25zdCBzZWxmID0gdGhpc1xuICAgIGxldCBzbGlkZXIgPSBuZXcgQ29udHJvbFNsaWRlcignc2VlaycpXG4gICAgc2xpZGVyLnZpZXcuY2xhc3NMaXN0LmFkZCgncmVkNXByby1tZWRpYS1jb250cm9sLWVsZW1lbnQnKVxuICAgIHNsaWRlci52aWV3LmNsYXNzTGlzdC5hZGQoJ3JlZDVwcm8tbWVkaWEtc2Vla3RpbWUtc2xpZGVyJylcbiAgICBzbGlkZXIudmlldy5jbGFzc0xpc3QuYWRkKCdyZWQ1cHJvLW1lZGlhLXNsaWRlcicpXG4gICAgc2xpZGVyLm9uKFNsaWRlckV2ZW50VHlwZXMuQ0hBTkdFX1NUQVJULCAoKSA9PiB7XG4gICAgICBpZiAoc2VsZi5nZXRTdGF0ZSgpID09PSBQbGF5YmFja1N0YXRlLlBMQVlJTkcpIHtcbiAgICAgICAgc2VsZi5fcmVzdW1lQWZ0ZXJTZWVrID0gdHJ1ZVxuICAgICAgICBzZWxmLnBsYXllci5wYXVzZSgpXG4gICAgICB9XG4gICAgfSlcbiAgICBzbGlkZXIub24oU2xpZGVyRXZlbnRUeXBlcy5DSEFOR0UsIChldmVudCkgPT4ge1xuICAgICAgY29uc3QgcGVyY2VudGFnZSA9IE51bWJlcihldmVudC5kYXRhKVxuICAgICAgc2VsZi5wbGF5ZXIuc2Vla1RvKHBlcmNlbnRhZ2UsIHNlbGYuX3BsYXliYWNrRHVyYXRpb24gPT09IDAgPyB1bmRlZmluZWQ6IHNlbGYuX3BsYXliYWNrRHVyYXRpb24pXG4gICAgICBzZWxmLnNldFNlZWtUaW1lKHBlcmNlbnRhZ2UgKiBzZWxmLl9wbGF5YmFja0R1cmF0aW9uLCBzZWxmLl9wbGF5YmFja0R1cmF0aW9uKVxuICAgIH0pXG4gICAgc2xpZGVyLm9uKFNsaWRlckV2ZW50VHlwZXMuQ0hBTkdFX0NPTVBMRVRFLCAoKSA9PiB7XG4gICAgICBpZiAoc2VsZi5fcmVzdW1lQWZ0ZXJTZWVrICYmIHNlbGYuZ2V0U3RhdGUoKSA9PT0gUGxheWJhY2tTdGF0ZS5QQVVTRUQpIHtcbiAgICAgICAgc2VsZi5fcmVzdW1lQWZ0ZXJTZWVrID0gZmFsc2VcbiAgICAgICAgc2VsZi5wbGF5ZXIucmVzdW1lKClcbiAgICAgIH1cbiAgICB9KVxuICAgIHJldHVybiBzbGlkZXJcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIHBsYXliYWNrIHRpbWUgZmllbGQuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfY3JlYXRlUGxheWJhY2tUaW1lICgpIHtcbiAgICBsZXQgc3BhbiA9IGVudmlyb25tZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKVxuICAgIGxldCB0ZXh0ID0gZW52aXJvbm1lbnQuY3JlYXRlRWxlbWVudCgndGV4dCcsICdoZWxsbyEnKVxuICAgIHNwYW4uY2xhc3NMaXN0LmFkZCgncmVkNXByby1tZWRpYS1jb250cm9sLWVsZW1lbnQnKVxuICAgIHNwYW4uY2xhc3NMaXN0LmFkZCgncmVkNXByby1tZWRpYS10aW1lLWZpZWxkJylcbiAgICBzcGFuLmFwcGVuZENoaWxkKHRleHQpXG4gICAgcmV0dXJuIHNwYW5cbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgZnVsbHNjcmVlbiB0b2dnbGUgY29udHJvbC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9jcmVhdGVGdWxsU2NyZWVuVG9nZ2xlICgpIHtcbiAgICBjb25zdCBzZWxmID0gdGhpc1xuICAgIGxldCBidXR0b24gPSBlbnZpcm9ubWVudC5jcmVhdGVFbGVtZW50KCdidXR0b24nKVxuICAgIGJ1dHRvbi5zZXRBdHRyaWJ1dGUoJ2FyaWEtbGFiZWwnLCAnVG9nZ2xlIEZ1bGxzY3JlZW4nKVxuICAgIGJ1dHRvbi5jbGFzc0xpc3QuYWRkKCdyZWQ1cHJvLW1lZGlhLWNvbnRyb2wtZWxlbWVudCcpXG4gICAgYnV0dG9uLmNsYXNzTGlzdC5hZGQoJ3JlZDVwcm8tbWVkaWEtZWxlbWVudC1idXR0b24nKVxuICAgIGJ1dHRvbi5jbGFzc0xpc3QuYWRkKCdyZWQ1cHJvLW1lZGlhLWZ1bGxzY3JlZW4tYnV0dG9uJylcbiAgICBidXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB7XG4gICAgICBzZWxmLnBsYXllci50b2dnbGVGdWxsU2NyZWVuKClcbiAgICB9KVxuICAgIHJldHVybiBidXR0b25cbiAgfVxuXG4gIC8qKlxuICAgKiBFbmFibGVzIGNvbnRyb2xzIGFuZCBldmVudCBoYW5kbGVycy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIGVuYWJsZSAodmFsdWUpIHtcbiAgICBpZiAodmFsdWUpIHtcbiAgICAgIHRoaXMuX3BsYXlQYXVzZUJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKCdyZWQ1cHJvLW1lZGlhLWVsZW1lbnQtYnV0dG9uLWRpc2FibGVkJylcbiAgICAgIHRoaXMuX3BsYXlQYXVzZUJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX29uUGxheVBhdXNlQ2xpY2tCb3VuZClcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICB0aGlzLl9wbGF5UGF1c2VCdXR0b24uY2xhc3NMaXN0LmFkZCgncmVkNXByby1tZWRpYS1lbGVtZW50LWJ1dHRvbi1kaXNhYmxlZCcpXG4gICAgICB0aGlzLl9wbGF5UGF1c2VCdXR0b24ucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9vblBsYXlQYXVzZUNsaWNrQm91bmQpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEZvcm1hdHMgdGhlIHRpbWUgdmFsdWUuXG4gICAqXG4gICAqIEBwYXJhbSB7dmFsdWV9IE51bWJlclxuICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAqL1xuICBmb3JtYXRUaW1lICh2YWx1ZSkge1xuICAgIGxldCBocnMgPSAwXG4gICAgbGV0IG1pbnMgPSB2YWx1ZSA9PT0gMCA/IDAgOiBwYXJzZUludCh2YWx1ZSAvIDYwKVxuICAgIGxldCBzZWNzID0gMFxuICAgIGlmIChtaW5zID49IDYwKSB7XG4gICAgICBocnMgPSBwYXJzZUludChtaW5zIC8gNjApXG4gICAgICBtaW5zID0gbWlucyAlIDYwXG4gICAgfVxuICAgIHNlY3MgPSB2YWx1ZSA9PT0gMCA/IDAgOiBwYXJzZUludCh2YWx1ZSAlIDYwKVxuXG4gICAgbGV0IGZvcm1hdHRlZEFyciA9IChocnMgPCAxMCkgPyBbJzAnICsgaHJzXSA6IFtocnNdXG4gICAgZm9ybWF0dGVkQXJyLnB1c2goKG1pbnMgPCAxMCkgPyBbJzAnICsgbWluc10gOiBbbWluc10pXG4gICAgZm9ybWF0dGVkQXJyLnB1c2goKHNlY3MgPCAxMCkgPyBbJzAnICsgc2Vjc10gOiBbc2Vjc10pXG4gICAgcmV0dXJuIGZvcm1hdHRlZEFyci5qb2luKCc6JylcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSB2b2x1bWUgbGV2ZWwuXG4gICAqXG4gICAqIEByZXR1cm4ge051bWJlcn0gMC4uMVxuICAgKi9cbiAgZ2V0Vm9sdW1lICgpIHtcbiAgICByZXR1cm4gdGhpcy5fdm9sdW1lVmFsdWVcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSB2b2x1bWUgbGV2ZWwgb2YgcGxheWJhY2suXG4gICAqXG4gICAqIEBwYXJhbSB7TnVtYmVyfSB2YWx1ZVxuICAgKiAgICAgICAgMC4uMVxuICAgKi9cbiAgc2V0Vm9sdW1lICh2YWx1ZSkge1xuICAgIHRoaXMuX3ZvbHVtZUZpZWxkLnZhbHVlID0gdmFsdWVcbiAgICB0aGlzLl92b2x1bWVWYWx1ZSA9IHZhbHVlXG4gICAgaWYgKHZhbHVlID09PSAwKSB7XG4gICAgICB0aGlzLnNldE11dGVkU3RhdGUodHJ1ZSlcbiAgICB9XG4gICAgZWxzZSBpZiAodGhpcy5nZXRNdXRlZFN0YXRlKCkpIHtcbiAgICAgIHRoaXMuc2V0TXV0ZWRTdGF0ZShmYWxzZSlcbiAgICB9XG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIHNldCBwbGF5YmFjayBwb2ludCBpbiB0aW1lLlxuICAgKlxuICAgKiBAcGFyYW0ge051bWJlcn0gdmFsdWVcbiAgICogICAgICAgIEVpdGhlciB0aGUgcGVyY2VudGFnZSBvZiB0aGUgZHVyYXRpb24gKGlmIHByb3ZpZGVkKSBvciB0aGUgdGltZSBpbiBzZWNvbmRzLlxuICAgKiBAcGFyYW0ge051bWJlcn0gZHVyYXRpb25cbiAgICogICAgICAgIE9wdGlvbmFsIGR1cmF0aW9uIG9mIHZpZGVvICh3aGVuIGtub3duIHRocm91Z2ggVk9EKSB0byB1c2UgdG8gZGV0ZXJtaW5lIHRpbWUgYmFzZWQgb24gZmlyc3QgcGFyYW0gcGFzc2VkIGFzIHBlcmNlbnRhZ2UuXG4gICAqL1xuICBzZXRTZWVrVGltZSAodmFsdWUsIGxlbmd0aCA9IDApIHtcbiAgICB0aGlzLl9zZWVrVGltZUZpZWxkLnZhbHVlID0gbGVuZ3RoID09PSAwID8gMCA6ICh2YWx1ZS9sZW5ndGgpXG4gICAgaWYgKHRoaXMuX3BsYXliYWNrRHVyYXRpb24gIT09IDAgJiYgcGFyc2VJbnQodGhpcy5fcGxheWJhY2tEdXJhdGlvbikgPD0gcGFyc2VJbnQodmFsdWUpKSB7XG4gICAgICB0aGlzLl9zZWVrVGltZUZpZWxkLnZhbHVlID0gMVxuICAgIH1cbiAgICB0aGlzLl90aW1lRmllbGQuaW5uZXJUZXh0ID0gdGhpcy5mb3JtYXRUaW1lKE1hdGguZmxvb3IodmFsdWUpKVxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgcGxheWJhY2sgZHVyYXRpb24gb2YgdGhlIHN0cmVhbSwgaWYgYXZhaWxhYmxlIGZyb20gVk9EIChWaWRlbyBPbiBEZW1hbmQpLlxuICAgKlxuICAgKiBAcGFyYW0ge051bWJlcn0gdmFsdWVcbiAgICogICAgICAgIEluIHNlY29uZHMuXG4gICAqL1xuICBzZXRQbGF5YmFja0R1cmF0aW9uICh2YWx1ZSkge1xuICAgIGRlYnVnKE5BTUUsICdbc2V0cGxheWJhY2tkdXJhdGlvbl06ICcgKyB2YWx1ZSlcbiAgICB0aGlzLl9wbGF5YmFja0R1cmF0aW9uID0gdmFsdWVcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHBsYXliYWNrIHN0YXRlLlxuICAgKlxuICAgKiBAcmV0dXJuIHtOdW1iZXJ9XG4gICAqIEBzZWUge1BsYXliYWNrU3RhdGV9XG4gICAqL1xuICBnZXRTdGF0ZSAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3N0YXRlXG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSBjdXJyZW50IHBsYXliYWNrIHN0YXRlLlxuICAgKlxuICAgKiBAcGFyYW0ge051bWJlcn0gc3RhdGVcbiAgICogQHNlZSB7UGxheWJhY2tTdGF0ZX1cbiAgICovXG4gIHNldFN0YXRlIChzdGF0ZSkge1xuICAgIGRlYnVnKE5BTUUsICdbc2V0U3RhdGVdOiAnICsgUGxheWJhY2tTdGF0ZVJlYWRhYmxlW3N0YXRlXSlcbiAgICB0aGlzLl9zdGF0ZSA9IHN0YXRlXG4gICAgdGhpcy5vblN0YXRlQ2hhbmdlKHRoaXMuX3N0YXRlKVxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgcGxheWJhY2sgYmVpbmcgbXV0ZWQuXG4gICAqIFRoaXMgZGlmZmVycyBmcm9tIGp1c3QgdGhlIHZvbHVtZSBsZXZlbCBiZWluZyAwLiBUaGUgY29udHJvbHMgY2FuIGJlIG11dGVkLCBidXQgaGF2ZSBhIHZvbHVtZSBsZXZlbCBncmVhdGVyIHRoYW4gMCAtIG1lYW5pbmcsIHVubXV0ZSB3aWxsIHJldHVybiBiYWNrIHRvIHRoZSB2b2x1bWUgbGV2ZWwgcHJldmlvdXNseSBzZXQuXG4gICAqXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBnZXRNdXRlZFN0YXRlICgpIHtcbiAgICByZXR1cm4gKCdtdXRlZCcgaW4gdGhpcy5wbGF5ZXIpID8gdGhpcy5wbGF5ZXIubXV0ZWQgOiB0aGlzLl9tdXRlZFN0YXRlXG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgbXV0ZWQgc3RhdGUgb2YgdGhlIHBsYXliYWNrLlxuICAgKlxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IHN0YXRlXG4gICAqL1xuICBzZXRNdXRlZFN0YXRlIChzdGF0ZSkge1xuICAgIHRoaXMuX211dGVkU3RhdGUgPSBzdGF0ZVxuICAgIHRoaXMub25NdXRlZFN0YXRlQ2hhbmdlKHRoaXMuX211dGVkU3RhdGUpXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGVyIGZvciBjaGFuZ2UgaW4gc3RhdGUuXG4gICAqXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBzdGF0ZVxuICAgKiAgICAgICAgVGhlIFBsYXliYWNrU3RhdGVcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIG9uU3RhdGVDaGFuZ2UgKHN0YXRlKSB7XG4gICAgaWYgKHN0YXRlID09PSBQbGF5YmFja1N0YXRlLlBMQVlJTkcpIHtcbiAgICAgIHRoaXMuX3BsYXlQYXVzZUJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKCdyZWQ1cHJvLW1lZGlhLXBsYXktYnV0dG9uJylcbiAgICAgIHRoaXMuX3BsYXlQYXVzZUJ1dHRvbi5jbGFzc0xpc3QuYWRkKCdyZWQ1cHJvLW1lZGlhLXBhdXNlLWJ1dHRvbicpXG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgdGhpcy5fcGxheVBhdXNlQnV0dG9uLmNsYXNzTGlzdC5hZGQoJ3JlZDVwcm8tbWVkaWEtcGxheS1idXR0b24nKVxuICAgICAgdGhpcy5fcGxheVBhdXNlQnV0dG9uLmNsYXNzTGlzdC5yZW1vdmUoJ3JlZDVwcm8tbWVkaWEtcGF1c2UtYnV0dG9uJylcbiAgICB9XG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGVyIGZvciBjaGFuZ2UgaW4gbXV0ZSBzdGF0ZS5cbiAgICpcbiAgICogQHBhcmFtIHtCb29sZWFufSBzdGF0ZVxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgb25NdXRlZFN0YXRlQ2hhbmdlIChzdGF0ZSkge1xuICAgIGlmIChzdGF0ZSkge1xuICAgICAgdGhpcy5fbXV0ZUJ1dHRvbi5jbGFzc0xpc3QuYWRkKCdyZWQ1cHJvLW1lZGlhLW11dGUtYnV0dG9uJylcbiAgICAgIHRoaXMuX211dGVCdXR0b24uY2xhc3NMaXN0LnJlbW92ZSgncmVkNXByby1tZWRpYS11bm11dGUtYnV0dG9uJylcbiAgICAgIHRoaXMuX3ZvbHVtZUZpZWxkLnZhbHVlID0gMFxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHRoaXMuX211dGVCdXR0b24uY2xhc3NMaXN0LnJlbW92ZSgncmVkNXByby1tZWRpYS1tdXRlLWJ1dHRvbicpXG4gICAgICB0aGlzLl9tdXRlQnV0dG9uLmNsYXNzTGlzdC5hZGQoJ3JlZDVwcm8tbWVkaWEtdW5tdXRlLWJ1dHRvbicpXG4gICAgICB0aGlzLl92b2x1bWVGaWVsZC52YWx1ZSA9IHRoaXMuX3ZvbHVtZVZhbHVlXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZXIgZm9yIGNoYW5nZSBpbiBmdWxsc2NyZWVuIHN0YXRlLlxuICAgKlxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IGlzRnVsbFNjcmVlblxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgb25GdWxsU2NyZWVuQ2hhbmdlIChpc0Z1bGxTY3JlZW4pIHtcbiAgICBpZiAoaXNGdWxsU2NyZWVuKSB7XG4gICAgICB0aGlzLl9mdWxsU2NyZWVuQnV0dG9uLmNsYXNzTGlzdC5hZGQoJ3JlZDVwcm8tbWVkaWEtZXhpdC1mdWxsc2NyZWVuLWJ1dHRvbicpXG4gICAgICB0aGlzLl9mdWxsU2NyZWVuQnV0dG9uLmNsYXNzTGlzdC5yZW1vdmUoJ3JlZDVwcm8tbWVkaWEtZnVsbHNjcmVlbi1idXR0b24nKVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHRoaXMuX2Z1bGxTY3JlZW5CdXR0b24uY2xhc3NMaXN0LnJlbW92ZSgncmVkNXByby1tZWRpYS1leGl0LWZ1bGxzY3JlZW4tYnV0dG9uJylcbiAgICAgIHRoaXMuX2Z1bGxTY3JlZW5CdXR0b24uY2xhc3NMaXN0LmFkZCgncmVkNXByby1tZWRpYS1mdWxsc2NyZWVuLWJ1dHRvbicpXG4gICAgfVxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICAvKipcbiAgICogU2V0cyBwbGF5YmFjayBhcyBWT0QgKFZpZGVvIE9uIERlbWFuZCkgdHlwZS5cbiAgICpcbiAgICogQHBhcmFtIHtCb29sZWFufSB2YWx1ZVxuICAgKi9cbiAgc2V0QXNWT0QgKGlzVk9EKSB7XG4gICAgZGVidWcoTkFNRSwgJ1tzZXRBc1ZPRF06ICcgKyBpc1ZPRClcbiAgICBpZiAoIWlzVk9EKSB7XG4gICAgICB0aGlzLl9zZWVrVGltZUZpZWxkLnZhbHVlPSAwXG4gICAgICB0aGlzLl9zZWVrVGltZUZpZWxkLmRpc2FibGVkID0gdHJ1ZVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHRoaXMuX3NlZWtUaW1lRmllbGQuZGlzYWJsZWQgPSBmYWxzZVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIGRldGFjaCB0aGUgY29udHJvbCBiYXIgdG8gcHJvdmlkZWQgY29udGFpbmVyLlxuICAgKi9cbiAgZGV0YWNoICgpIHtcbiAgICB0aGlzLmVuYWJsZShmYWxzZSlcbiAgICBpZiAodGhpcy5fY29udHJvbGJhciAmJiB0aGlzLl9jb250cm9sYmFyLnBhcmVudE5vZGUgPT09IHRoaXMuY29udGFpbmVyKSB7XG4gICAgICB0aGlzLmNvbnRhaW5lci5yZW1vdmVDaGlsZCh0aGlzLl9jb250cm9sYmFyKVxuICAgIH1cbiAgfVxuXG59XG5cbmV4cG9ydCBjb25zdCBQbGF5YmFja0NvbnRyb2xsZXIgPSBTdWJzY3JpYmVyUGxheWJhY2tDb250cm9sbGVyXG5leHBvcnQgY29uc3QgUGxheWJhY2tDb250cm9scyA9IFN1YnNjcmliZXJQbGF5YmFja0NvbnRyb2xzXG5leHBvcnQgY29uc3QgUGxheWJhY2tDb250cm9sc0ltcGwgPSBTdWJzY3JpYmVyUGxheWJhY2tDb250cm9sc0ltcGxcblxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2pzL3N1YnNjcmliZXIvY29udHJvbHMvaW5kZXguanMiLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGV4ZWMpe1xuICB0cnkge1xuICAgIHJldHVybiAhIWV4ZWMoKTtcbiAgfSBjYXRjaChlKXtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2ZhaWxzLmpzXG4vLyBtb2R1bGUgaWQgPSAyNVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIndXNlIHN0cmljdCc7XG52YXIgJGF0ICA9IHJlcXVpcmUoJy4vX3N0cmluZy1hdCcpKHRydWUpO1xuXG4vLyAyMS4xLjMuMjcgU3RyaW5nLnByb3RvdHlwZVtAQGl0ZXJhdG9yXSgpXG5yZXF1aXJlKCcuL19pdGVyLWRlZmluZScpKFN0cmluZywgJ1N0cmluZycsIGZ1bmN0aW9uKGl0ZXJhdGVkKXtcbiAgdGhpcy5fdCA9IFN0cmluZyhpdGVyYXRlZCk7IC8vIHRhcmdldFxuICB0aGlzLl9pID0gMDsgICAgICAgICAgICAgICAgLy8gbmV4dCBpbmRleFxuLy8gMjEuMS41LjIuMSAlU3RyaW5nSXRlcmF0b3JQcm90b3R5cGUlLm5leHQoKVxufSwgZnVuY3Rpb24oKXtcbiAgdmFyIE8gICAgID0gdGhpcy5fdFxuICAgICwgaW5kZXggPSB0aGlzLl9pXG4gICAgLCBwb2ludDtcbiAgaWYoaW5kZXggPj0gTy5sZW5ndGgpcmV0dXJuIHt2YWx1ZTogdW5kZWZpbmVkLCBkb25lOiB0cnVlfTtcbiAgcG9pbnQgPSAkYXQoTywgaW5kZXgpO1xuICB0aGlzLl9pICs9IHBvaW50Lmxlbmd0aDtcbiAgcmV0dXJuIHt2YWx1ZTogcG9pbnQsIGRvbmU6IGZhbHNlfTtcbn0pO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYuc3RyaW5nLml0ZXJhdG9yLmpzXG4vLyBtb2R1bGUgaWQgPSAyNlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJyZXF1aXJlKCcuL2VzNi5hcnJheS5pdGVyYXRvcicpO1xudmFyIGdsb2JhbCAgICAgICAgPSByZXF1aXJlKCcuL19nbG9iYWwnKVxuICAsIGhpZGUgICAgICAgICAgPSByZXF1aXJlKCcuL19oaWRlJylcbiAgLCBJdGVyYXRvcnMgICAgID0gcmVxdWlyZSgnLi9faXRlcmF0b3JzJylcbiAgLCBUT19TVFJJTkdfVEFHID0gcmVxdWlyZSgnLi9fd2tzJykoJ3RvU3RyaW5nVGFnJyk7XG5cbmZvcih2YXIgY29sbGVjdGlvbnMgPSBbJ05vZGVMaXN0JywgJ0RPTVRva2VuTGlzdCcsICdNZWRpYUxpc3QnLCAnU3R5bGVTaGVldExpc3QnLCAnQ1NTUnVsZUxpc3QnXSwgaSA9IDA7IGkgPCA1OyBpKyspe1xuICB2YXIgTkFNRSAgICAgICA9IGNvbGxlY3Rpb25zW2ldXG4gICAgLCBDb2xsZWN0aW9uID0gZ2xvYmFsW05BTUVdXG4gICAgLCBwcm90byAgICAgID0gQ29sbGVjdGlvbiAmJiBDb2xsZWN0aW9uLnByb3RvdHlwZTtcbiAgaWYocHJvdG8gJiYgIXByb3RvW1RPX1NUUklOR19UQUddKWhpZGUocHJvdG8sIFRPX1NUUklOR19UQUcsIE5BTUUpO1xuICBJdGVyYXRvcnNbTkFNRV0gPSBJdGVyYXRvcnMuQXJyYXk7XG59XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL3dlYi5kb20uaXRlcmFibGUuanNcbi8vIG1vZHVsZSBpZCA9IDI3XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIid1c2Ugc3RyaWN0J1xuXG4vKipcbiAqIERlZXAtZGVmaW5lcyBhbiBgT2JqZWN0YCBpbiBwbGFjZSB3aXRoIG5hbWVzcGFjZWQgYXR0cmlidXRlIHZhbHVlLlxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmV4cG9ydCBjb25zdCBkZWVwRGVmaW5lID0gKG9iamVjdCwgcGF0aHMsIHZhbHVlKSA9PiB7XG4gIGxldCBpID0gMFxuICBsZXQgdGFpbCA9IG9iamVjdFxuICBjb25zdCBwcm9wID0gcGF0aHMucG9wKClcbiAgY29uc3QgbGVuZ3RoID0gcGF0aHMubGVuZ3RoXG4gIGZvciAoaTsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgbGV0IHBhdGggPSBwYXRoc1tpXVxuICAgIHRhaWxbcGF0aF0gPSB0YWlsW3BhdGhdIHx8IHt9XG4gICAgdGFpbCA9IHRhaWxbcGF0aF1cbiAgfVxuICB0YWlsW3Byb3BdID0gdmFsdWVcbn1cblxuLyoqXG4gKiBEZWVwLWNvcHkgdXRpbGl6aW5nIEpTT04gQVBJLlxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmV4cG9ydCBjb25zdCBkZWVwQ29weSA9IChvYmopID0+IHtcbiAgY29uc3Qgc3RyID0gSlNPTi5zdHJpbmdpZnkob2JqKVxuICByZXR1cm4gSlNPTi5wYXJzZShzdHIpXG59XG5cbi8qKlxuICogU2ltcGxlIHV0aWwgdG8gcGFyc2UgcmVzb2x1dGlvbiBmcm9tIG1ldGFkYXRhLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSB2YWx1ZVxuICogICAgICAgIFRoZSByZXNvbHV0aW9uIHZhbHVlIGZyb20gbWV0YWRhdGE6IGUuZywgYDY0MCw0ODBgLlxuICogQHJldHVybiB7T2JqZWN0fVxuICogICAgICAgIFRoZSBzdHJ1Y3R1cmVkIGRpbWVuc2lvbnMgT2JqZWN0IHdpdGggYHdpZHRoYCBhbmQgYGhlaWdodGAgcHJvcGVydGllcy5cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5leHBvcnQgY29uc3QgbWV0YWRhdGFSZXNvbHV0aW9uVG9PYmplY3QgPSAodmFsdWUpID0+IHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICBsZXQgZGltcyA9IHZhbHVlLnNwbGl0KCcsJylcbiAgICByZXR1cm4ge1xuICAgICAgd2lkdGg6IHBhcnNlSW50KGRpbXNbMF0pLFxuICAgICAgaGVpZ2h0OiBwYXJzZUludChkaW1zWzFdKVxuICAgIH1cbiAgfVxuICByZXR1cm4gdmFsdWVcbn1cblxuLyoqXG4gKiBVdGlsaXR5IGNoZWNrIGlmIHByb3ZpZGluZyBPYmplY3QgaXMgZW1wdHkgKHdpdGhvdXQgYW55IHByb3BlcnRpZXMuXG4gKlxuICogQHByaXZhdGVcbiAqL1xuZXhwb3J0IGNvbnN0IGlzT2JqZWN0RW1wdHkgPSAob2JqKSA9PiB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmxlbmd0aCA9PT0gMCAmJiBvYmouY29uc3RydWN0b3IgPT09IE9iamVjdFxufVxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2pzL3V0aWwvb2JqZWN0LmpzIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbnZhciBfYXNzaWduID0gcmVxdWlyZShcIi4uL2NvcmUtanMvb2JqZWN0L2Fzc2lnblwiKTtcblxudmFyIF9hc3NpZ24yID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfYXNzaWduKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZXhwb3J0cy5kZWZhdWx0ID0gX2Fzc2lnbjIuZGVmYXVsdCB8fCBmdW5jdGlvbiAodGFyZ2V0KSB7XG4gIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHNvdXJjZSA9IGFyZ3VtZW50c1tpXTtcblxuICAgIGZvciAodmFyIGtleSBpbiBzb3VyY2UpIHtcbiAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoc291cmNlLCBrZXkpKSB7XG4gICAgICAgIHRhcmdldFtrZXldID0gc291cmNlW2tleV07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRhcmdldDtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2JhYmVsLXJ1bnRpbWUvaGVscGVycy9leHRlbmRzLmpzXG4vLyBtb2R1bGUgaWQgPSAyOVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9faXRlcmF0b3JzLmpzXG4vLyBtb2R1bGUgaWQgPSAzMFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJ2YXIgTUVUQSAgICAgPSByZXF1aXJlKCcuL191aWQnKSgnbWV0YScpXG4gICwgaXNPYmplY3QgPSByZXF1aXJlKCcuL19pcy1vYmplY3QnKVxuICAsIGhhcyAgICAgID0gcmVxdWlyZSgnLi9faGFzJylcbiAgLCBzZXREZXNjICA9IHJlcXVpcmUoJy4vX29iamVjdC1kcCcpLmZcbiAgLCBpZCAgICAgICA9IDA7XG52YXIgaXNFeHRlbnNpYmxlID0gT2JqZWN0LmlzRXh0ZW5zaWJsZSB8fCBmdW5jdGlvbigpe1xuICByZXR1cm4gdHJ1ZTtcbn07XG52YXIgRlJFRVpFID0gIXJlcXVpcmUoJy4vX2ZhaWxzJykoZnVuY3Rpb24oKXtcbiAgcmV0dXJuIGlzRXh0ZW5zaWJsZShPYmplY3QucHJldmVudEV4dGVuc2lvbnMoe30pKTtcbn0pO1xudmFyIHNldE1ldGEgPSBmdW5jdGlvbihpdCl7XG4gIHNldERlc2MoaXQsIE1FVEEsIHt2YWx1ZToge1xuICAgIGk6ICdPJyArICsraWQsIC8vIG9iamVjdCBJRFxuICAgIHc6IHt9ICAgICAgICAgIC8vIHdlYWsgY29sbGVjdGlvbnMgSURzXG4gIH19KTtcbn07XG52YXIgZmFzdEtleSA9IGZ1bmN0aW9uKGl0LCBjcmVhdGUpe1xuICAvLyByZXR1cm4gcHJpbWl0aXZlIHdpdGggcHJlZml4XG4gIGlmKCFpc09iamVjdChpdCkpcmV0dXJuIHR5cGVvZiBpdCA9PSAnc3ltYm9sJyA/IGl0IDogKHR5cGVvZiBpdCA9PSAnc3RyaW5nJyA/ICdTJyA6ICdQJykgKyBpdDtcbiAgaWYoIWhhcyhpdCwgTUVUQSkpe1xuICAgIC8vIGNhbid0IHNldCBtZXRhZGF0YSB0byB1bmNhdWdodCBmcm96ZW4gb2JqZWN0XG4gICAgaWYoIWlzRXh0ZW5zaWJsZShpdCkpcmV0dXJuICdGJztcbiAgICAvLyBub3QgbmVjZXNzYXJ5IHRvIGFkZCBtZXRhZGF0YVxuICAgIGlmKCFjcmVhdGUpcmV0dXJuICdFJztcbiAgICAvLyBhZGQgbWlzc2luZyBtZXRhZGF0YVxuICAgIHNldE1ldGEoaXQpO1xuICAvLyByZXR1cm4gb2JqZWN0IElEXG4gIH0gcmV0dXJuIGl0W01FVEFdLmk7XG59O1xudmFyIGdldFdlYWsgPSBmdW5jdGlvbihpdCwgY3JlYXRlKXtcbiAgaWYoIWhhcyhpdCwgTUVUQSkpe1xuICAgIC8vIGNhbid0IHNldCBtZXRhZGF0YSB0byB1bmNhdWdodCBmcm96ZW4gb2JqZWN0XG4gICAgaWYoIWlzRXh0ZW5zaWJsZShpdCkpcmV0dXJuIHRydWU7XG4gICAgLy8gbm90IG5lY2Vzc2FyeSB0byBhZGQgbWV0YWRhdGFcbiAgICBpZighY3JlYXRlKXJldHVybiBmYWxzZTtcbiAgICAvLyBhZGQgbWlzc2luZyBtZXRhZGF0YVxuICAgIHNldE1ldGEoaXQpO1xuICAvLyByZXR1cm4gaGFzaCB3ZWFrIGNvbGxlY3Rpb25zIElEc1xuICB9IHJldHVybiBpdFtNRVRBXS53O1xufTtcbi8vIGFkZCBtZXRhZGF0YSBvbiBmcmVlemUtZmFtaWx5IG1ldGhvZHMgY2FsbGluZ1xudmFyIG9uRnJlZXplID0gZnVuY3Rpb24oaXQpe1xuICBpZihGUkVFWkUgJiYgbWV0YS5ORUVEICYmIGlzRXh0ZW5zaWJsZShpdCkgJiYgIWhhcyhpdCwgTUVUQSkpc2V0TWV0YShpdCk7XG4gIHJldHVybiBpdDtcbn07XG52YXIgbWV0YSA9IG1vZHVsZS5leHBvcnRzID0ge1xuICBLRVk6ICAgICAgTUVUQSxcbiAgTkVFRDogICAgIGZhbHNlLFxuICBmYXN0S2V5OiAgZmFzdEtleSxcbiAgZ2V0V2VhazogIGdldFdlYWssXG4gIG9uRnJlZXplOiBvbkZyZWV6ZVxufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX21ldGEuanNcbi8vIG1vZHVsZSBpZCA9IDMxXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIDE5LjEuMi4xNCAvIDE1LjIuMy4xNCBPYmplY3Qua2V5cyhPKVxudmFyICRrZXlzICAgICAgID0gcmVxdWlyZSgnLi9fb2JqZWN0LWtleXMtaW50ZXJuYWwnKVxuICAsIGVudW1CdWdLZXlzID0gcmVxdWlyZSgnLi9fZW51bS1idWcta2V5cycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IE9iamVjdC5rZXlzIHx8IGZ1bmN0aW9uIGtleXMoTyl7XG4gIHJldHVybiAka2V5cyhPLCBlbnVtQnVnS2V5cyk7XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LWtleXMuanNcbi8vIG1vZHVsZSBpZCA9IDMyXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIDcuMS4xMyBUb09iamVjdChhcmd1bWVudClcbnZhciBkZWZpbmVkID0gcmVxdWlyZSgnLi9fZGVmaW5lZCcpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdCl7XG4gIHJldHVybiBPYmplY3QoZGVmaW5lZChpdCkpO1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3RvLW9iamVjdC5qc1xuLy8gbW9kdWxlIGlkID0gMzNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyoqXG4gKiBFbnVtZXJhdGlvbiBvZiBQbGF5YmFjayBUeXBlcy5cbiAqL1xuZXhwb3J0IGNvbnN0IFBsYXliYWNrVHlwZXMgPSBPYmplY3QuZnJlZXplKHtcbiAgUlRDOiAncnRjJyxcbiAgUlRNUDogJ3J0bXAnLFxuICBITFM6ICdobHMnXG59KVxuXG4vKipcbiAqIEVudW1lcmF0aW9uIG9mIEF1ZGlvIEVuY29kZXIgdHlwZXMgdG8gcmVxdWVzdCBmb3IgUGxheWJhY2tcbiAqL1xuZXhwb3J0IGNvbnN0IFBsYXliYWNrQXVkaW9FbmNvZGVyID0gT2JqZWN0LmZyZWV6ZSh7XG4gIE9QVVM6ICdPcHVzJyxcbiAgUENNVTogJ1BDTVUnLFxuICBQQ01BOiAnUENNQScsXG4gIFNQRUVYOiAnU3BlZXgnLFxuICBOT05FOiAnTk9ORSdcbn0pXG5cbi8qKlxuICogRW51bWVyYXRpb24gb2YgVmlkZW8gRW5jb2RlciB0eXBlcyB0byByZXF1ZXN0IGZvciBQbGF5YmFjay5cbiAqL1xuZXhwb3J0IGNvbnN0IFBsYXliYWNrVmlkZW9FbmNvZGVyID0gT2JqZWN0LmZyZWV6ZSh7XG4gIFZQODogJ1ZQOCcsXG4gIEgyNjQ6ICdIMjY0JyxcbiAgTk9ORTogJ05PTkUnXG59KVxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2pzL2VudW0vcGxheWJhY2suanMiLCIvKipcbiAqIEVudW1lcmF0aW9uIG9mIFBsYXliYWNrIFN0YXRlLlxuICpcbiAqIEBzZWUge1N1YnNjcmliZXJQbGF5YmFja0NvbnRyb2xzfVxuICovXG5leHBvcnQgY29uc3QgUGxheWJhY2tTdGF0ZSA9IE9iamVjdC5mcmVlemUoe1xuICBVTkFWQUlMQUJMRTogMTAwMCxcbiAgQVZBSUxBQkxFOiAwLFxuICBJRExFOiAxLFxuICBQTEFZSU5HOiAyLFxuICBQQVVTRUQ6IDNcbn0pXG5cbi8qKlxuICogSHVtYW4gcmVhZGFibGUgcGxheWJhY2sgc3RhdGUuXG4gKlxuICogQHNlZSB7U3Vic2NyaWJlclBsYXliYWNrQ29udHJvbHN9XG4gKiBAcHJpdmF0ZVxuICovXG5leHBvcnQgY29uc3QgUGxheWJhY2tTdGF0ZVJlYWRhYmxlID0gT2JqZWN0LmZyZWV6ZSh7XG4gIDEwMDA6ICdQbGF5YmFjay5VTkFWQUlMQUJMRScsXG4gIDA6ICdQbGF5YmFjay5BVkFJTEFCTEUnLFxuICAxOiAnUGxheWJhY2suSURMRScsXG4gIDI6ICdQbGF5YmFjay5QTEFZSU5HJyxcbiAgMzogJ1BsYXliYWNrLlBBVVNFRCdcbn0pXG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvanMvc3Vic2NyaWJlci9jb250cm9scy9zdGF0ZS5qcyIsInZhciB0b1N0cmluZyA9IHt9LnRvU3RyaW5nO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGl0KXtcbiAgcmV0dXJuIHRvU3RyaW5nLmNhbGwoaXQpLnNsaWNlKDgsIC0xKTtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19jb2YuanNcbi8vIG1vZHVsZSBpZCA9IDM2XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsInZhciBjdHggICAgICAgICA9IHJlcXVpcmUoJy4vX2N0eCcpXG4gICwgY2FsbCAgICAgICAgPSByZXF1aXJlKCcuL19pdGVyLWNhbGwnKVxuICAsIGlzQXJyYXlJdGVyID0gcmVxdWlyZSgnLi9faXMtYXJyYXktaXRlcicpXG4gICwgYW5PYmplY3QgICAgPSByZXF1aXJlKCcuL19hbi1vYmplY3QnKVxuICAsIHRvTGVuZ3RoICAgID0gcmVxdWlyZSgnLi9fdG8tbGVuZ3RoJylcbiAgLCBnZXRJdGVyRm4gICA9IHJlcXVpcmUoJy4vY29yZS5nZXQtaXRlcmF0b3ItbWV0aG9kJylcbiAgLCBCUkVBSyAgICAgICA9IHt9XG4gICwgUkVUVVJOICAgICAgPSB7fTtcbnZhciBleHBvcnRzID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdGVyYWJsZSwgZW50cmllcywgZm4sIHRoYXQsIElURVJBVE9SKXtcbiAgdmFyIGl0ZXJGbiA9IElURVJBVE9SID8gZnVuY3Rpb24oKXsgcmV0dXJuIGl0ZXJhYmxlOyB9IDogZ2V0SXRlckZuKGl0ZXJhYmxlKVxuICAgICwgZiAgICAgID0gY3R4KGZuLCB0aGF0LCBlbnRyaWVzID8gMiA6IDEpXG4gICAgLCBpbmRleCAgPSAwXG4gICAgLCBsZW5ndGgsIHN0ZXAsIGl0ZXJhdG9yLCByZXN1bHQ7XG4gIGlmKHR5cGVvZiBpdGVyRm4gIT0gJ2Z1bmN0aW9uJyl0aHJvdyBUeXBlRXJyb3IoaXRlcmFibGUgKyAnIGlzIG5vdCBpdGVyYWJsZSEnKTtcbiAgLy8gZmFzdCBjYXNlIGZvciBhcnJheXMgd2l0aCBkZWZhdWx0IGl0ZXJhdG9yXG4gIGlmKGlzQXJyYXlJdGVyKGl0ZXJGbikpZm9yKGxlbmd0aCA9IHRvTGVuZ3RoKGl0ZXJhYmxlLmxlbmd0aCk7IGxlbmd0aCA+IGluZGV4OyBpbmRleCsrKXtcbiAgICByZXN1bHQgPSBlbnRyaWVzID8gZihhbk9iamVjdChzdGVwID0gaXRlcmFibGVbaW5kZXhdKVswXSwgc3RlcFsxXSkgOiBmKGl0ZXJhYmxlW2luZGV4XSk7XG4gICAgaWYocmVzdWx0ID09PSBCUkVBSyB8fCByZXN1bHQgPT09IFJFVFVSTilyZXR1cm4gcmVzdWx0O1xuICB9IGVsc2UgZm9yKGl0ZXJhdG9yID0gaXRlckZuLmNhbGwoaXRlcmFibGUpOyAhKHN0ZXAgPSBpdGVyYXRvci5uZXh0KCkpLmRvbmU7ICl7XG4gICAgcmVzdWx0ID0gY2FsbChpdGVyYXRvciwgZiwgc3RlcC52YWx1ZSwgZW50cmllcyk7XG4gICAgaWYocmVzdWx0ID09PSBCUkVBSyB8fCByZXN1bHQgPT09IFJFVFVSTilyZXR1cm4gcmVzdWx0O1xuICB9XG59O1xuZXhwb3J0cy5CUkVBSyAgPSBCUkVBSztcbmV4cG9ydHMuUkVUVVJOID0gUkVUVVJOO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fZm9yLW9mLmpzXG4vLyBtb2R1bGUgaWQgPSAzN1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGJpdG1hcCwgdmFsdWUpe1xuICByZXR1cm4ge1xuICAgIGVudW1lcmFibGUgIDogIShiaXRtYXAgJiAxKSxcbiAgICBjb25maWd1cmFibGU6ICEoYml0bWFwICYgMiksXG4gICAgd3JpdGFibGUgICAgOiAhKGJpdG1hcCAmIDQpLFxuICAgIHZhbHVlICAgICAgIDogdmFsdWVcbiAgfTtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19wcm9wZXJ0eS1kZXNjLmpzXG4vLyBtb2R1bGUgaWQgPSAzOFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJ2YXIgZGVmID0gcmVxdWlyZSgnLi9fb2JqZWN0LWRwJykuZlxuICAsIGhhcyA9IHJlcXVpcmUoJy4vX2hhcycpXG4gICwgVEFHID0gcmVxdWlyZSgnLi9fd2tzJykoJ3RvU3RyaW5nVGFnJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaXQsIHRhZywgc3RhdCl7XG4gIGlmKGl0ICYmICFoYXMoaXQgPSBzdGF0ID8gaXQgOiBpdC5wcm90b3R5cGUsIFRBRykpZGVmKGl0LCBUQUcsIHtjb25maWd1cmFibGU6IHRydWUsIHZhbHVlOiB0YWd9KTtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19zZXQtdG8tc3RyaW5nLXRhZy5qc1xuLy8gbW9kdWxlIGlkID0gMzlcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiJ3VzZSBzdHJpY3QnXG5cbmltcG9ydCBlbnZpcm9ubWVudCBmcm9tICcuLi9lbnYvYnJvd3NlcidcbmltcG9ydCB7IERlZmVycmVkUHJvbWlzZSB9IGZyb20gJy4uL3V0aWwvcHJvbWlzZSdcbmltcG9ydCB7IGN1cnJ5LCBmaWx0ZXIgfSBmcm9tICcuLi91dGlsJ1xuaW1wb3J0IHsgZGVlcENvcHkgfSBmcm9tICcuLi91dGlsL29iamVjdCdcbmltcG9ydCB7IGRlYnVnIH0gZnJvbSAnLi4vbG9nJ1xuLy8gaW1wb3J0IHsgTm9TdXBwb3J0ZWRDYW1lcmFSZXNvbHV0aW9uc0Vycm9yIH0gZnJvbSAnLi4vZXhjZXB0aW9uL2Vycm9ycydcblxuLy8gUmVzb2x1dGlvbnMgYm9ycm93ZWQgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vd2VicnRjSGFja3MvV2ViUlRDLUNhbWVyYS1SZXNvbHV0aW9uL2Jsb2IvbWFzdGVyL2pzL3Jlc29sdXRpb25TY2FuLmpzXG5jb25zdCBmb3JtYXRzID0gW1xuICB7XG4gICAgXCJsYWJlbFwiOiBcIjRLKFVIRClcIixcbiAgICBcIndpZHRoXCIgOiAzODQwLFxuICAgIFwiaGVpZ2h0XCI6IDIxNjBcbiAgfSxcbiAge1xuICAgIFwibGFiZWxcIjogXCIxMDgwcChGSEQpXCIsXG4gICAgXCJ3aWR0aFwiOiAxOTIwLFxuICAgIFwiaGVpZ2h0XCI6IDEwODBcbiAgfSxcbiAge1xuICAgIFwibGFiZWxcIjogXCJVWEdBXCIsXG4gICAgXCJ3aWR0aFwiOiAxNjAwLFxuICAgIFwiaGVpZ2h0XCI6IDEyMDBcbiAgfSxcbiAge1xuICAgIFwibGFiZWxcIjogXCI3MjBwKEhEKVwiLFxuICAgIFwid2lkdGhcIjogMTI4MCxcbiAgICBcImhlaWdodFwiOiA3MjBcbiAgfSxcbiAge1xuICAgIFwibGFiZWxcIjogXCJTVkdBXCIsXG4gICAgXCJ3aWR0aFwiOiA4MDAsXG4gICAgXCJoZWlnaHRcIjogNjAwXG4gIH0sXG4gIHtcbiAgICBcImxhYmVsXCI6IFwiVkdBXCIsXG4gICAgXCJ3aWR0aFwiOiA2NDAsXG4gICAgXCJoZWlnaHRcIjogNDgwXG4gIH0sXG4gIHtcbiAgICBcImxhYmVsXCI6IFwiMzYwcChuSEQpXCIsXG4gICAgXCJ3aWR0aFwiOiA2NDAsXG4gICAgXCJoZWlnaHRcIjogMzYwXG4gIH0sXG4gIHtcbiAgICBcImxhYmVsXCI6IFwiQ0lGXCIsXG4gICAgXCJ3aWR0aFwiOiAzNTIsXG4gICAgXCJoZWlnaHRcIjogMjg4XG4gIH0sXG4gIHtcbiAgICBcImxhYmVsXCI6IFwiUVZHQVwiLFxuICAgIFwid2lkdGhcIjogMzIwLFxuICAgIFwiaGVpZ2h0XCI6IDI0MFxuICB9LFxuICB7XG4gICAgXCJsYWJlbFwiOiBcIlFDSUZcIixcbiAgICBcIndpZHRoXCI6IDE3NixcbiAgICBcImhlaWdodFwiOiAxNDRcbiAgfSxcbiAge1xuICAgIFwibGFiZWxcIjogXCJRUVZHQVwiLFxuICAgIFwid2lkdGhcIjogMTYwLFxuICAgIFwiaGVpZ2h0XCI6IDEyMFxuICB9XG5cbl07XG5cbi8qKlxuICogRGV0ZWN0cyBpZiByZXNvbHV0aW9ucyBhcmUgZGVmaW5lZCBvbiB0aGUgcHJvdmllZCBjb25zdHJhaW50cy5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gY29uc3RyYWludHNcbiAqICAgICAgICBUaGUgTWVkaWEgQ29uc3RyYWludHMgdG8gdGVzdCBhZ2FpbnN0LlxuICogQHJldHVybiB7Qm9vbGVhbn1cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5jb25zdCBoYXNSZXNvbHV0aW9uc0RlZmluZWQgPSAoY29uc3RyYWludHMpID0+IHtcbiAgcmV0dXJuIGNvbnN0cmFpbnRzLmhhc093blByb3BlcnR5KCd2aWRlbycpICYmXG4gICAgICAgICAgKGNvbnN0cmFpbnRzLnZpZGVvLmhhc093blByb3BlcnR5KCd3aWR0aCcpIHx8IGNvbnN0cmFpbnRzLnZpZGVvLmhhc093blByb3BlcnR5KCdoZWlnaHQnKSlcbn1cblxuLyoqXG4gKiBSZXR1cm4gdmFsdWUgb24gYXR0cmlidXRlIGJhc2VkIG9uIGZhaWxvdmVyIHRlc3Qgb2YgYXR0cmlidXRlIGF2YWlsYWJpbGl0eSBvbiBwcm92aWRlZCBvYmplY3QuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGF0dHJpYnV0ZVxuICogQHJldHVybiB7T2JqZWN0fVxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmNvbnN0IGdldFZhbHVlRnJvbUNvbnN0cmFpbnRBdHRyaWJ1dGUgPSAoYXR0cmlidXRlKSA9PiB7XG4gIHJldHVybiBhdHRyaWJ1dGUuZXhhY3QgfHwgYXR0cmlidXRlLmlkZWFsIHx8IGF0dHJpYnV0ZS5tYXggfHwgYXR0cmlidXRlLm1pbiB8fCBhdHRyaWJ1dGVcbn1cblxuLyoqXG4gKiBUZXN0IGlmIHZpZGVvIG9uIE1lZGlhIENvbnN0cmFpbnQgaXMgZWl0aGVyIHNldCB0byBgdHJ1ZWAgb3IgaWYgdGhlIGNvbnN0cmFpbnRzIGFuZCBmb3JtYXQgb2JqZWN0cyBoYXZlIHRoZSBzYW1lIGRpbWVuc2lvbiB2YWx1ZXMuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGNvbnN0cmFpbnRzXG4gKiBAcGFyYW0ge09iamVjdH0gZm9ybWF0XG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmNvbnN0IGlzRXhhY3QgPSBjdXJyeSgoY29uc3RyYWludHMsIGZvcm1hdCkgPT4ge1xuICBpZiAodHlwZW9mIGNvbnN0cmFpbnRzLnZpZGVvID09PSAnYm9vbGVhbicpIHtcbiAgICByZXR1cm4gdHJ1ZVxuICB9XG4gIGNvbnN0IHcgPSBjb25zdHJhaW50cy52aWRlby5oYXNPd25Qcm9wZXJ0eSgnd2lkdGgnKSA/IGdldFZhbHVlRnJvbUNvbnN0cmFpbnRBdHRyaWJ1dGUoY29uc3RyYWludHMudmlkZW8ud2lkdGgpIDogMFxuICBjb25zdCBoID0gY29uc3RyYWludHMudmlkZW8uaGFzT3duUHJvcGVydHkoJ2hlaWdodCcpID8gZ2V0VmFsdWVGcm9tQ29uc3RyYWludEF0dHJpYnV0ZShjb25zdHJhaW50cy52aWRlby5oZWlnaHQpIDogMFxuICBjb25zdCBjb25maXJtZWQgPSAodyA9PT0gZm9ybWF0LndpZHRoKSAmJiAoaCA9PT0gZm9ybWF0LmhlaWdodClcbiAgaWYgKGNvbmZpcm1lZCkge1xuICAgIGRlYnVnKCdbZ3VtOmlzRXhhY3RdJywgYEZvdW5kIG1hdGNoaW5nIHJlc29sdXRpb24gZm9yICR7Zm9ybWF0LndpZHRofSwgJHtmb3JtYXQuaGVpZ2h0fS5gKVxuICB9XG4gIHJldHVybiBjb25maXJtZWRcbn0pXG5cbi8qKlxuICogVGVzdCBpZiB0aGUgYXJlYSBvbiB0aGUgcHJvdmlkZSBmb3JtYXQgaXMgbG93ZXIgdGhhbiB0aGUgYXJlYSBvbiB0aGUgTWVkaWEgQ29uc3RyYWludHMuXG4gKiBUaGlzIGlzIHVzZWQgaW4gdHJ5aW5nIHRvIGZpbmQgdGhlIG5leHQgbmVhcmVzdCBuZWlnaGJvciBvZiBkaW1lbnNpb25zIHRoYXQgdGhlIGJyb3dzZXIgc3VwcG9ydHMuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGNvbnN0cmFpbnRzXG4gKiBAcGFyYW0ge09iamVjdH0gZm9ybWF0XG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmNvbnN0IGlzTG93ZXIgPSBjdXJyeSgoY29uc3RyYWludHMsIGZvcm1hdCkgPT4ge1xuICBjb25zdCB3ID0gY29uc3RyYWludHMudmlkZW8uaGFzT3duUHJvcGVydHkoJ3dpZHRoJykgPyBnZXRWYWx1ZUZyb21Db25zdHJhaW50QXR0cmlidXRlKGNvbnN0cmFpbnRzLnZpZGVvLndpZHRoKSA6IDBcbiAgY29uc3QgaCA9IGNvbnN0cmFpbnRzLnZpZGVvLmhhc093blByb3BlcnR5KCdoZWlnaHQnKSA/IGdldFZhbHVlRnJvbUNvbnN0cmFpbnRBdHRyaWJ1dGUoY29uc3RyYWludHMudmlkZW8uaGVpZ2h0KSA6IDBcbiAgY29uc3QgZGVzaXJlZCA9IHcgKiBoXG4gIGNvbnN0IGRpbWVuc2lvbnMgPSBmb3JtYXQud2lkdGggKiBmb3JtYXQuaGVpZ2h0XG4gIHJldHVybiBkaW1lbnNpb25zIDwgZGVzaXJlZFxufSlcblxuLyoqXG4gKiBSZXR1cm5zIGZpbHRlcmVkIG9mIE1lZGlhIENvbnN0cmFpbnQgZm9ybWF0IGlmIG1hdGNoaW5nIHRoZSBjYW5uZWQgbGlzdCBvZiBzdXBwb3J0IGZvcm0gYGZvcm1hdHNgLlxuICpcbiAqIEBwYXJhbSB7QXJyYXl9IGZvcm1hdExpc3RcbiAqIEBwYXJhbSB7T2JqZWN0fSBjb25zdHJhaW50c1xuICogQHJldHVybiB7QXJyYXl9XG4gKlxuICogQHByaXZhdGVcbiAqL1xuY29uc3QgaGFzTWF0Y2hpbmdGb3JtYXQgPSBjdXJyeSgoZm9ybWF0c0xpc3QsIGNvbnN0cmFpbnRzKSA9PiB7XG4gIGRlYnVnKCdbZ3VtOmhhc01hdGNoaW5nRm9ybWF0XScsICdGaWx0ZXJlZCBsaXN0OiAnICsgSlNPTi5zdHJpbmdpZnkoZmlsdGVyKGlzRXhhY3QoY29uc3RyYWludHMpKShmb3JtYXRzTGlzdCksIG51bGwsIDIpKVxuICByZXR1cm4gZmlsdGVyKGlzRXhhY3QoY29uc3RyYWludHMpKShmb3JtYXRzTGlzdCkubGVuZ3RoID4gMFxufSlcblxuLyoqXG4gKiBSZXR1cm5zIGxpc3Qgb2YgZmlsdGVyIGxvd2VyIHJlc29sdXRpb24gY29uc3RyYWludHMgZnJvbSB0aGUgcHJvdmlkZWQgTWVkaWEgY29uc3RyYWludHMuXG4gKlxuICogQHBhcmFtIHtBcnJheX0gZm9ybWF5TGlzdFxuICogQHBhcmFtIHtPYmplY3R9IGNvbnN0cmFpbnRzXG4gKiBAcmV0dXJuIHtBcnJheX1cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5jb25zdCBmaW5kTG93ZXJSZXNvbHV0aW9ucyA9IGN1cnJ5KChmb3JtYXRzTGlzdCwgY29uc3RyYWludHMpID0+IHtcbiAgbGV0IHJlc0lzTG93ZXIgPSBpc0xvd2VyKGNvbnN0cmFpbnRzKVxuICByZXR1cm4gZmlsdGVyKHJlc0lzTG93ZXIpKGZvcm1hdHNMaXN0KVxufSlcblxuLyoqXG4gKiBBbGxvd3MgdGhlIGJyb3dzZXIgdG8gdHJ5IGFuZCBkZXRlcm1pbmUgdGhlIHJlc29sdXRpb24gdG8gdXNlIGJhc2VkIG9uIGB2aWRlbzogdHJ1ZWAgYXR0cmlidXRlIGluIGBnZXRVc2VyTWVkaWFgIGNhbGwuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGRhdGFcbiAqICAgICAgICBUaGUgTWVkaWEgQ29uc3RhaW50cyBvYmplY3QuXG4gKiBAcGFyYW0ge1Byb21pc2V9IHBcbiAqICAgICAgICBUaGUgYFByb21pc2VgIHRvIHJlc29sdmUgb3IgcmVqZWN0IG9uIGRldGVtaW5hdGlvbiBvZiBhbGxvd2VkIE1lZGlhIENvbnN0cmFpbnRzIG9uIHRoZSBicm93c2VyLlxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmNvbnN0IGFsbG93QnJvd3NlclRvRGVmaW5lUmVzb2x1dGlvbiA9IChkYXRhLCBwKSA9PiB7XG4gIC8vIGRlZmF1bHQgdG8gYHZpZGVvOiB0cnVlYCBpbiBob3BlcyB0aGUgYnJvd3NlciBjYW4gZGVjaWRlIG9uIGl0cyBvd24uXG4gIGRhdGEudmlkZW8gPSB0cnVlXG4gIGVudmlyb25tZW50LmdVTShkYXRhKVxuICAgIC50aGVuKG1lZGlhID0+IHtcbiAgICAgIHAucmVzb2x2ZSh7XG4gICAgICAgIG1lZGlhOiBtZWRpYSxcbiAgICAgICAgY29uc3RyYWludHM6IGRhdGFcbiAgICAgIH0pXG4gICAgfSlcbiAgICAuY2F0Y2goZXJyID0+IHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuICAgICAgY29uc3QgbXNnID0gdHlwZW9mIGVyciA9PT0gJ3N0cmluZycgPyBlcnIgOiBbZXJyLm5hbWUsIGVyci5tZXNzYWdlXS5qb2luKCc6ICcpXG4gICAgICBkZWJ1ZygnW2d1bTpnZXRVc2VyTWVkaWFdJywgYEZhaWx1cmUgaW4gZ2V0VXNlck1lZGlhOiAke21zZ30uIEF0dGVtcHRpbmcgb3RoZXIgcmVzb2x1dGlvbiB0ZXN0cy4uLmApXG4gICAgICBkZWJ1ZygnW2dVTTpmaW5kZm9ybWF0XScsIGBDb25zdHJhaW50cyBkZWNsaW5lZCBieSBicm93c2VyOiAke0pTT04uc3RyaW5naWZ5KGRhdGEsIG51bGwsIDIpfWApXG4gICAgICBwLnJlamVjdCgnQ291bGQgbm90IGZpbmQgcHJvcGVyIGNhbWVyYSBmb3IgcHJvdmlkZWQgY29uc3RyYWludHMuJylcbiAgICB9KVxufVxuXG4vKipcbiAqIEF0dGVtcHRzIHRvIHNlbGVjdCB0aGUgYmVzdCByZXNvbHV0aW9uIGJhc2VkIG9uIHdoZXRoZXIgdGhlIGJyb3dzZXIgdGhyb3dzIGFuIGV4Y2VwdGlvbiB3aGVuIHJlcXVlc3RpbmcgYE1lZGlhU3RyZWFtYCBvbiBgZ2V0VXNlck1lZGlhYC5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gZGF0YVxuICogICAgICAgIFRoZSBNZWRpYSBDb25zdGFpbnRzIG9iamVjdC5cbiAqIEBwYXJhbSB7QXJyYXl9IHNlbGVjdGlvbnNcbiAqICAgICAgICBUaGUgbGlzdGluZyBvZiBmb3JtYXRzIHRvIHRlc3Qgb24uXG4gKiBAcGFyYW0ge1Byb21pc2V9IHBcbiAqICAgICAgICBUaGUgYFByb21pc2VgIHRvIHJlc29sdmUgb3IgcmVqZWN0IG9uIGRldGVtaW5hdGlvbiBvZiBhbGxvd2VkIE1lZGlhIENvbnN0cmFpbnRzIG9uIHRoZSBicm93c2VyLlxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmNvbnN0IGZpbmROZXh0U2VsZWN0aW9uID0gKGRhdGEsIHNlbGVjdGlvbnMsIHApID0+IHtcbiAgaWYgKHNlbGVjdGlvbnMubGVuZ3RoID09IDApIHtcbiAgICAvLyBpZiB3ZSBnb3QgaGVyZSwgdGhlcmUgaXMgbm8gc3VwcG9ydC5cbiAgICBhbGxvd0Jyb3dzZXJUb0RlZmluZVJlc29sdXRpb24oZGF0YSwgcClcbiAgICByZXR1cm5cbiAgfVxuICBjb25zdCBzZWxlY3Rpb24gPSBzZWxlY3Rpb25zLnNoaWZ0KClcbiAgZGF0YS52aWRlby53aWR0aCA9IHtleGFjdDogc2VsZWN0aW9uLndpZHRofVxuICBkYXRhLnZpZGVvLmhlaWdodCA9IHtleGFjdDogc2VsZWN0aW9uLmhlaWdodH1cbiAgZW52aXJvbm1lbnQuZ1VNKGRhdGEpXG4gICAgLnRoZW4obWVkaWEgPT4ge1xuICAgICAgcC5yZXNvbHZlKHtcbiAgICAgICAgbWVkaWE6IG1lZGlhLFxuICAgICAgICBjb25zdHJhaW50czogZGF0YVxuICAgICAgfSlcbiAgICB9KVxuICAgIC5jYXRjaChlcnIgPT4geyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gICAgICBjb25zdCBtc2cgPSB0eXBlb2YgZXJyID09PSAnc3RyaW5nJyA/IGVyciA6IFtlcnIubmFtZSwgZXJyLm1lc3NhZ2VdLmpvaW4oJzogJylcbiAgICAgIGRlYnVnKCdbZ3VtOmdldFVzZXJNZWRpYV0nLCBgRmFpbHVyZSBpbiBnZXRVc2VyTWVkaWE6ICR7bXNnfS4gQXR0ZW1wdGluZyBvdGhlciByZXNvbHV0aW9uIHRlc3RzLi4uYClcbiAgICAgIGRlYnVnKCdbZ1VNOmZpbmRmb3JtYXRdJywgYENvbnN0cmFpbnRzIGRlY2xpbmVkIGJ5IGJyb3dzZXI6ICR7SlNPTi5zdHJpbmdpZnkoZGF0YSwgbnVsbCwgMil9YClcbiAgICAgIGZpbmROZXh0U2VsZWN0aW9uKGRhdGEsIHNlbGVjdGlvbnMsIHApXG4gICAgfSlcbn1cblxuLyoqXG4gKiBRdWljayB0ZXN0IGlmIHJlc29sdXRpb24gaXMgc3VwcG9ydGVkIG9uIHRoZSBicm93c2VyLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBjb25zdHJhaW50c1xuICpcbiAqIEBwcml2YXRlXG4gKi9cbmV4cG9ydCBjb25zdCBxdWlja1Jlc29sdXRpb25TdXBwb3J0ID0gKGNvbnN0cmFpbnRzKSA9PiB7XG4gIGxldCBkYXRhID0gZGVlcENvcHkoY29uc3RyYWludHMpXG4gIC8vIGlmIHZpZGVvOiBgdHJ1ZWAsIHJldHVybmVkIHVuc2NhdGhlZC5cbiAgaWYgKHR5cGVvZiBjb25zdHJhaW50cy52aWRlbyA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgcmV0dXJuIGRhdGFcbiAgfVxuICAvLyBlbHNlLCBkZWZpbmUgZXhhY3QuXG4gIGlmIChjb25zdHJhaW50cy52aWRlby53aWR0aCkge1xuICAgIGRhdGEudmlkZW8ud2lkdGggPSB7ZXhhY3Q6IGdldFZhbHVlRnJvbUNvbnN0cmFpbnRBdHRyaWJ1dGUoY29uc3RyYWludHMudmlkZW8ud2lkdGgpfVxuICB9XG4gIGlmIChjb25zdHJhaW50cy52aWRlby5oZWlnaHQpIHtcbiAgICBkYXRhLnZpZGVvLmhlaWdodCA9IHtleGFjdDogZ2V0VmFsdWVGcm9tQ29uc3RyYWludEF0dHJpYnV0ZShjb25zdHJhaW50cy52aWRlby5oZWlnaHQpfVxuICB9XG4gIHJldHVybiBkYXRhXG59XG5cbi8qKlxuICogRGV0ZW1pbmUgdGhlIHN1cHBvcnRlZCByZXNvbHV0aW9uIG9uIHRoZSBicm93c2VyIGJhc2VkIG9uIHRoZSBNZWRpYSBDb25zdHJhaW50cyByZXF1ZXN0ZWQuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGNvbnN0cmFpbnRzXG4gKlxuICogQHByaXZhdGVcbiAqL1xuZXhwb3J0IGNvbnN0IGRldGVybWluZVN1cHBvcnRlZFJlc29sdXRpb24gPSAoY29uc3RyYWludHMpID0+IHtcbiAgZGVidWcoJ1tndW06ZGV0ZXJtaW5lU3VwcG9ydGVkUmVzb2x1dGlvbl0nLCAnRGV0ZXJtaW5lIG5leHQgbmVpZ2hib3IgYmFzZWQgb24gY29uc3RyYWludHM6ICcgKyBKU09OLnN0cmluZ2lmeShjb25zdHJhaW50cywgbnVsbCwgMikpXG4gIGxldCBkZWZlcnJlZCA9IG5ldyBEZWZlcnJlZFByb21pc2UoKVxuICBsZXQgc2VsZWN0aW9ucyA9IGZpbmRMb3dlclJlc29sdXRpb25zKGZvcm1hdHMpKGNvbnN0cmFpbnRzKVxuICBsZXQgZGF0YSA9IGRlZXBDb3B5KGNvbnN0cmFpbnRzKVxuICBmaW5kTmV4dFNlbGVjdGlvbihkYXRhLCBzZWxlY3Rpb25zLCBkZWZlcnJlZClcbiAgcmV0dXJuIGRlZmVycmVkLnByb21pc2Vcbn1cblxuLyoqXG4gKiBRdWljayB0ZXN0IHRvIHNlZSBpZiBXZWJSVEMgaXMgc3VwcG9ydGVkIGluIHRoZSBjdXJyZW50IGVudmlyb25tZW50LlxuICpcbiAqIEByZXR1cm4ge0Jvb2xlYW59XG4gKlxuICogQHByaXZhdGVcbiAqL1xuZXhwb3J0IGNvbnN0IGlzU3VwcG9ydGVkID0gKCkgPT4ge1xuICByZXR1cm4gX1JUQ1BlZXJDb25uZWN0aW9uICYmIF9SVENJY2VDYW5kaWRhdGUgJiYgX1JUQ1Nlc3Npb25EZXNjcmlwdGlvblxufVxuXG4vKipcbiAqIFByb3h5IG9uIGBnZXRVc2VyTWVkaWFgIHRvIHRyeSBhbmQgcmVzb2x2ZSB0byB0aGUgYmVzdCBwb3NzaWJsZSByZXNvbHV0aW9uIGZvciBicm9hZGNhc3QgYmFzZWQgb24gTWVkaWEgQ29uc3RyYWludHMgb2JqZWN0IHByb3ZpZGVkLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBjb25zdHJhaW50c1xuICogQHJldHVybiB7UHJvbWlzZX1cbiAqICAgICAgICBUaGUgYFByb21pc2VgIHdpbGwgcmVzb2x2ZSBvciByZWplY3Qgb24gcHJvcGVybHkgYWNjZXNzaW5nIGEgYE1lZGlhU3RyZWFtYCBmcm9tIGBnZXRVc2VyTWVkaWFgIG9uIHRoZSBicm93c2VyLlxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmV4cG9ydCBjb25zdCBnZXRVc2VyTWVkaWEgPSAoY29uc3RyYWludHMpID0+IHtcbiAgLy8gV3JhcHBpbmcgYGdldFVzZXJNZWRpYWAgcmVxdWVzdHMgaW4gYW5vdGhlciBkZWZlcnJlZCBwcm9taXNlIHNvIHdlIGNhbiByZXR1cm4gdGhlIHNlbGVjdGVkIHJlc29sdXRpb25zIGlmIHN1Y2Nlc3NmdWwuXG4gIGxldCBkZmQgPSBuZXcgRGVmZXJyZWRQcm9taXNlKClcbiAgbGV0IGlzQXZhaWxhYmxlSW5Gb3JtYXRzID0gaGFzTWF0Y2hpbmdGb3JtYXQoZm9ybWF0cylcbiAgZGVidWcoJ1tndW06Z2V0VXNlck1lZGlhXScsICdJcyBBdmFpbGFibGUgaW4gZm9ybWF0IGxpc3Rpbmc6ICcgKyBpc0F2YWlsYWJsZUluRm9ybWF0cyhjb25zdHJhaW50cykpXG4gIGNvbnN0IGZhaWxvdmVyID0gKGVycikgPT4ge1xuICAgIGlmIChlcnIpIHtcbiAgICAgIGNvbnN0IG1zZyA9IHR5cGVvZiBlcnIgPT09ICdzdHJpbmcnID8gZXJyIDogW2Vyci5uYW1lLCBlcnIubWVzc2FnZV0uam9pbignOiAnKVxuICAgICAgZGVidWcoJ1tndW06Z2V0VXNlck1lZGlhXScsIGBGYWlsdXJlIGluIGdldFVzZXJNZWRpYTogJHttc2d9LiBBdHRlbXB0aW5nIG90aGVyIHJlc29sdXRpb24gdGVzdHMuLi5gKVxuICAgIH1cbiAgICBkZXRlcm1pbmVTdXBwb3J0ZWRSZXNvbHV0aW9uKGNvbnN0cmFpbnRzKVxuICAgICAgLnRoZW4ocmVzID0+IHtcbiAgICAgICAgZGZkLnJlc29sdmUoe1xuICAgICAgICAgIG1lZGlhOiByZXMubWVkaWEsXG4gICAgICAgICAgY29uc3RyYWludHM6IHJlcy5jb25zdHJhaW50c1xuICAgICAgICB9KVxuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGRmZC5yZWplY3Qoe1xuICAgICAgICAgIGVycm9yOiBlcnJvcixcbiAgICAgICAgICBjb25zdHJhaW50czogY29uc3RyYWludHNcbiAgICAgICAgfSlcbiAgICAgIH0pXG4gIH1cbiAgaWYgKCFoYXNSZXNvbHV0aW9uc0RlZmluZWQoY29uc3RyYWludHMpKSB7XG4gICAgZGVidWcoJ1tndW06Z2V0VXNlck1lZGlhXScsICdDb25zdHJhaW50cyB3ZXJlIG5vdCBkZWZpbmVkIHByb3Blcmx5LiBBdHRlbXB0aW5nIGZhaWxvdmVyLi4uJylcbiAgICBlbnZpcm9ubWVudC5nVU0oY29uc3RyYWludHMpXG4gICAgICAudGhlbihtZWRpYSA9PiB7XG4gICAgICAgIGRmZC5yZXNvbHZlKHtcbiAgICAgICAgICBtZWRpYTogbWVkaWEsXG4gICAgICAgICAgY29uc3RyYWludHM6IGNvbnN0cmFpbnRzXG4gICAgICAgIH0pXG4gICAgICB9KVxuICAgICAgLmNhdGNoKGZhaWxvdmVyKVxuICB9XG4gIGVsc2UgaWYgKGlzQXZhaWxhYmxlSW5Gb3JtYXRzKGNvbnN0cmFpbnRzKSkge1xuICAgIGRlYnVnKCdbZ3VtOmdldFVzZXJNZWRpYV0nLCAnRm91bmQgY29uc3RyYWludHMgaW4gbGlzdC4gQ2hlY2tpbmcgcXVpY2sgc3VwcG9ydCBmb3IgZmFzdGVyIHNldHVwIHdpdGg6ICcgKyBKU09OLnN0cmluZ2lmeShjb25zdHJhaW50cywgbnVsbCwgMikpXG4gICAgLy8gVHJ5IHF1aWNrIHNldHRpbmcgb2YgYGV4YWN0YCByZXNvbHV0aW9uLi4uXG4gICAgbGV0IGF2YWlsYWJsZSA9IHF1aWNrUmVzb2x1dGlvblN1cHBvcnQoY29uc3RyYWludHMpXG4gICAgZW52aXJvbm1lbnQuZ1VNKGF2YWlsYWJsZSlcbiAgICAgIC50aGVuKG1lZGlhID0+IHtcbiAgICAgICAgZGZkLnJlc29sdmUoe1xuICAgICAgICAgIG1lZGlhOiBtZWRpYSxcbiAgICAgICAgICBjb25zdHJhaW50czogYXZhaWxhYmxlXG4gICAgICAgIH0pXG4gICAgICB9KVxuICAgICAgLmNhdGNoKGZhaWxvdmVyKVxuICB9XG4gIGVsc2Uge1xuICAgIGRlYnVnKCdbZ3VtOmdldFVzZXJNZWRpYV0nLCAnQ291bGQgbm90IGZpbmQgY29udHJhaW50cyBpbiBsaXN0LiBBdHRlbXB0aW5nIGZhaWxvdmVyLi4uJylcbiAgICBmYWlsb3ZlcigpXG4gIH1cbiAgcmV0dXJuIGRmZC5wcm9taXNlXG59XG5cbi8qKlxuICogRm9yY2UgdG8gY2FsbCBgZ2V0VXNlck1lZGlhYCBkaXJlY3RseSBvbiB0aGUgYnJvd3NlciBhbmQgYnlwYXNzIHRoZSByZXNvbHV0aW9uIGRldGVjdGlvbiBtZWNoYW5pc20gcHJvdmlkZWQgYnkgb3RoZXIgbWV0aG9kcyBvbiB0aGlzIG1vZHVsZS5cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5leHBvcnQgY29uc3QgZm9yY2VVc2VyTWVkaWEgPSAoY29uc3RyYWludHMpID0+IHtcbiAgcmV0dXJuIGVudmlyb25tZW50LmdVTShjb25zdHJhaW50cylcbn1cblxuLy8gaHR0cHM6Ly9naXRodWIuY29tL211YXota2hhbi9XZWJSVEMtRXhwZXJpbWVudC9ibG9iL21hc3Rlci9SVENQZWVyQ29ubmVjdGlvbi9SVENQZWVyQ29ubmVjdGlvbi12MS42LmpzI0wxNThcbi8vIE11YXogS2hhbiAgICAgLSBnaXRodWIuY29tL211YXota2hhblxuLy8gTUlUIExpY2Vuc2UgICAtIHd3dy5XZWJSVEMtRXhwZXJpbWVudC5jb20vbGljZW5jZVxuLy8gRG9jdW1lbnRhdGlvbiAtIGdpdGh1Yi5jb20vbXVhei1raGFuL1dlYlJUQy1FeHBlcmltZW50L3RyZWUvbWFzdGVyL1JUQ1BlZXJDb25uZWN0aW9uXG5leHBvcnQgY29uc3QgdXBkYXRlQmFuZHdpZHRoID0gKG9wdGlvbnMsIHNkcCkgPT4ge1xuICBpZiAoZW52aXJvbm1lbnQuZ2V0SXNNb3ooKSkge1xuICAgIGxldCBhX2luZGV4LCBsX2luZGV4LCBmcm9udCwgYmFja1xuICAgIGlmIChvcHRpb25zLmF1ZGlvKSB7XG4gICAgICBhX2luZGV4ID0gc2RwLmluZGV4T2YoJ209YXVkaW8nKVxuICAgICAgbF9pbmRleCA9IHNkcC5pbmRleE9mKCdcXHJcXG4nLCBhX2luZGV4KVxuICAgICAgZnJvbnQgPSBzZHAuc2xpY2UoMCwgbF9pbmRleClcbiAgICAgIGJhY2sgPSBzZHAuc2xpY2UobF9pbmRleCArICdcXHJcXG4nLmxlbmd0aCwgc2RwLmxlbmd0aClcbiAgICAgIHNkcCA9IFtmcm9udCwgJ2I9QVM6JyArIG9wdGlvbnMuYXVkaW8sIGJhY2tdLmpvaW4oJ1xcclxcbicpXG4gICAgfVxuICAgIGlmIChvcHRpb25zLnZpZGVvKSB7XG4gICAgICBhX2luZGV4ID0gc2RwLmluZGV4T2YoJ209dmlkZW8nKVxuICAgICAgbF9pbmRleCA9IHNkcC5pbmRleE9mKCdcXHJcXG4nLCBhX2luZGV4KVxuICAgICAgZnJvbnQgPSBzZHAuc2xpY2UoMCwgbF9pbmRleClcbiAgICAgIGJhY2sgPSBzZHAuc2xpY2UobF9pbmRleCArICdcXHJcXG4nLmxlbmd0aCwgc2RwLmxlbmd0aClcbiAgICAgIHNkcCA9IFtmcm9udCwgJ2I9QVM6JyArIG9wdGlvbnMudmlkZW8sIGJhY2tdLmpvaW4oJ1xcclxcbicpXG4gICAgfVxuICB9XG4gIGVsc2Uge1xuICAgIHNkcCA9IHNkcC5yZXBsYWNlKC9iPUFTKFteXFxyXFxuXStcXHJcXG4pL2csICcnKVxuICAgIGlmIChvcHRpb25zLmF1ZGlvKSB7XG4gICAgICBzZHAgPSBzZHAucmVwbGFjZSgvYT1taWQ6YXVkaW9cXHJcXG4vZywgJ2E9bWlkOmF1ZGlvXFxyXFxuYj1BUzonICsgb3B0aW9ucy5hdWRpbyArICdcXHJcXG4nKVxuICAgIH1cbiAgICBpZiAob3B0aW9ucy52aWRlbykge1xuICAgICAgc2RwID0gc2RwLnJlcGxhY2UoL2E9bWlkOnZpZGVvXFxyXFxuL2csICdhPW1pZDp2aWRlb1xcclxcbmI9QVM6JyArIG9wdGlvbnMudmlkZW8gKyAnXFxyXFxuJylcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHNkcFxufVxuXG4vKiAtLSBoYW5kbGVkIGJ5IGFkYXB0ZXIuanMgLS0gKi9cbmNvbnN0IF9SVENQZWVyQ29ubmVjdGlvbiA9IHdpbmRvdy5SVENQZWVyQ29ubmVjdGlvbiB8fCAod2luZG93Lm1velJUQ1BlZXJDb25uZWN0aW9uIHx8IHdpbmRvdy53ZWJraXRSVENQZWVyQ29ubmVjdGlvbilcbmNvbnN0IF9SVENJY2VDYW5kaWRhdGUgPSB3aW5kb3cuUlRDSWNlQ2FuZGlkYXRlIHx8ICh3aW5kb3cubW96UlRDSWNlQ2FuZGlkYXRlIHx8IHdpbmRvdy53ZWJraXRSVENJY2VDYW5kaWRhdGUpXG5jb25zdCBfUlRDU2Vzc2lvbkRlc2NyaXB0aW9uID0gd2luZG93LlJUQ1Nlc3Npb25EZXNjcmlwdGlvbiB8fCAod2luZG93Lm1velJUQ1Nlc3Npb25EZXNjcmlwdGlvbiB8fCB3aW5kb3cud2Via2l0UlRDU2Vzc2lvbkRlc2NyaXB0aW9uKVxuXG5leHBvcnQgY29uc3QgUlRDUGVlckNvbm5lY3Rpb24gPSBfUlRDUGVlckNvbm5lY3Rpb25cbmV4cG9ydCBjb25zdCBSVENJY2VDYW5kaWRhdGUgPSBfUlRDSWNlQ2FuZGlkYXRlXG5leHBvcnQgY29uc3QgUlRDU2Vzc2lvbkRlc2NyaXB0aW9uID0gX1JUQ1Nlc3Npb25EZXNjcmlwdGlvblxuXG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvanMvYWRhcHRlci93ZWJydGMuanMiLCIndXNlIHN0cmljdCdcblxuaW1wb3J0IGVudmlyb25tZW50IGZyb20gJy4uL2Vudi9icm93c2VyJ1xuXG4vKipcbiAqIFRlc3QgZm9yIFdlYlNvY2tldCBzdXBwb3J0IGluIGVudmlyb25tZW50LlxuICpcbiAqIEByZXR1cm4ge0Jvb2xlYW59XG4gKlxuICogQHByaXZhdGVcbiAqL1xuZXhwb3J0IGNvbnN0IGlzU3VwcG9ydGVkID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gZW52aXJvbm1lbnQuc3VwcG9ydHNXZWJTb2NrZXQoKVxufVxuXG4vKipcbiAqIEF0dGVtcHQgYXQgY3JlYXRpbmcgbmV3IGluc3RhbmNlIG9mIGEgYFdlYlNvY2tldGAgYXQgZW5kcG9pbnQgVVJMLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSB1cmxcbiAqIEByZXR1cm4ge1dlYlNvY2tldH1cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5leHBvcnQgY29uc3QgY3JlYXRlID0gZnVuY3Rpb24gKHVybCkge1xuICByZXR1cm4gZW52aXJvbm1lbnQuY3JlYXRlV2ViU29ja2V0KHVybClcbn1cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9qcy9hZGFwdGVyL3dlYnNvY2tldC5qcyIsIid1c2Ugc3RyaWN0J1xuXG5pbXBvcnQgZW52aXJvbm1lbnQgZnJvbSAnLi4vZW52L2Jyb3dzZXInXG5pbXBvcnQgeyBkZWJ1ZywgZXJyb3IgfSBmcm9tICcuLi9sb2cnXG5cbmNvbnN0IE5BTUUgPSAnUjVQcm9QbGF5YmFja1ZpZXcnXG5jb25zdCBwbGF5YmFja0lkID0gJ3JlZDVwcm8tc3Vic2NyaWJlcidcblxuLyoqXG4gKiBCcmlkZ2UgYmV0d2VlbiBET00gRWxlbWVudCB2aWV3IGFuZCBTdWJzY3JpYmVyIGltcGxlbWVudGF0aW9uLlxuICogU3RpbGwgdXNlZCwgYnV0IGludGVybmFsaXplZCBhcyBvZiA0LjAuMC4gVXAgZm9yIGRlcHJlY2F0aW9uLCB1cCBmb3IgZGlzY3Vzc2lvbi5cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5leHBvcnQgY2xhc3MgUGxheWJhY2tWaWV3IHtcblxuICAvKipcbiAgICogQHBhcmFtIHtTdHJpbmd9IGVsZW1lbnRJZFxuICAgKiAgICAgICAgVGhlIGVsZW1lbnQgYGlkYCB0byB1c2UgZm9yIHBsYXliYWNrIGRpc3BsYXkuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBjb25zdHJ1Y3RvciAoZWxlbWVudElkID0gcGxheWJhY2tJZCkge1xuICAgIHRyeSB7XG4gICAgICAvLyBUYXJnZXQgdmlkZW8vYXVkaW8gZWxlbWVudC5cbiAgICAgIHRoaXMuX3RhcmdldEVsZW1lbnQgPSBlbnZpcm9ubWVudC5yZXNvbHZlRWxlbWVudChlbGVtZW50SWQpXG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgZXJyb3IoTkFNRSwgYENvdWxkIG5vdCBpbnN0YW50aWF0ZSBhIG5ldyBpbnN0YW5jZSBvZiBSZWQ1UHJvU3Vic2NyaWJlci4gUmVhc29uOiAke2UubWVzc2FnZX1gKVxuICAgICAgdGhyb3cgZVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBc3NvY2lhdGVzIFN1YnNjcmliZXIgaW5zdGFuY2Ugd2l0aCB0aGlzIHZpZXcgbWFuYWdlci5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IHN1YnNjcmliZXJcbiAgICogICAgICAgIFRoZSBTdWJzY3JpYmVyIGluc3RhbmNlLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgYXR0YWNoU3Vic2NyaWJlciAoc3Vic2NyaWJlcikge1xuICAgIGRlYnVnKE5BTUUsICdbYXR0YWNoc3Vic2NyaWJlcl0nKVxuICAgIHN1YnNjcmliZXIuc2V0Vmlldyh0aGlzLCBlbnZpcm9ubWVudC5nZXRFbGVtZW50SWQodGhpcy5fdGFyZ2V0RWxlbWVudCkpXG4gIH1cblxuICAvKipcbiAgICogQXNzaWduIHRoZSBgTWVkaWFTdHJlYW1gIG9iamVjdCB0byB0aGUgdmlldy5cbiAgICpcbiAgICogQHBhcmFtIHtNZWRpYVN0cmVhbX0gbWVkaWFTdHJlYW1cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIGF0dGFjaFN0cmVhbSAobWVkaWFTdHJlYW0pIHtcbiAgICBsZXQgYXV0b3BsYXkgPSB0aGlzLmlzQXV0b3BsYXlcbiAgICBkZWJ1ZyhOQU1FLCAnW2F0dGFjaHN0cmVhbV0nKVxuICAgIGVudmlyb25tZW50LnNldFZpZGVvU291cmNlKHRoaXMuX3RhcmdldEVsZW1lbnQsIG1lZGlhU3RyZWFtLCBhdXRvcGxheSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHJlY29nbml6ZWQgYGF1dG9wbGF5YCBhdHRyaWJ1dGUgb24gdGhlIERPTSBlbGVtZW50LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgZ2V0IGlzQXV0b3BsYXkgKCkge1xuICAgIHJldHVybiBlbnZpcm9ubWVudC5oYXNBdHRyaWJ1dGVEZWZpbmVkKHRoaXMuX3RhcmdldEVsZW1lbnQsICdhdXRvcGxheScpXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgRE9NIGVsZW1lbnQuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBnZXQgdmlldyAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3RhcmdldEVsZW1lbnRcbiAgfVxuXG59XG5cbmV4cG9ydCBkZWZhdWx0IFBsYXliYWNrVmlld1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2pzL3ZpZXcvcGxheWJhY2suanMiLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGl0LCBDb25zdHJ1Y3RvciwgbmFtZSwgZm9yYmlkZGVuRmllbGQpe1xuICBpZighKGl0IGluc3RhbmNlb2YgQ29uc3RydWN0b3IpIHx8IChmb3JiaWRkZW5GaWVsZCAhPT0gdW5kZWZpbmVkICYmIGZvcmJpZGRlbkZpZWxkIGluIGl0KSl7XG4gICAgdGhyb3cgVHlwZUVycm9yKG5hbWUgKyAnOiBpbmNvcnJlY3QgaW52b2NhdGlvbiEnKTtcbiAgfSByZXR1cm4gaXQ7XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fYW4taW5zdGFuY2UuanNcbi8vIG1vZHVsZSBpZCA9IDQ0XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIGdldHRpbmcgdGFnIGZyb20gMTkuMS4zLjYgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZygpXG52YXIgY29mID0gcmVxdWlyZSgnLi9fY29mJylcbiAgLCBUQUcgPSByZXF1aXJlKCcuL193a3MnKSgndG9TdHJpbmdUYWcnKVxuICAvLyBFUzMgd3JvbmcgaGVyZVxuICAsIEFSRyA9IGNvZihmdW5jdGlvbigpeyByZXR1cm4gYXJndW1lbnRzOyB9KCkpID09ICdBcmd1bWVudHMnO1xuXG4vLyBmYWxsYmFjayBmb3IgSUUxMSBTY3JpcHQgQWNjZXNzIERlbmllZCBlcnJvclxudmFyIHRyeUdldCA9IGZ1bmN0aW9uKGl0LCBrZXkpe1xuICB0cnkge1xuICAgIHJldHVybiBpdFtrZXldO1xuICB9IGNhdGNoKGUpeyAvKiBlbXB0eSAqLyB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGl0KXtcbiAgdmFyIE8sIFQsIEI7XG4gIHJldHVybiBpdCA9PT0gdW5kZWZpbmVkID8gJ1VuZGVmaW5lZCcgOiBpdCA9PT0gbnVsbCA/ICdOdWxsJ1xuICAgIC8vIEBAdG9TdHJpbmdUYWcgY2FzZVxuICAgIDogdHlwZW9mIChUID0gdHJ5R2V0KE8gPSBPYmplY3QoaXQpLCBUQUcpKSA9PSAnc3RyaW5nJyA/IFRcbiAgICAvLyBidWlsdGluVGFnIGNhc2VcbiAgICA6IEFSRyA/IGNvZihPKVxuICAgIC8vIEVTMyBhcmd1bWVudHMgZmFsbGJhY2tcbiAgICA6IChCID0gY29mKE8pKSA9PSAnT2JqZWN0JyAmJiB0eXBlb2YgTy5jYWxsZWUgPT0gJ2Z1bmN0aW9uJyA/ICdBcmd1bWVudHMnIDogQjtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19jbGFzc29mLmpzXG4vLyBtb2R1bGUgaWQgPSA0NVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyA3LjIuMSBSZXF1aXJlT2JqZWN0Q29lcmNpYmxlKGFyZ3VtZW50KVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdCl7XG4gIGlmKGl0ID09IHVuZGVmaW5lZCl0aHJvdyBUeXBlRXJyb3IoXCJDYW4ndCBjYWxsIG1ldGhvZCBvbiAgXCIgKyBpdCk7XG4gIHJldHVybiBpdDtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19kZWZpbmVkLmpzXG4vLyBtb2R1bGUgaWQgPSA0NlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IHRydWU7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19saWJyYXJ5LmpzXG4vLyBtb2R1bGUgaWQgPSA0N1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyAxOS4xLjIuMiAvIDE1LjIuMy41IE9iamVjdC5jcmVhdGUoTyBbLCBQcm9wZXJ0aWVzXSlcbnZhciBhbk9iamVjdCAgICA9IHJlcXVpcmUoJy4vX2FuLW9iamVjdCcpXG4gICwgZFBzICAgICAgICAgPSByZXF1aXJlKCcuL19vYmplY3QtZHBzJylcbiAgLCBlbnVtQnVnS2V5cyA9IHJlcXVpcmUoJy4vX2VudW0tYnVnLWtleXMnKVxuICAsIElFX1BST1RPICAgID0gcmVxdWlyZSgnLi9fc2hhcmVkLWtleScpKCdJRV9QUk9UTycpXG4gICwgRW1wdHkgICAgICAgPSBmdW5jdGlvbigpeyAvKiBlbXB0eSAqLyB9XG4gICwgUFJPVE9UWVBFICAgPSAncHJvdG90eXBlJztcblxuLy8gQ3JlYXRlIG9iamVjdCB3aXRoIGZha2UgYG51bGxgIHByb3RvdHlwZTogdXNlIGlmcmFtZSBPYmplY3Qgd2l0aCBjbGVhcmVkIHByb3RvdHlwZVxudmFyIGNyZWF0ZURpY3QgPSBmdW5jdGlvbigpe1xuICAvLyBUaHJhc2gsIHdhc3RlIGFuZCBzb2RvbXk6IElFIEdDIGJ1Z1xuICB2YXIgaWZyYW1lID0gcmVxdWlyZSgnLi9fZG9tLWNyZWF0ZScpKCdpZnJhbWUnKVxuICAgICwgaSAgICAgID0gZW51bUJ1Z0tleXMubGVuZ3RoXG4gICAgLCBsdCAgICAgPSAnPCdcbiAgICAsIGd0ICAgICA9ICc+J1xuICAgICwgaWZyYW1lRG9jdW1lbnQ7XG4gIGlmcmFtZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICByZXF1aXJlKCcuL19odG1sJykuYXBwZW5kQ2hpbGQoaWZyYW1lKTtcbiAgaWZyYW1lLnNyYyA9ICdqYXZhc2NyaXB0Oic7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tc2NyaXB0LXVybFxuICAvLyBjcmVhdGVEaWN0ID0gaWZyYW1lLmNvbnRlbnRXaW5kb3cuT2JqZWN0O1xuICAvLyBodG1sLnJlbW92ZUNoaWxkKGlmcmFtZSk7XG4gIGlmcmFtZURvY3VtZW50ID0gaWZyYW1lLmNvbnRlbnRXaW5kb3cuZG9jdW1lbnQ7XG4gIGlmcmFtZURvY3VtZW50Lm9wZW4oKTtcbiAgaWZyYW1lRG9jdW1lbnQud3JpdGUobHQgKyAnc2NyaXB0JyArIGd0ICsgJ2RvY3VtZW50LkY9T2JqZWN0JyArIGx0ICsgJy9zY3JpcHQnICsgZ3QpO1xuICBpZnJhbWVEb2N1bWVudC5jbG9zZSgpO1xuICBjcmVhdGVEaWN0ID0gaWZyYW1lRG9jdW1lbnQuRjtcbiAgd2hpbGUoaS0tKWRlbGV0ZSBjcmVhdGVEaWN0W1BST1RPVFlQRV1bZW51bUJ1Z0tleXNbaV1dO1xuICByZXR1cm4gY3JlYXRlRGljdCgpO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBPYmplY3QuY3JlYXRlIHx8IGZ1bmN0aW9uIGNyZWF0ZShPLCBQcm9wZXJ0aWVzKXtcbiAgdmFyIHJlc3VsdDtcbiAgaWYoTyAhPT0gbnVsbCl7XG4gICAgRW1wdHlbUFJPVE9UWVBFXSA9IGFuT2JqZWN0KE8pO1xuICAgIHJlc3VsdCA9IG5ldyBFbXB0eTtcbiAgICBFbXB0eVtQUk9UT1RZUEVdID0gbnVsbDtcbiAgICAvLyBhZGQgXCJfX3Byb3RvX19cIiBmb3IgT2JqZWN0LmdldFByb3RvdHlwZU9mIHBvbHlmaWxsXG4gICAgcmVzdWx0W0lFX1BST1RPXSA9IE87XG4gIH0gZWxzZSByZXN1bHQgPSBjcmVhdGVEaWN0KCk7XG4gIHJldHVybiBQcm9wZXJ0aWVzID09PSB1bmRlZmluZWQgPyByZXN1bHQgOiBkUHMocmVzdWx0LCBQcm9wZXJ0aWVzKTtcbn07XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX29iamVjdC1jcmVhdGUuanNcbi8vIG1vZHVsZSBpZCA9IDQ4XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsImV4cG9ydHMuZiA9IHt9LnByb3BlcnR5SXNFbnVtZXJhYmxlO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LXBpZS5qc1xuLy8gbW9kdWxlIGlkID0gNDlcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8gbW9zdCBPYmplY3QgbWV0aG9kcyBieSBFUzYgc2hvdWxkIGFjY2VwdCBwcmltaXRpdmVzXG52YXIgJGV4cG9ydCA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpXG4gICwgY29yZSAgICA9IHJlcXVpcmUoJy4vX2NvcmUnKVxuICAsIGZhaWxzICAgPSByZXF1aXJlKCcuL19mYWlscycpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihLRVksIGV4ZWMpe1xuICB2YXIgZm4gID0gKGNvcmUuT2JqZWN0IHx8IHt9KVtLRVldIHx8IE9iamVjdFtLRVldXG4gICAgLCBleHAgPSB7fTtcbiAgZXhwW0tFWV0gPSBleGVjKGZuKTtcbiAgJGV4cG9ydCgkZXhwb3J0LlMgKyAkZXhwb3J0LkYgKiBmYWlscyhmdW5jdGlvbigpeyBmbigxKTsgfSksICdPYmplY3QnLCBleHApO1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX29iamVjdC1zYXAuanNcbi8vIG1vZHVsZSBpZCA9IDUwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsInZhciBoaWRlID0gcmVxdWlyZSgnLi9faGlkZScpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbih0YXJnZXQsIHNyYywgc2FmZSl7XG4gIGZvcih2YXIga2V5IGluIHNyYyl7XG4gICAgaWYoc2FmZSAmJiB0YXJnZXRba2V5XSl0YXJnZXRba2V5XSA9IHNyY1trZXldO1xuICAgIGVsc2UgaGlkZSh0YXJnZXQsIGtleSwgc3JjW2tleV0pO1xuICB9IHJldHVybiB0YXJnZXQ7XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fcmVkZWZpbmUtYWxsLmpzXG4vLyBtb2R1bGUgaWQgPSA1MVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyA3LjEuMTUgVG9MZW5ndGhcbnZhciB0b0ludGVnZXIgPSByZXF1aXJlKCcuL190by1pbnRlZ2VyJylcbiAgLCBtaW4gICAgICAgPSBNYXRoLm1pbjtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaXQpe1xuICByZXR1cm4gaXQgPiAwID8gbWluKHRvSW50ZWdlcihpdCksIDB4MWZmZmZmZmZmZmZmZmYpIDogMDsgLy8gcG93KDIsIDUzKSAtIDEgPT0gOTAwNzE5OTI1NDc0MDk5MVxufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3RvLWxlbmd0aC5qc1xuLy8gbW9kdWxlIGlkID0gNTJcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwidmFyIGlkID0gMFxuICAsIHB4ID0gTWF0aC5yYW5kb20oKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oa2V5KXtcbiAgcmV0dXJuICdTeW1ib2woJy5jb25jYXQoa2V5ID09PSB1bmRlZmluZWQgPyAnJyA6IGtleSwgJylfJywgKCsraWQgKyBweCkudG9TdHJpbmcoMzYpKTtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL191aWQuanNcbi8vIG1vZHVsZSBpZCA9IDUzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIid1c2Ugc3RyaWN0J1xuXG5leHBvcnQgY29uc3QgUHVibGlzaFR5cGVzID0gT2JqZWN0LmZyZWV6ZSh7XG4gIFJUTVA6ICdydG1wJyxcbiAgUlRDOiAncnRjJ1xufSlcblxuZXhwb3J0IGNvbnN0IFB1Ymxpc2hNb2RlVHlwZXMgPSBPYmplY3QuZnJlZXplKHtcbiAgTElWRTogJ2xpdmUnLFxuICBSRUNPUkQ6ICdyZWNvcmQnLFxuICBBUFBFTkQ6ICdhcHBlbmQnXG59KVxuXG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvanMvZW51bS9wdWJsaXNoLmpzIiwiLyoqXG4gKiBFbnVtZXJhdGlvbiBvZiBTdXBwb3J0IElDRSBUcmFuc3BvcnQgdHlwZXMuXG4gKi9cbmV4cG9ydCBjb25zdCBJY2VUcmFuc3BvcnRUeXBlcyA9IE9iamVjdC5mcmVlemUoe1xuICBVRFA6ICd1ZHAnLFxuICBUQ1A6J3RjcCdcbn0pXG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvanMvZW51bS93ZWJydGMuanMiLCIvKipcbiAqIENvbW1vbiBldmVudCB0eXBlcyBvbiBTaGFyZWRPYmplY3QuXG4gKlxuICogQHNlZSB7UmVkNVByb1NoYXJlZE9iamVjdH1cbiAqL1xuZXhwb3J0IGNvbnN0IFNoYXJlZE9iamVjdEV2ZW50VHlwZXMgPSBPYmplY3QuZnJlZXplKHtcbiAgQ09OTkVDVF9TVUNDRVNTOiAnQ29ubmVjdC5TdWNjZXNzJyxcbiAgQ09OTkVDVF9GQUlMVVJFOiAnQ29ubmVjdC5GYWlsdXJlJyxcbiAgUFJPUEVSVFlfVVBEQVRFOiAnU2hhcmVkT2JqZWN0LlByb3BlcnR5VXBkYXRlJyxcbiAgTUVUSE9EX1VQREFURTogJ1NoYXJlZE9iamVjdC5NZXRob2RVcGRhdGUnXG59KVxuXG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvanMvZXZlbnQvc2hhcmVkb2JqZWN0LWV2ZW50LmpzIiwiJ3VzZSBzdHJpY3QnXG5pbXBvcnQgKiBhcyB3ZWJzb2NrZXQgZnJvbSAnLi4vYWRhcHRlci93ZWJzb2NrZXQnXG5pbXBvcnQgZW52aXJvbm1lbnQgZnJvbSAnLi4vZW52L2Jyb3dzZXInXG5pbXBvcnQgeyBEZWZlcnJlZFByb21pc2UgfSBmcm9tICcuLi91dGlsL3Byb21pc2UnXG5pbXBvcnQgeyBpbmZvLCBkZWJ1Zywgd2FybiB9IGZyb20gJy4uL2xvZydcblxuLyoqXG4gKiBCYXNlIFByb3h5IGZvciBjb21tdW5pY2F0aW9uIHdpdGggV2ViU29ja2V0LlxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmNsYXNzIFNvY2tldEhlbHBlciB7XG5cbiAgY29uc3RydWN0b3IgKHJlc3BvbmRlciwgbmFtZSkge1xuICAgIHRoaXMuX3Jlc3BvbmRlciA9IHJlc3BvbmRlclxuICAgIHRoaXMuX3BlbmRpbmdQb3N0UmVxdWVzdHMgPSBbXVxuICAgIHRoaXMuX3dlYnNvY2tldCA9IHVuZGVmaW5lZFxuICAgIHRoaXMuX2Nvbm5lY3Rpb25Qcm9taXNlID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fbmFtZSA9IG5hbWVcbiAgICB0aGlzLl9yZXNwb25zZUhhbmRsZXJzID0gW11cbiAgICB0aGlzLl9pc1Rlcm1pbmF0ZWQgPSBmYWxzZVxuICAgIHRoaXMuX3JldHJ5Q291bnQgPSAwXG4gICAgdGhpcy5fcmV0cnlMaW1pdCA9IDFcbiAgICB0aGlzLl9yZWFkeUNoZWNrQ291bnQgPSAwXG4gICAgdGhpcy5fcmVhZHlDaGVja0xpbWl0ID0gMTBcbiAgICB0aGlzLl9vbmNsb3NlID0gdGhpcy50ZWFyRG93bi5iaW5kKHRoaXMpXG5cbiAgICB0aGlzLl9vbm9wZW5UaW1lb3V0ID0gMFxuXG4gICAgdGhpcy5fYXN5bmNUaWNrZXRzID0gW11cbiAgfVxuXG4gIF9yZXNldE9ub3BlblRpbWVvdXQgKHdzLCBwcm9taXNlKSB7XG4gICAgY29uc3QgaXNNb3ogPSBlbnZpcm9ubWVudC5nZXRJc01veigpXG4gICAgbGV0IHRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KVxuICAgICAgaWYgKHdzLnJlYWR5U3RhdGUgPT09IDEpIHtcbiAgICAgICAgaW5mbyh0aGlzLl9uYW1lLCAnW3dlYnNvY2tldG9wZW5dJylcbiAgICAgICAgd2hpbGUgKHRoaXMuX3BlbmRpbmdQb3N0UmVxdWVzdHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHRoaXMucG9zdCh0aGlzLl9wZW5kaW5nUG9zdFJlcXVlc3RzLnNoaWZ0KCkpXG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuX3Jlc3BvbmRlciAmJiB0aGlzLl9yZXNwb25kZXIub25Tb2NrZXRPcGVuKSB7XG4gICAgICAgICAgdGhpcy5fcmVzcG9uZGVyLm9uU29ja2V0T3BlbigpXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZih3cy5yZWFkeVN0YXRlID09PSAwKSB7XG4gICAgICAgIGlmICgrK3RoaXMuX3JlYWR5Q2hlY2tDb3VudCA+IHRoaXMuX3JlYWR5Q2hlY2tMaW1pdCkge1xuICAgICAgICAgIHdhcm4odGhpcy5fbmFtZSwgYFdlYlNvY2tldCBjb25uZWN0aW9uIGlzc3VlLiBXZSBoYXZlIHdhaXRlZCBmb3IgJHt0aGlzLl9yZWFkeUNoZWNrQ291bnQtMX0gc2FtcGxlcywgd2l0aG91dCBhbnkgY29ubmVjdGlvbi5gKVxuICAgICAgICAgIC8vIElmIEZpcmVmb3gsIHRyeSBhIHNlY29uZCBjb25uZWN0aW9uIGF0dGVtcHQgb3IgZmFpbC5cbiAgICAgICAgICAvKlxuICAgICAgICAgIGlmIChpc01veiAmJiArK3RoaXMuX3JldHJ5Q291bnQgPCB0aGlzLl9yZXRyeUxpbWl0KSB7XG4gICAgICAgICAgICB3YXJuKHRoaXMuX25hbWUsIGBXZWJTb2NrZXQgYXR0ZW1wdGluZyByZXRyeS4uLmApXG4gICAgICAgICAgICB0aGlzLl9yZW1vdmVTb2NrZXRIYW5kbGVycyh3cylcbiAgICAgICAgICAgIHRoaXMuX29ub3BlblRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuX29ub3BlblRpbWVvdXQpXG4gICAgICAgICAgICAgIHRoaXMuc2V0VXAod3MudXJsLCBwcm9taXNlKVxuICAgICAgICAgICAgfSwgMjAwMClcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcHJvbWlzZS5yZWplY3Qoe3R5cGU6ICdUaW1lb3V0J30pXG4gICAgICAgICAgfVxuICAgICAgICAgICovXG4gICAgICAgICAgdGhpcy5jbGVhclJldHJ5KClcbiAgICAgICAgICBwcm9taXNlLnJlamVjdCh7dHlwZTogJ1RpbWVvdXQnfSlcbiAgICAgICAgICB0aGlzLnRlYXJEb3duKClcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpbmZvKHRoaXMuX25hbWUsIGBXZWJTb2NrZXQgY29ubmVjdGlvbiBpcyBzdGlsbCBvcGVuaW5nLCB3aWxsIGxldCBpdCBjb250aW51ZSAoJHt0aGlzLl9yZWFkeUNoZWNrQ291bnR9KS4uLmApXG4gICAgICAgICAgdGhpcy5fb25vcGVuVGltZW91dCA9IHRoaXMuX3Jlc2V0T25vcGVuVGltZW91dCh3cywgcHJvbWlzZSlcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW5mbyh0aGlzLl9uYW1lLCBgV2ViU29ja2V0IGNvbm5lY3Rpb24gYXR0ZW1wdHMgaGF2ZSBlbmRlZCB3aXRoIHN0YXRlICgke3dzLnJlYWR5U3RhdGV9KS5gKVxuICAgICAgfVxuICAgIH0sIDUwMClcbiAgICByZXR1cm4gdGltZW91dFxuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgZXZlbnQgaGFuZGxlcnMgZnJvbSBXZWJTb2NrZXQuXG4gICAqXG4gICAqIEBwYXJhbSB7V2ViU29ja2V0fSB3c1xuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX3JlbW92ZVNvY2tldEhhbmRsZXJzICh3cykge1xuICAgIGlmICh3cykge1xuICAgICAgd3Mub25vcGVuID0gdW5kZWZpbmVkXG4gICAgICB3cy5vbm1lc3NhZ2UgPSB1bmRlZmluZWRcbiAgICAgIHdzLm9uZXJyb3IgPSB1bmRlZmluZWRcbiAgICAgIHdzLm9uY2xvc2UgPSB1bmRlZmluZWRcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQXNzaWducyBldmVudCBoYW5kbGVyIHRvIFdlYlNvY2tldC5cbiAgICpcbiAgICogQHBhcmFtIHtXZWJTb2NrZXR9IHdzXG4gICAqIEBwYXJhbSB7UHJvbWlzZX1cbiAgICogICAgICAgIFRoZSBgUHJvbWlzZWAgdG8gcmVqZWN0IG9uIGVycm9yIGluIGNvbm5lY3Rpb24gdG8gV2ViU29ja2V0LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX2FkZFNvY2tldEhhbmRsZXJzICh3cywgcHJvbWlzZSkge1xuXG4gICAgLyogXG4gICAgICogUmVtb3ZpbmcgdGhpcyBpbiBmYXZvciBvZiBjaGVja2luZyByZWFkeVN0YXRlIGZvciB2ZXJpZmljYXRpb24gb2Ygb3Blbi5cbiAgICAgKlxuICAgIHdzLm9ub3BlbiA9ICgpID0+IHtcbiAgICAgIGluZm8odGhpcy5fbmFtZSwgJ1t3ZWJzb2NrZXRvcGVuXScpXG4gICAgICB3aGlsZSAodGhpcy5fcGVuZGluZ1Bvc3RSZXF1ZXN0cy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHRoaXMucG9zdCh0aGlzLl9wZW5kaW5nUG9zdFJlcXVlc3RzLnNoaWZ0KCkpXG4gICAgICB9XG4gICAgfVxuICAgICovXG5cbiAgICB0aGlzLl9yZWFkeUNoZWNrQ291bnQgPSAwXG4gICAgY2xlYXJUaW1lb3V0KHRoaXMuX29ub3BlblRpbWVvdXQpXG4gICAgdGhpcy5fb25vcGVuVGltZW91dCA9IHRoaXMuX3Jlc2V0T25vcGVuVGltZW91dCh3cywgcHJvbWlzZSlcblxuICAgIHdzLm9uZXJyb3IgPSAoZXJyb3IpID0+IHtcbiAgICAgIHdhcm4odGhpcy5fbmFtZSwgYFt3ZWJzb2NrZXRlcnJvcl06IEVycm9yIGZyb20gV2ViU29ja2V0LiAke2Vycm9yLnR5cGV9LmApXG4gICAgICB0aGlzLmNsZWFyUmV0cnkoKVxuICAgICAgcHJvbWlzZS5yZWplY3QoZXJyb3IpXG4gICAgfVxuXG4gICAgd3Mub25tZXNzYWdlID0gKG1lc3NhZ2UpID0+IHtcbiAgICAgIHRoaXMucmVzcG9uZChtZXNzYWdlKVxuICAgIH1cblxuICAgIHdzLm9uY2xvc2UgPSAoZXZlbnQpID0+IHtcbiAgICAgIHdhcm4odGhpcy5fbmFtZSwgYFt3ZWJzb2NrZXRjbG9zZV06ICR7ZXZlbnQuY29kZX1gKVxuICAgICAgaWYgKHRoaXMuX3Jlc3BvbmRlcikge1xuICAgICAgIHRoaXMuX3Jlc3BvbmRlci5vblNvY2tldENsb3NlKGV2ZW50KVxuICAgICAgfVxuICAgICAgdGhpcy5jbGVhclJldHJ5KClcbiAgICAgIHRoaXMuX3JlbW92ZVNvY2tldEhhbmRsZXJzKHdzIHx8IHRoaXMuX3dlYnNvY2tldClcbiAgICB9XG5cbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGVyIGZvciB1bmV4cGVjdGVkIGVycm9yIHRocm91Z2ggV2ViU29ja2V0LlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZXJyb3JcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9vblVuZXhwZWN0ZWRTb2NrZXRFcnJvciAoZXJyb3IpIHtcbiAgICBpZiAodGhpcy5fcmVzcG9uZGVyKSB7XG4gICAgICB0aGlzLl9yZXNwb25kZXIub25Tb2NrZXRDbG9zZShlcnJvcilcbiAgICB9XG4gICAgd2Fybih0aGlzLl9uYW1lLCBgW3dlYnNvY2tldGVycm9yXTogUG9zc2libGUgVW5leHBlY3RlZCBFcnJvciBmcm9tIFdlYlNvY2tldC4gJHtlcnJvci50eXBlfSwgJHtlcnJvci5kZXRhaWx9YClcbiAgICB0aGlzLmNsZWFyUmV0cnkoKVxuICAgIHRoaXMuX3JlbW92ZVNvY2tldEhhbmRsZXJzKHRoaXMuX3dlYnNvY2tldClcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhcnMgdGhlIHJldHJ5IGNvdW50IHRvIGFsbG93IGZvciBzaW5nbGUgcHVibGlzaGVyIHRvIHJldHJ5IGFnYWluIGFmdGVyIGFuIHVucHVibGlzaC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIGNsZWFyUmV0cnkgKCkge1xuICAgIHRoaXMuX3JldHJ5Q291bnQgPSAwXG4gICAgdGhpcy5fcmVhZHlDaGVja0NvdW50ID0gMFxuICAgIGNsZWFyVGltZW91dCh0aGlzLl9vbm9wZW5UaW1lb3V0KVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gc2V0dXAgV2ViU29ja2V0IGNvbm5lY3Rpb24gZm9yIGNvbW11bmljYXRpb24uXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSB1cmxcbiAgICogICAgICAgIEVuZHBvaW50IFVSTCBvZiB0aGUgc29ja2V0IHRvIGNvbm5lY3QgdG8uXG4gICAqIEBwYXJhbSB7UHJvbWlzZX0gc2V0dXBQcm9taXNlXG4gICAqICAgICAgICBUaGUgYFByb21pc2VgIHRvIHJlc29sdmUgb3IgcmVqZWN0IG9uIHN1Y2Nlc3Mgb2Ygc2V0dXAgV2ViU29ja2V0IGNvbm5lY3Rpb24uXG4gICAqL1xuICBzZXRVcCAodXJsLCBzZXR1cFByb21pc2UpIHtcbiAgICBjb25zdCBpc01veiA9IGVudmlyb25tZW50LmdldElzTW96KClcbiAgICBkZWJ1Zyh0aGlzLl9uYW1lLCBgW3dlYnNvY2tldDpzZXR1cF0gJHt1cmx9LmApXG4gICAgdGhpcy50ZWFyRG93bigpXG4gICAgdGhpcy5faXNUZXJtaW5hdGVkID0gZmFsc2VcbiAgICB0aGlzLl9jb25uZWN0aW9uUHJvbWlzZSA9IHNldHVwUHJvbWlzZVxuICAgIGVudmlyb25tZW50LmFkZENsb3NlSGFuZGxlcih0aGlzLl9vbmNsb3NlKVxuICAgIHRoaXMuX3dlYnNvY2tldCA9IHdlYnNvY2tldC5jcmVhdGUodXJsKVxuICAgIHRoaXMuX2FkZFNvY2tldEhhbmRsZXJzKHRoaXMuX3dlYnNvY2tldCwgdGhpcy5fY29ubmVjdGlvblByb21pc2UpXG4gICAgaWYgKGlzTW96ICYmIHRoaXMuX3JldHJ5Q291bnQrKyA8IHRoaXMuX3JldHJ5TGltaXQpIHtcbiAgICAgIGRlYnVnKHRoaXMuX25hbWUsICdXZSBoYXZlIGRldGVybWluZWQgaXQgaXMgRmlyZWZveCBhbmQgYXJlIHNldHRpbmcgdXAgYSByZXRyeSBsaW1pdC4nKVxuICAgICAgbGV0IHRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuX3dlYnNvY2tldCAmJiB0aGlzLl93ZWJzb2NrZXQucmVhZHlTdGF0ZSA9PT0gMCkge1xuICAgICAgICAgIGRlYnVnKHRoaXMuX25hbWUsIGBbd2Vic29ja2V0OkZGLXRpbWVvdXRdYClcbiAgICAgICAgICBkZWJ1Zyh0aGlzLl9uYW1lLCAnT3VyIGNvbm5lY3Rpb24gb24gRmlyZWZveCB0byB0aGUgd3NzIGVuZHBvaW50IGhhcyB0aW1lZCBvdXQuIExldFxcJ3MgdHJ5IHRoYXQgYWdhaW4uJylcbiAgICAgICAgICB0aGlzLl9yZW1vdmVTb2NrZXRIYW5kbGVycyh0aGlzLl93ZWJzb2NrZXQpXG4gICAgICAgICAgdGhpcy5zZXRVcCh1cmwsIHNldHVwUHJvbWlzZSlcbiAgICAgICAgfVxuICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dClcbiAgICAgIH0sIDIwMDApXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gdGVhciBkb3duIGFueSBXZWJTb2NrZXQgY29ubmVjdGlvbi5cbiAgICovXG4gIHRlYXJEb3duICgpIHtcbiAgICB0aGlzLl9wZW5kaW5nUG9zdFJlcXVlc3RzLmxlbmd0aCA9IDBcbiAgICBpZiAodHlwZW9mIHRoaXMuX3dlYnNvY2tldCAhPT0gJ3VuZGVmaW5lZCcgJiYgIXRoaXMuX2lzVGVybWluYXRlZCkge1xuICAgICAgZGVidWcodGhpcy5fbmFtZSwgJ1t0ZWFyZG93bl0gPj4nKVxuICAgICAgZGVidWcodGhpcy5fbmFtZSwgYFtXZWJTb2NrZXQoJHt0aGlzLl93ZWJzb2NrZXQudXJsfSldIGNsb3NlKCkgPj5gKVxuICAgICAgLy8gICAgICB0aGlzLl9yZW1vdmVTb2NrZXRIYW5kbGVycyh0aGlzLl93ZWJzb2NrZXQpXG4gICAgICB0cnkge1xuICAgICAgICB0aGlzLl93ZWJzb2NrZXQuY2xvc2UoKVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB3YXJuKHRoaXMuX25hbWUsIGBBdHRlbXB0IHRvIGNsb3NlIFdlYlNvY2tldCBmYWlsZWQ6ICR7ZS5tZXNzYWdlfS5gKVxuICAgICAgICB0aGlzLl9yZW1vdmVTb2NrZXRIYW5kbGVycyh0aGlzLl93ZWJzb2NrZXQpXG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBpZiAodGhpcy5fd2Vic29ja2V0KSB7XG4gICAgICAgICAgZGVidWcodGhpcy5fbmFtZSwgYDw8IFtXZWJTb2NrZXQoJHt0aGlzLl93ZWJzb2NrZXQudXJsfSldIGNsb3NlKClgKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBkZWJ1Zyh0aGlzLl9uYW1lLCAnPDwgW3RlYXJkb3duXScpXG4gICAgfVxuICAgIHRoaXMuX3dlYnNvY2tldCA9IHVuZGVmaW5lZFxuICAgIHRoaXMuX2lzVGVybWluYXRlZCA9IHRydWVcbiAgICB3aGlsZSh0aGlzLl9yZXNwb25zZUhhbmRsZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuX3Jlc3BvbnNlSGFuZGxlcnMuc2hpZnQoKVxuICAgIH1cbiAgICBlbnZpcm9ubWVudC5yZW1vdmVDbG9zZUhhbmRsZXIodGhpcy5fb25jbG9zZSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIHBhcnNlIEpTT04gZnJvbSBtZXNzYWdlIHJlY2VpdmVkIG92ZXIgV2ViU29ja2V0LlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gbWVzc2FnZVxuICAgKiAgICAgICAgU3RyaW5nIG9yIE9iamVjdC5cbiAgICovXG4gIGdldEpzb25Gcm9tU29ja2V0TWVzc2FnZSAobWVzc2FnZSkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gdHlwZW9mIG1lc3NhZ2UuZGF0YSA9PT0gJ3N0cmluZycgPyBKU09OLnBhcnNlKG1lc3NhZ2UuZGF0YSkgOiBtZXNzYWdlLmRhdGFcbiAgICB9XG4gICAgY2F0Y2ggKGUpIHtcbiAgICAgIHdhcm4odGhpcy5fbmFtZSwgJ0NvdWxkIG5vdCBwYXJzZSBtZXNzYWdlIGFzIEpTT04uIE1lc3NhZ2U9ICcgKyBtZXNzYWdlLmRhdGEgKyAnLiBFcnJvcj0gJyArIGUubWVzc2FnZSlcbiAgICB9XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgU2hhcmVkT2JqZWN0IHJlc3BvbnNlIGhhbmRsZXIuIEhhbmRsZXJzIGFyZSByZXF1ZXN0ZWQgdG8gcmVzcG9uZCB0byBhIG1lc3NhZ2UgaW4gYGhhbmRsZU1lc3NhZ2VSZXNwb25zZWAuXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBoYW5kbGVyXG4gICAqL1xuICBhZGRTaGFyZWRPYmplY3RSZXNwb25zZUhhbmRsZXIgKGhhbmRsZXIpIHtcbiAgICB0aGlzLl9yZXNwb25zZUhhbmRsZXJzLnB1c2goaGFuZGxlcilcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIGEgU2hhcmVkT2JqZWN0IHJlc3BvbnNlIGhhbmRsZXIuXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBoYW5kbGVyXG4gICAqL1xuICByZW1vdmVTaGFyZWRPYmplY3RSZXNwb25zZUhhbmRsZXIgKGhhbmRsZXIpIHtcbiAgICBsZXQgaSA9IHRoaXMuX3Jlc3BvbnNlSGFuZGxlcnMubGVuZ3RoXG4gICAgbGV0IHJIYW5kbGVyXG4gICAgd2hpbGUoLS1pID4gLTEpIHtcbiAgICAgIHJIYW5kbGVyID0gdGhpcy5fcmVzcG9uc2VIYW5kbGVyc1tpXVxuICAgICAgaWYgKHJIYW5kbGVyID09PSBoYW5kbGVyKSB7XG4gICAgICAgIHRoaXMuX3Jlc3BvbnNlSGFuZGxlcnMuc3BsaWNlKGksIDEpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUcmF2ZXJzZXMgbGlzdCBvZiByZXNwb25zZSBoYW5kbGVycyBhbmQgcmV0dXJucyBmbGFnIG9mIGl0IGJlaW5nIGhhbmRsZWQgd2l0aGluIHRoZSBjaGFpbi5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IG1lc3NhZ2VcbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGhhbmRsZU1lc3NhZ2VSZXNwb25zZSAobWVzc2FnZSkge1xuICAgIGxldCBpLCBoYW5kbGVyXG4gICAgbGV0IGxlbmd0aCA9IHRoaXMuX3Jlc3BvbnNlSGFuZGxlcnMubGVuZ3RoXG4gICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVyID0gdGhpcy5fcmVzcG9uc2VIYW5kbGVyc1tpXVxuICAgICAgaWYgKGhhbmRsZXIucmVzcG9uZChtZXNzYWdlKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIHBvc3Qgbm90aWZpY2F0aW9uIG9mIGVuZCBvZiBjYW5kaWRhdGVzIGluIFdlYlJUQyBzY2VuYXJpby5cbiAgICovXG4gIHBvc3RFbmRPZkNhbmRpZGF0ZXMgKHN0cmVhbU5hbWUpIHtcbiAgICB0aGlzLnBvc3Qoe1xuICAgICAgaGFuZGxlQ2FuZGlkYXRlOiBzdHJlYW1OYW1lLFxuICAgICAgZGF0YToge1xuICAgICAgICBjYW5kaWRhdGU6IHtcbiAgICAgICAgICB0eXBlOiAnY2FuZGlkYXRlJyxcbiAgICAgICAgICBjYW5kaWRhdGU6ICcnXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gcG9zdCBkYXRhIG92ZXIgV2ViU29ja2V0IGNvbm5lY3Rpb24uXG4gICAqIFF1ZXVlcyBtZXNzYWdlcyBpZiBXZWJTb2NrZXQgY29ubmVjdGlvbiBpcyBzdGlsbCBiZWluZyBlc3RhYmxpc2hlZC5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IHNlbmRSZXF1ZXN0XG4gICAqL1xuICBwb3N0IChzZW5kUmVxdWVzdCkge1xuICAgIGlmICh0aGlzLl93ZWJzb2NrZXQgIT09IHVuZGVmaW5lZCAmJiB0aGlzLl93ZWJzb2NrZXQucmVhZHlTdGF0ZSA9PT0gMSAvKiBXZWJTb2NrZXQuT1BFTiAqLykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZGVidWcodGhpcy5fbmFtZSwgJ1t3ZWJzb2NrZXQtcG9zdF06ICcgKyBKU09OLnN0cmluZ2lmeShzZW5kUmVxdWVzdCwgbnVsbCwgMikpXG4gICAgICAgIHRoaXMuX3dlYnNvY2tldC5zZW5kKEpTT04uc3RyaW5naWZ5KHNlbmRSZXF1ZXN0KSlcbiAgICAgICAgcmV0dXJuIHRydWVcbiAgICAgIH1cbiAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgIGRlYnVnKHRoaXMuX25hbWUsIGBDb3VsZCBub3Qgc2VuZCByZXF1ZXN0OiAke3NlbmRSZXF1ZXN0fS4gJHtlfWApXG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIGlmICh0aGlzLl93ZWJzb2NrZXQgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAodGhpcy5fd2Vic29ja2V0LnJlYWR5U3RhdGUgPT09IDIgfHwgdGhpcy5fd2Vic29ja2V0LnJlYWR5U3RhdGUgPT09IDMpKSAvKiBXZWJTb2NrZXQuKENMT1NJTkcgfCBDTE9TRUQpICovIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgICBlbHNlIGlmICh0aGlzLl9pc1Rlcm1pbmF0ZWQpIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHRoaXMuX3BlbmRpbmdQb3N0UmVxdWVzdHMucHVzaChzZW5kUmVxdWVzdClcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuICB9XG5cbiAgcG9zdEFzeW5jIChzZW5kUmVxdWVzdCkge1xuICAgIGNvbnN0IHAgPSBuZXcgRGVmZXJyZWRQcm9taXNlKClcbiAgICBjb25zdCBpZCA9IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIDB4MTAwMDApLnRvU3RyaW5nKDE2KVxuICAgIHNlbmRSZXF1ZXN0LmlkID0gaWRcbiAgICBzZW5kUmVxdWVzdC5hc3luYyA9IHRydWVcbiAgICB0aGlzLl9hc3luY1RpY2tldHMucHVzaCh7aWQ6IGlkLCBwcm9taXNlOiBwfSlcbiAgICB0aGlzLnBvc3Qoc2VuZFJlcXVlc3QpXG4gICAgcmV0dXJuIHAucHJvbWlzZVxuICB9XG5cbiAgLyoqXG4gICAqIFJlc3BvbmRzIHRvIG1lc3NhZ2VzIGNvbWluZyBvdmVyIHRoZSBXZWJTb2NrZXQgY29ubmVjdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IG1lc3NhZ2VcbiAgICovXG4gIHJlc3BvbmQgKG1lc3NhZ2UpIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuICAgIGxldCBoYW5kbGVkID0gdGhpcy5oYW5kbGVNZXNzYWdlUmVzcG9uc2UobWVzc2FnZSlcbiAgICBpZiAoIWhhbmRsZWQgJiYgbWVzc2FnZS5kYXRhKSB7XG4gICAgICBsZXQganNvbiA9IHRoaXMuZ2V0SnNvbkZyb21Tb2NrZXRNZXNzYWdlKG1lc3NhZ2UpXG4gICAgICBpZiAoanNvbiA9PT0gbnVsbCkge1xuICAgICAgICB3YXJuKHRoaXMuX25hbWUsICdEZXRlcm1pbmVkIHdlYnNvY2tldCByZXNwb25zZSBub3QgaW4gY29ycmVjdCBmb3JtYXQuIEFib3J0aW5nIG1lc3NhZ2UgaGFuZGxlLicpXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgZGVidWcodGhpcy5fbmFtZSwgJ1t3ZWJzb2NrZXQtcmVzcG9uc2VdOiAnICsgSlNPTi5zdHJpbmdpZnkoanNvbiwgbnVsbCwgMikpXG4gICAgICBpZiAoanNvbi5pc0F2YWlsYWJsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGlmICh0eXBlb2YganNvbi5pc0F2YWlsYWJsZSA9PT0gJ2Jvb2xlYW4nICYmIGpzb24uaXNBdmFpbGFibGUpIHtcbiAgICAgICAgICB0aGlzLl9yZXNwb25kZXIub25TdHJlYW1BdmFpbGFibGUoanNvbilcbiAgICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuX3Jlc3BvbmRlci5vblN0cmVhbVVuYXZhaWxhYmxlKGpzb24pXG4gICAgICAgICAgcmV0dXJuIHRydWVcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChqc29uLmFzeW5jICYmIGpzb24uaWQpIHtcbiAgICAgICAgY29uc3QgdGlja2V0ID0gdGhpcy5fYXN5bmNUaWNrZXRzLmZpbmQoZWwgPT4gZWwuaWQgPT09IGpzb24uaWQpXG4gICAgICAgIGNvbnN0IHsgcHJvbWlzZSB9ID0gdGlja2V0XG4gICAgICAgIGlmIChwcm9taXNlICYmIGpzb24uZGF0YSkge1xuICAgICAgICAgIHByb21pc2UucmVzb2x2ZShqc29uLmRhdGEpXG4gICAgICAgIH0gZWxzZSBpZiAocHJvbWlzZSAmJiBqc29uLmVycm9yKSB7XG4gICAgICAgICAgcHJvbWlzZS5yZWplY3QoanNvbi5lcnJvcilcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChqc29uLmRhdGEgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjb25zdCB7IGRhdGEgfSA9IGpzb25cbiAgICAgICAgaWYgKGRhdGEubWVzc2FnZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgaWYgKGRhdGEudHlwZSA9PT0gJ2Vycm9yJykge1xuICAgICAgICAgICAgdGhpcy5fcmVzcG9uZGVyLm9uU29ja2V0TWVzc2FnZUVycm9yKGRhdGEubWVzc2FnZSwgZGF0YS5kZXRhaWwpXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChkYXRhLnR5cGUgPT09ICdzdGF0dXMnKSB7XG4gICAgICAgICAgaWYgKGRhdGEuY29kZSA9PT0gJ05ldENvbm5lY3Rpb24uQ29ubmVjdC5TdWNjZXNzJykge1xuICAgICAgICAgICAgdGhpcy5fd2Vic29ja2V0Lm9uZXJyb3IgPSB0aGlzLl9vblVuZXhwZWN0ZWRTb2NrZXRFcnJvci5iaW5kKHRoaXMpXG4gICAgICAgICAgICB0aGlzLl9jb25uZWN0aW9uUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgICAgfSBlbHNlIGlmIChkYXRhLmNvZGUgPT09ICdOZXRDb25uZWN0aW9uLkNvbm5lY3QuUmVqZWN0ZWQnKSB7XG4gICAgICAgICAgICB0aGlzLl9jb25uZWN0aW9uUHJvbWlzZS5yZWplY3QoJ05ldENvbm5lY3Rpb24uQ29ubmVjdC5SZWplY3RlZCcpXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChkYXRhLnR5cGUgPT09ICdlcnJvcicpIHtcbiAgICAgICAgICBpZiAoZGF0YS5jb2RlID09PSAnTmV0Q29ubmVjdGlvbi5Db25uZWN0LlJlamVjdGVkJykge1xuICAgICAgICAgICAgdGhpcy5fY29ubmVjdGlvblByb21pc2UucmVqZWN0KCdOZXRDb25uZWN0aW9uLkNvbm5lY3QuUmVqZWN0ZWQnKVxuICAgICAgICAgICAgcmV0dXJuIHRydWVcbiAgICAgICAgICB9IGVsc2UgaWYgKGRhdGEuY29kZSA9PT0gJ05ldENvbm5lY3Rpb24uQ29ubmVjdC5GYWlsZWQnKSB7XG4gICAgICAgICAgICB0aGlzLl9jb25uZWN0aW9uUHJvbWlzZS5yZWplY3QoJ05ldENvbm5lY3Rpb24uQ29ubmVjdC5GYWlsZWQnKVxuICAgICAgICAgICAgcmV0dXJuIHRydWVcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGhhbmRsZWRcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIGdldCBTaGFyZWRPYmplY3QgZnJvbSBzZXJ2ZXIgb3ZlciBXZWJTb2NrZXQuXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqL1xuICBnZXRSZW1vdGVTaGFyZWRPYmplY3QgKG5hbWUpIHtcbiAgICB0aGlzLnBvc3Qoe1xuICAgICAgc2hhcmVkT2JqZWN0R2V0UmVtb3RlOiB7XG4gICAgICAgIG5hbWU6IG5hbWVcbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gY29ubmVjdCB0byBTaGFyZWRPYmplY3QgZnJvbSBzZXJ2ZXIgb3ZlciBXZWJTb2NrZXQuXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqL1xuICBjb25uZWN0VG9TaGFyZWRPYmplY3QgKG5hbWUpIHtcbiAgICB0aGlzLnBvc3Qoe1xuICAgICAgc2hhcmVkT2JqZWN0Q29ubmVjdDoge1xuICAgICAgICBuYW1lOiBuYW1lXG4gICAgICB9XG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIHNlbmQgbWV0aG9kIGNhbGwgdG8gU2hhcmVkT2JqZWN0IG92ZXIgV2ViU29ja2V0LlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gY2FsbE5hbWVcbiAgICogQHBhcmFtIHtPYmplY3R9IGRhdGFcbiAgICovXG4gIHNlbmRUb1NoYXJlZE9iamVjdCAobmFtZSwgY2FsbE5hbWUsIGRhdGEpIHtcbiAgICB0aGlzLnBvc3Qoe1xuICAgICAgc2hhcmVkT2JqZWN0U2VuZDoge1xuICAgICAgICBuYW1lOiBuYW1lLFxuICAgICAgICBjYWxsOiBjYWxsTmFtZSxcbiAgICAgICAgcGFyYW1zOiBbZGF0YV1cbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gdXBkYXRlIHByb3BlcnR5IG9uIFNoYXJlZE9iamVjdCBvdmVyIFdlYlNvY2tldC5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IGtleVxuICAgKiBAcGFyYW0ge1N0cmluZ30gdmFsdWVcbiAgICovXG4gIHNlbmRQcm9wZXJ0eVRvU2hhcmVkT2JqZWN0IChuYW1lLCBrZXksIHZhbHVlKSB7XG4gICAgdGhpcy5wb3N0KHtcbiAgICAgIHNoYXJlZE9iamVjdFNldFByb3BlcnR5OiB7XG4gICAgICAgIG5hbWU6IG5hbWUsXG4gICAgICAgIGtleToga2V5LFxuICAgICAgICB2YWx1ZTogdmFsdWVcbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gY2xvc2UgdGhlIFNoYXJlZE9iamVjdCBjb25uZWN0aW9uIG92ZXIgV2ViU29ja2V0LlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZVxuICAgKi9cbiAgY2xvc2VTaGFyZWRPYmplY3QgKG5hbWUpIHtcbiAgICB0aGlzLnBvc3Qoe1xuICAgICAgc2hhcmVkT2JqZWN0Q2xvc2U6IHtcbiAgICAgICAgbmFtZTogbmFtZVxuICAgICAgfVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBmbGFnIG9mIHNvY2tldCBiZWluZyBjbG9zZWQgYW5kIHRlbXJpbmF0ZWQuXG4gICAqXG4gICAqIEByZXR1cm5zIHtCb29sZWFufVxuICAgKi9cbiAgZ2V0IGlzVGVybWluYXRlZCAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2lzVGVybWluYXRlZFxuICB9XG5cbn1cblxuZXhwb3J0IGRlZmF1bHQgU29ja2V0SGVscGVyXG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvanMvaGVscGVyL3NvY2tldC1oZWxwZXIuanMiLCIndXNlIHN0cmljdCdcblxuLyoqXG4gKiBFbmNvZGUgdGhlIHZhbHVlIG9mIGVhY2gga2V5IGFuZCByZXR1cm4gYSBuZXcgb2JqZWN0LlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSB2YWx1ZU9iamVjdFxuICogICAgICAgIFRoZSBvYmplY3Qgd2hvc2UgdmFsdWVzIHNob3VsZCBiZSBlbmNvZGVkLlxuICogQHJldHVybiB7T2JqZWN0fVxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmV4cG9ydCBjb25zdCBlbmNvZGVLZXlWYWx1ZXMgPSAodmFsdWVPYmplY3QpID0+IHtcbiAgbGV0IGVuY29kZWQgPSB7fVxuICBPYmplY3Qua2V5cyh2YWx1ZU9iamVjdCkuZm9yRWFjaCgoa2V5LCBpbmRleCkgPT4geyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gICAgZW5jb2RlZFtrZXldID0gZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlT2JqZWN0W2tleV0pXG4gIH0pXG4gIHJldHVybiBlbmNvZGVkXG59XG5cbi8qKlxuICogQ29uc3RydWN0IGVuZHBvaW50IHRvIHVzZSBmb3IgV2ViU29ja2V0IGNvbm5lY3Rpb24gYmFzZWQgb24gY29uZmlndXJhdGlvbiBvYmplY3QgYW5kIG9wdGlvbmFsIHBhcmFtcyB0byBhcHBlbmQgdG8gcXVlcnkuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAqICAgICAgICBUaGUgY29uZmlndXJhdGlvbiBvcHRpb25zIHByb3ZpZGVkIGluIGBpbml0KClgIG9mIFdlYlJUQyBiYXNlZCBwdWJsaXNoZXIgb3Igc3Vic2NyaWJlci5cbiAqIEBwYXJhbSB7T2JqZWN0fSBwYXJhbXNcbiAqICAgICAgICBUaGUgb3B0aW9uYWwgcGFyYW1zIHRvIGFwcGVuZCB0byB0aGUgZW5kcG9pbnQuIFVzZWQgYnkgc2VydmVyIGluIGNvbm5lY3Rpb24gcGFyc2UuXG4gKiBAcHJpdmF0ZVxuICovXG5leHBvcnQgY29uc3QgcnRjU29ja2V0RW5kcG9pbnRGcm9tT3B0aW9ucyA9IChvcHRpb25zLCBwYXJhbXMgPSB1bmRlZmluZWQpID0+IHtcbiAgY29uc3QgcHJvdG9jb2wgPSBvcHRpb25zLndzcHJvdG9jb2wgfHwgb3B0aW9ucy5wcm90b2NvbFxuICBjb25zdCBwb3J0ID0gb3B0aW9ucy53c3BvcnQgfHwgb3B0aW9ucy5wb3J0XG4gIGNvbnN0IGFwcEVuZHBvaW50ID0gb3B0aW9ucy5jb250ZXh0ID8gW29wdGlvbnMuYXBwLCBvcHRpb25zLmNvbnRleHRdLmpvaW4oJy8nKSA6IG9wdGlvbnMuYXBwXG4gIGxldCBlbmRwb2ludCA9IGAke3Byb3RvY29sfTovLyR7b3B0aW9ucy5ob3N0fToke3BvcnR9LyR7YXBwRW5kcG9pbnR9YFxuICBpZiAodHlwZW9mIG9wdGlvbnMuY29ubmVjdGlvblBhcmFtcyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBjb25zdCBlbmNvZGVkUGFyYW1zID0gZW5jb2RlS2V5VmFsdWVzKG9wdGlvbnMuY29ubmVjdGlvblBhcmFtcylcbiAgICBwYXJhbXMgPSBPYmplY3QuYXNzaWduKHBhcmFtcywgZW5jb2RlZFBhcmFtcylcbiAgfVxuICBpZiAodHlwZW9mIHBhcmFtcyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBsZXQga3YgPSBbXVxuICAgIE9iamVjdC5rZXlzKHBhcmFtcykuZm9yRWFjaCgoa2V5LCBpbmRleCkgPT4geyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gICAgICBrdi5wdXNoKFtrZXksIHBhcmFtc1trZXldXS5qb2luKCc9JykpXG4gICAgfSlcbiAgICBpZiAoa3YubGVuZ3RoID4gMCkge1xuICAgICAgZW5kcG9pbnQgKz0gJz8nICsgKGt2LmpvaW4oJyYnKSlcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZW5kcG9pbnRcbn1cblxuLyoqXG4gKiBDb25zdHJ1Y3QgZW5kcG9pbnQgdG8gdXNlIGZvciBXZWJTb2NrZXQgY29ubmVjdGlvbiBiYXNlZCBvbiBjb25maWd1cmF0aW9uIG9iamVjdCBhbmQgb3B0aW9uYWwgcGFyYW1zIHRvIGFwcGVuZCB0byBxdWVyeS5cbiAqIFRoaXMgYWxsb3dzIGZvciBzdWNoIHRoaW5ncyBhcyBhdXRoZW50aWNhdGlvbiBwcmlvciB0byByZXF1ZXN0IG9mIHBsYXliYWNrIG9mIEhMUyBmaWxlLlxuICogUmVxdWlyZXMgYSBgc29ja2V0UGFyYW1zYCBhdHRyaWJ1dGUgaW4gdGhlIGluaXQgY29uZmlndXJhdGlvbiB0aGF0IGRlc2NyaWJlIHRoZSBXZWJTb2NrZXQgZW5kcG9pbnQgdG8gbWFrZSB0aGUgcmVxdWVzdCBvbi5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICogICAgICAgIFRoZSBjb25maWd1cmF0aW9uIG9wdGlvbnMgcHJvdmlkZWQgaW4gYGluaXQoKWAgb2YgSExTIGJhc2VkIHN1YnNjcmliZXIuXG4gKiBAcGFyYW0ge09iamVjdH0gcGFyYW1zXG4gKiAgICAgICAgVGhlIG9wdGlvbmFsIHBhcmFtcyB0byBhcHBlbmQgdG8gdGhlIGVuZHBvaW50LiBVc2VkIGJ5IHNlcnZlciBpbiBjb25uZWN0aW9uIHBhcnNlLlxuICpcbiAqIEBleGFtcGxlXG4gKiAgdmFyIHN1YnNjcmliZXIgPSBuZXcgSExTdWJzY3JpYmVyKClcbiAqICBzdWJzY3JpYmVyLmluaXQoe1xuICogICAgcHJvdG9jb2w6ICdodHRwcycsXG4gKiAgICBob3N0OiAnbXljb21wYW55Lm9yZycsXG4gKiAgICBhcHA6ICdsaXZlJyxcbiAqICAgIHN0cmVhbU5hbWU6ICdteXN0cmVhbScsXG4gKiAgICBzb2NrZXRQYXJhbXM6IHtcbiAqICAgICAgcHJvdG9jb2w6ICd3c3MnLFxuICogICAgICBob3N0OiAnbXljb21wYW55Lm9yZycsXG4gKiAgICAgIGFwcDogJ2xpdmUnXG4gKiAgICB9LFxuICogICAgY29ubmVjdGlvblBhcmFtczoge1xuICogICAgICB1c2VyOiAnZm9vJyxcbiAqICAgICAgcGFzc3dvcmQ6ICdiYXInXG4gKiAgICB9XG4gKiAgfSlcbiAqIEBwcml2YXRlXG4gKi9cbmV4cG9ydCBjb25zdCBobHNTb2NrZXRFbmRwb2ludEZyb21PcHRpb25zID0gKG9wdGlvbnMsIHBhcmFtcyA9IHVuZGVmaW5lZCkgPT4ge1xuICBjb25zdCB7XG4gICAgc29ja2V0UGFyYW1zLFxuICAgIGNvbm5lY3Rpb25QYXJhbXNcbiAgfSA9IG9wdGlvbnNcbiAgY29uc3QgcHJvdG9jb2wgPSBzb2NrZXRQYXJhbXMucHJvdG9jb2xcbiAgY29uc3QgcG9ydCA9IHNvY2tldFBhcmFtcy5wb3J0IHx8IChwcm90b2NvbCA9PT0gJ3dzcycgPyA4MDgzIDogODA4MSlcbiAgbGV0IGVuZHBvaW50ID0gYCR7cHJvdG9jb2x9Oi8vJHtzb2NrZXRQYXJhbXMuaG9zdH06JHtwb3J0fS8ke3NvY2tldFBhcmFtcy5hcHB9YFxuICBpZiAoY29ubmVjdGlvblBhcmFtcykge1xuICAgIGNvbnN0IGVuY29kZWRQYXJhbXMgPSBlbmNvZGVLZXlWYWx1ZXMob3B0aW9ucy5jb25uZWN0aW9uUGFyYW1zKVxuICAgIHBhcmFtcyA9IE9iamVjdC5hc3NpZ24ocGFyYW1zLCBlbmNvZGVkUGFyYW1zKVxuICB9XG4gIGlmIChwYXJhbXMpIHtcbiAgICBsZXQga3YgPSBbXVxuICAgIE9iamVjdC5rZXlzKHBhcmFtcykuZm9yRWFjaCgoa2V5LCBpbmRleCkgPT4geyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gICAgICBrdi5wdXNoKFtrZXksIHBhcmFtc1trZXldXS5qb2luKCc9JykpXG4gICAgfSlcbiAgICBpZiAoa3YubGVuZ3RoID4gMCkge1xuICAgICAgZW5kcG9pbnQgKz0gJz8nICsgKGt2LmpvaW4oJyYnKSlcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZW5kcG9pbnRcbn1cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9qcy91dGlsL3VybC1lbmRwb2ludC5qcyIsIid1c2Ugc3RyaWN0J1xuXG5pbXBvcnQgZW52aXJvbm1lbnQgZnJvbSAnLi4vZW52L2Jyb3dzZXInXG5pbXBvcnQgeyBkZWJ1ZywgZXJyb3IgfSBmcm9tICcuLi9sb2cnXG5cbmNvbnN0IE5BTUUgPSAnUjVQcm9QdWJsaXNoVmlldydcbmNvbnN0IHB1Ymxpc2hlcklkID0gJ3JlZDVwcm8tcHVibGlzaGVyJ1xuXG4vKipcbiAqIEJyaWRnZSBiZXR3ZWVuIERPTSBFbGVtZW50IHZpZXcgYW5kIFB1Ymxpc2hlciBpbXBsZW1lbnRhdGlvbi5cbiAqIFN0aWxsIHVzZWQsIGJ1dCBpbnRlcm5hbGl6ZWQgYXMgb2YgNC4wLjAuIFVwIGZvciBkZXByZWNhdGlvbiwgdXAgZm9yIGRpc2N1c3Npb24uXG4gKlxuICogQHByaXZhdGVcbiAqL1xuY2xhc3MgUHVibGlzaFZpZXcge1xuXG4gIC8qKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gZWxlbWVudElkXG4gICAqICAgICAgICBUaGUgZWxlbWVudCBgaWRgIHRvIHVzZSBmb3IgcGxheWJhY2sgZGlzcGxheS5cbiAgICogQHByaXZhdGVcbiAgICovXG4gIGNvbnN0cnVjdG9yIChlbGVtZW50SWQgPSBwdWJsaXNoZXJJZCkge1xuICAgIHRyeSB7XG4gICAgICB0aGlzLl90YXJnZXRFbGVtZW50ID0gZW52aXJvbm1lbnQucmVzb2x2ZUVsZW1lbnQoZWxlbWVudElkKVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGVycm9yKE5BTUUsIGBDb3VsZCBub3QgaW5zdGFudGlhdGUgYSBuZXcgaW5zdGFuY2Ugb2YgUmVkNVByb1B1Ymxpc2hlci4gUmVhc29uOiAke2UubWVzc2FnZX1gKVxuICAgICAgdGhyb3cgZVxuICAgIH1cbiAgfVxuXG4gIGF0dGFjaFB1Ymxpc2hlciAocHVibGlzaGVyKSB7XG4gICAgZGVidWcoTkFNRSwgJ1thdHRhY2hwdWJsaXNoZXJdJylcbiAgICBwdWJsaXNoZXIuc2V0Vmlldyh0aGlzLCBlbnZpcm9ubWVudC5nZXRFbGVtZW50SWQodGhpcy5fdGFyZ2V0RWxlbWVudCkpXG4gIH1cblxuICBwcmV2aWV3IChtZWRpYVN0cmVhbSkge1xuICAgIGxldCBhdXRvcGxheSA9IHRoaXMuaXNBdXRvcGxheVxuICAgIGRlYnVnKE5BTUUsIGBbcHJldmlld106IGF1dG9wbGF5KCR7YXV0b3BsYXl9KWApXG4gICAgZW52aXJvbm1lbnQuc2V0VmlkZW9Tb3VyY2UodGhpcy5fdGFyZ2V0RWxlbWVudCwgbWVkaWFTdHJlYW0sIGF1dG9wbGF5KVxuICB9XG5cbiAgZ2V0IGlzQXV0b3BsYXkgKCkge1xuICAgIHJldHVybiBlbnZpcm9ubWVudC5oYXNBdHRyaWJ1dGVEZWZpbmVkKHRoaXMuX3RhcmdldEVsZW1lbnQsICdhdXRvcGxheScpXG4gIH1cblxuICBnZXQgdmlldyAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3RhcmdldEVsZW1lbnRcbiAgfVxuXG59XG5cbmV4cG9ydCBkZWZhdWx0IFB1Ymxpc2hWaWV3XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvanMvdmlldy9wdWJsaXNoLmpzIiwibW9kdWxlLmV4cG9ydHMgPSB7IFwiZGVmYXVsdFwiOiByZXF1aXJlKFwiY29yZS1qcy9saWJyYXJ5L2ZuL29iamVjdC9rZXlzXCIpLCBfX2VzTW9kdWxlOiB0cnVlIH07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9vYmplY3Qva2V5cy5qc1xuLy8gbW9kdWxlIGlkID0gNjBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSB7IFwiZGVmYXVsdFwiOiByZXF1aXJlKFwiY29yZS1qcy9saWJyYXJ5L2ZuL3Byb21pc2VcIiksIF9fZXNNb2R1bGU6IHRydWUgfTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vYmFiZWwtcnVudGltZS9jb3JlLWpzL3Byb21pc2UuanNcbi8vIG1vZHVsZSBpZCA9IDYxXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIlwidXNlIHN0cmljdFwiO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG52YXIgX2l0ZXJhdG9yID0gcmVxdWlyZShcIi4uL2NvcmUtanMvc3ltYm9sL2l0ZXJhdG9yXCIpO1xuXG52YXIgX2l0ZXJhdG9yMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2l0ZXJhdG9yKTtcblxudmFyIF9zeW1ib2wgPSByZXF1aXJlKFwiLi4vY29yZS1qcy9zeW1ib2xcIik7XG5cbnZhciBfc3ltYm9sMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3N5bWJvbCk7XG5cbnZhciBfdHlwZW9mID0gdHlwZW9mIF9zeW1ib2wyLmRlZmF1bHQgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgX2l0ZXJhdG9yMi5kZWZhdWx0ID09PSBcInN5bWJvbFwiID8gZnVuY3Rpb24gKG9iaikgeyByZXR1cm4gdHlwZW9mIG9iajsgfSA6IGZ1bmN0aW9uIChvYmopIHsgcmV0dXJuIG9iaiAmJiB0eXBlb2YgX3N5bWJvbDIuZGVmYXVsdCA9PT0gXCJmdW5jdGlvblwiICYmIG9iai5jb25zdHJ1Y3RvciA9PT0gX3N5bWJvbDIuZGVmYXVsdCAmJiBvYmogIT09IF9zeW1ib2wyLmRlZmF1bHQucHJvdG90eXBlID8gXCJzeW1ib2xcIiA6IHR5cGVvZiBvYmo7IH07XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmV4cG9ydHMuZGVmYXVsdCA9IHR5cGVvZiBfc3ltYm9sMi5kZWZhdWx0ID09PSBcImZ1bmN0aW9uXCIgJiYgX3R5cGVvZihfaXRlcmF0b3IyLmRlZmF1bHQpID09PSBcInN5bWJvbFwiID8gZnVuY3Rpb24gKG9iaikge1xuICByZXR1cm4gdHlwZW9mIG9iaiA9PT0gXCJ1bmRlZmluZWRcIiA/IFwidW5kZWZpbmVkXCIgOiBfdHlwZW9mKG9iaik7XG59IDogZnVuY3Rpb24gKG9iaikge1xuICByZXR1cm4gb2JqICYmIHR5cGVvZiBfc3ltYm9sMi5kZWZhdWx0ID09PSBcImZ1bmN0aW9uXCIgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBfc3ltYm9sMi5kZWZhdWx0ICYmIG9iaiAhPT0gX3N5bWJvbDIuZGVmYXVsdC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogdHlwZW9mIG9iaiA9PT0gXCJ1bmRlZmluZWRcIiA/IFwidW5kZWZpbmVkXCIgOiBfdHlwZW9mKG9iaik7XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9iYWJlbC1ydW50aW1lL2hlbHBlcnMvdHlwZW9mLmpzXG4vLyBtb2R1bGUgaWQgPSA2MlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGl0KXtcbiAgaWYodHlwZW9mIGl0ICE9ICdmdW5jdGlvbicpdGhyb3cgVHlwZUVycm9yKGl0ICsgJyBpcyBub3QgYSBmdW5jdGlvbiEnKTtcbiAgcmV0dXJuIGl0O1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2EtZnVuY3Rpb24uanNcbi8vIG1vZHVsZSBpZCA9IDYzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIDAgLT4gQXJyYXkjZm9yRWFjaFxuLy8gMSAtPiBBcnJheSNtYXBcbi8vIDIgLT4gQXJyYXkjZmlsdGVyXG4vLyAzIC0+IEFycmF5I3NvbWVcbi8vIDQgLT4gQXJyYXkjZXZlcnlcbi8vIDUgLT4gQXJyYXkjZmluZFxuLy8gNiAtPiBBcnJheSNmaW5kSW5kZXhcbnZhciBjdHggICAgICA9IHJlcXVpcmUoJy4vX2N0eCcpXG4gICwgSU9iamVjdCAgPSByZXF1aXJlKCcuL19pb2JqZWN0JylcbiAgLCB0b09iamVjdCA9IHJlcXVpcmUoJy4vX3RvLW9iamVjdCcpXG4gICwgdG9MZW5ndGggPSByZXF1aXJlKCcuL190by1sZW5ndGgnKVxuICAsIGFzYyAgICAgID0gcmVxdWlyZSgnLi9fYXJyYXktc3BlY2llcy1jcmVhdGUnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oVFlQRSwgJGNyZWF0ZSl7XG4gIHZhciBJU19NQVAgICAgICAgID0gVFlQRSA9PSAxXG4gICAgLCBJU19GSUxURVIgICAgID0gVFlQRSA9PSAyXG4gICAgLCBJU19TT01FICAgICAgID0gVFlQRSA9PSAzXG4gICAgLCBJU19FVkVSWSAgICAgID0gVFlQRSA9PSA0XG4gICAgLCBJU19GSU5EX0lOREVYID0gVFlQRSA9PSA2XG4gICAgLCBOT19IT0xFUyAgICAgID0gVFlQRSA9PSA1IHx8IElTX0ZJTkRfSU5ERVhcbiAgICAsIGNyZWF0ZSAgICAgICAgPSAkY3JlYXRlIHx8IGFzYztcbiAgcmV0dXJuIGZ1bmN0aW9uKCR0aGlzLCBjYWxsYmFja2ZuLCB0aGF0KXtcbiAgICB2YXIgTyAgICAgID0gdG9PYmplY3QoJHRoaXMpXG4gICAgICAsIHNlbGYgICA9IElPYmplY3QoTylcbiAgICAgICwgZiAgICAgID0gY3R4KGNhbGxiYWNrZm4sIHRoYXQsIDMpXG4gICAgICAsIGxlbmd0aCA9IHRvTGVuZ3RoKHNlbGYubGVuZ3RoKVxuICAgICAgLCBpbmRleCAgPSAwXG4gICAgICAsIHJlc3VsdCA9IElTX01BUCA/IGNyZWF0ZSgkdGhpcywgbGVuZ3RoKSA6IElTX0ZJTFRFUiA/IGNyZWF0ZSgkdGhpcywgMCkgOiB1bmRlZmluZWRcbiAgICAgICwgdmFsLCByZXM7XG4gICAgZm9yKDtsZW5ndGggPiBpbmRleDsgaW5kZXgrKylpZihOT19IT0xFUyB8fCBpbmRleCBpbiBzZWxmKXtcbiAgICAgIHZhbCA9IHNlbGZbaW5kZXhdO1xuICAgICAgcmVzID0gZih2YWwsIGluZGV4LCBPKTtcbiAgICAgIGlmKFRZUEUpe1xuICAgICAgICBpZihJU19NQVApcmVzdWx0W2luZGV4XSA9IHJlczsgICAgICAgICAgICAvLyBtYXBcbiAgICAgICAgZWxzZSBpZihyZXMpc3dpdGNoKFRZUEUpe1xuICAgICAgICAgIGNhc2UgMzogcmV0dXJuIHRydWU7ICAgICAgICAgICAgICAgICAgICAvLyBzb21lXG4gICAgICAgICAgY2FzZSA1OiByZXR1cm4gdmFsOyAgICAgICAgICAgICAgICAgICAgIC8vIGZpbmRcbiAgICAgICAgICBjYXNlIDY6IHJldHVybiBpbmRleDsgICAgICAgICAgICAgICAgICAgLy8gZmluZEluZGV4XG4gICAgICAgICAgY2FzZSAyOiByZXN1bHQucHVzaCh2YWwpOyAgICAgICAgICAgICAgIC8vIGZpbHRlclxuICAgICAgICB9IGVsc2UgaWYoSVNfRVZFUlkpcmV0dXJuIGZhbHNlOyAgICAgICAgICAvLyBldmVyeVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gSVNfRklORF9JTkRFWCA/IC0xIDogSVNfU09NRSB8fCBJU19FVkVSWSA/IElTX0VWRVJZIDogcmVzdWx0O1xuICB9O1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2FycmF5LW1ldGhvZHMuanNcbi8vIG1vZHVsZSBpZCA9IDY0XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIid1c2Ugc3RyaWN0JztcbnZhciBnbG9iYWwgICAgICAgICA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpXG4gICwgJGV4cG9ydCAgICAgICAgPSByZXF1aXJlKCcuL19leHBvcnQnKVxuICAsIG1ldGEgICAgICAgICAgID0gcmVxdWlyZSgnLi9fbWV0YScpXG4gICwgZmFpbHMgICAgICAgICAgPSByZXF1aXJlKCcuL19mYWlscycpXG4gICwgaGlkZSAgICAgICAgICAgPSByZXF1aXJlKCcuL19oaWRlJylcbiAgLCByZWRlZmluZUFsbCAgICA9IHJlcXVpcmUoJy4vX3JlZGVmaW5lLWFsbCcpXG4gICwgZm9yT2YgICAgICAgICAgPSByZXF1aXJlKCcuL19mb3Itb2YnKVxuICAsIGFuSW5zdGFuY2UgICAgID0gcmVxdWlyZSgnLi9fYW4taW5zdGFuY2UnKVxuICAsIGlzT2JqZWN0ICAgICAgID0gcmVxdWlyZSgnLi9faXMtb2JqZWN0JylcbiAgLCBzZXRUb1N0cmluZ1RhZyA9IHJlcXVpcmUoJy4vX3NldC10by1zdHJpbmctdGFnJylcbiAgLCBkUCAgICAgICAgICAgICA9IHJlcXVpcmUoJy4vX29iamVjdC1kcCcpLmZcbiAgLCBlYWNoICAgICAgICAgICA9IHJlcXVpcmUoJy4vX2FycmF5LW1ldGhvZHMnKSgwKVxuICAsIERFU0NSSVBUT1JTICAgID0gcmVxdWlyZSgnLi9fZGVzY3JpcHRvcnMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihOQU1FLCB3cmFwcGVyLCBtZXRob2RzLCBjb21tb24sIElTX01BUCwgSVNfV0VBSyl7XG4gIHZhciBCYXNlICA9IGdsb2JhbFtOQU1FXVxuICAgICwgQyAgICAgPSBCYXNlXG4gICAgLCBBRERFUiA9IElTX01BUCA/ICdzZXQnIDogJ2FkZCdcbiAgICAsIHByb3RvID0gQyAmJiBDLnByb3RvdHlwZVxuICAgICwgTyAgICAgPSB7fTtcbiAgaWYoIURFU0NSSVBUT1JTIHx8IHR5cGVvZiBDICE9ICdmdW5jdGlvbicgfHwgIShJU19XRUFLIHx8IHByb3RvLmZvckVhY2ggJiYgIWZhaWxzKGZ1bmN0aW9uKCl7XG4gICAgbmV3IEMoKS5lbnRyaWVzKCkubmV4dCgpO1xuICB9KSkpe1xuICAgIC8vIGNyZWF0ZSBjb2xsZWN0aW9uIGNvbnN0cnVjdG9yXG4gICAgQyA9IGNvbW1vbi5nZXRDb25zdHJ1Y3Rvcih3cmFwcGVyLCBOQU1FLCBJU19NQVAsIEFEREVSKTtcbiAgICByZWRlZmluZUFsbChDLnByb3RvdHlwZSwgbWV0aG9kcyk7XG4gICAgbWV0YS5ORUVEID0gdHJ1ZTtcbiAgfSBlbHNlIHtcbiAgICBDID0gd3JhcHBlcihmdW5jdGlvbih0YXJnZXQsIGl0ZXJhYmxlKXtcbiAgICAgIGFuSW5zdGFuY2UodGFyZ2V0LCBDLCBOQU1FLCAnX2MnKTtcbiAgICAgIHRhcmdldC5fYyA9IG5ldyBCYXNlO1xuICAgICAgaWYoaXRlcmFibGUgIT0gdW5kZWZpbmVkKWZvck9mKGl0ZXJhYmxlLCBJU19NQVAsIHRhcmdldFtBRERFUl0sIHRhcmdldCk7XG4gICAgfSk7XG4gICAgZWFjaCgnYWRkLGNsZWFyLGRlbGV0ZSxmb3JFYWNoLGdldCxoYXMsc2V0LGtleXMsdmFsdWVzLGVudHJpZXMsdG9KU09OJy5zcGxpdCgnLCcpLGZ1bmN0aW9uKEtFWSl7XG4gICAgICB2YXIgSVNfQURERVIgPSBLRVkgPT0gJ2FkZCcgfHwgS0VZID09ICdzZXQnO1xuICAgICAgaWYoS0VZIGluIHByb3RvICYmICEoSVNfV0VBSyAmJiBLRVkgPT0gJ2NsZWFyJykpaGlkZShDLnByb3RvdHlwZSwgS0VZLCBmdW5jdGlvbihhLCBiKXtcbiAgICAgICAgYW5JbnN0YW5jZSh0aGlzLCBDLCBLRVkpO1xuICAgICAgICBpZighSVNfQURERVIgJiYgSVNfV0VBSyAmJiAhaXNPYmplY3QoYSkpcmV0dXJuIEtFWSA9PSAnZ2V0JyA/IHVuZGVmaW5lZCA6IGZhbHNlO1xuICAgICAgICB2YXIgcmVzdWx0ID0gdGhpcy5fY1tLRVldKGEgPT09IDAgPyAwIDogYSwgYik7XG4gICAgICAgIHJldHVybiBJU19BRERFUiA/IHRoaXMgOiByZXN1bHQ7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICBpZignc2l6ZScgaW4gcHJvdG8pZFAoQy5wcm90b3R5cGUsICdzaXplJywge1xuICAgICAgZ2V0OiBmdW5jdGlvbigpe1xuICAgICAgICByZXR1cm4gdGhpcy5fYy5zaXplO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgc2V0VG9TdHJpbmdUYWcoQywgTkFNRSk7XG5cbiAgT1tOQU1FXSA9IEM7XG4gICRleHBvcnQoJGV4cG9ydC5HICsgJGV4cG9ydC5XICsgJGV4cG9ydC5GLCBPKTtcblxuICBpZighSVNfV0VBSyljb21tb24uc2V0U3Ryb25nKEMsIE5BTUUsIElTX01BUCk7XG5cbiAgcmV0dXJuIEM7XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fY29sbGVjdGlvbi5qc1xuLy8gbW9kdWxlIGlkID0gNjVcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwidmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9faXMtb2JqZWN0JylcbiAgLCBkb2N1bWVudCA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpLmRvY3VtZW50XG4gIC8vIGluIG9sZCBJRSB0eXBlb2YgZG9jdW1lbnQuY3JlYXRlRWxlbWVudCBpcyAnb2JqZWN0J1xuICAsIGlzID0gaXNPYmplY3QoZG9jdW1lbnQpICYmIGlzT2JqZWN0KGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdCl7XG4gIHJldHVybiBpcyA/IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoaXQpIDoge307XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fZG9tLWNyZWF0ZS5qc1xuLy8gbW9kdWxlIGlkID0gNjZcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8gSUUgOC0gZG9uJ3QgZW51bSBidWcga2V5c1xubW9kdWxlLmV4cG9ydHMgPSAoXG4gICdjb25zdHJ1Y3RvcixoYXNPd25Qcm9wZXJ0eSxpc1Byb3RvdHlwZU9mLHByb3BlcnR5SXNFbnVtZXJhYmxlLHRvTG9jYWxlU3RyaW5nLHRvU3RyaW5nLHZhbHVlT2YnXG4pLnNwbGl0KCcsJyk7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19lbnVtLWJ1Zy1rZXlzLmpzXG4vLyBtb2R1bGUgaWQgPSA2N1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyBmYWxsYmFjayBmb3Igbm9uLWFycmF5LWxpa2UgRVMzIGFuZCBub24tZW51bWVyYWJsZSBvbGQgVjggc3RyaW5nc1xudmFyIGNvZiA9IHJlcXVpcmUoJy4vX2NvZicpO1xubW9kdWxlLmV4cG9ydHMgPSBPYmplY3QoJ3onKS5wcm9wZXJ0eUlzRW51bWVyYWJsZSgwKSA/IE9iamVjdCA6IGZ1bmN0aW9uKGl0KXtcbiAgcmV0dXJuIGNvZihpdCkgPT0gJ1N0cmluZycgPyBpdC5zcGxpdCgnJykgOiBPYmplY3QoaXQpO1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2lvYmplY3QuanNcbi8vIG1vZHVsZSBpZCA9IDY4XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIid1c2Ugc3RyaWN0JztcbnZhciBMSUJSQVJZICAgICAgICA9IHJlcXVpcmUoJy4vX2xpYnJhcnknKVxuICAsICRleHBvcnQgICAgICAgID0gcmVxdWlyZSgnLi9fZXhwb3J0JylcbiAgLCByZWRlZmluZSAgICAgICA9IHJlcXVpcmUoJy4vX3JlZGVmaW5lJylcbiAgLCBoaWRlICAgICAgICAgICA9IHJlcXVpcmUoJy4vX2hpZGUnKVxuICAsIGhhcyAgICAgICAgICAgID0gcmVxdWlyZSgnLi9faGFzJylcbiAgLCBJdGVyYXRvcnMgICAgICA9IHJlcXVpcmUoJy4vX2l0ZXJhdG9ycycpXG4gICwgJGl0ZXJDcmVhdGUgICAgPSByZXF1aXJlKCcuL19pdGVyLWNyZWF0ZScpXG4gICwgc2V0VG9TdHJpbmdUYWcgPSByZXF1aXJlKCcuL19zZXQtdG8tc3RyaW5nLXRhZycpXG4gICwgZ2V0UHJvdG90eXBlT2YgPSByZXF1aXJlKCcuL19vYmplY3QtZ3BvJylcbiAgLCBJVEVSQVRPUiAgICAgICA9IHJlcXVpcmUoJy4vX3drcycpKCdpdGVyYXRvcicpXG4gICwgQlVHR1kgICAgICAgICAgPSAhKFtdLmtleXMgJiYgJ25leHQnIGluIFtdLmtleXMoKSkgLy8gU2FmYXJpIGhhcyBidWdneSBpdGVyYXRvcnMgdy9vIGBuZXh0YFxuICAsIEZGX0lURVJBVE9SICAgID0gJ0BAaXRlcmF0b3InXG4gICwgS0VZUyAgICAgICAgICAgPSAna2V5cydcbiAgLCBWQUxVRVMgICAgICAgICA9ICd2YWx1ZXMnO1xuXG52YXIgcmV0dXJuVGhpcyA9IGZ1bmN0aW9uKCl7IHJldHVybiB0aGlzOyB9O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKEJhc2UsIE5BTUUsIENvbnN0cnVjdG9yLCBuZXh0LCBERUZBVUxULCBJU19TRVQsIEZPUkNFRCl7XG4gICRpdGVyQ3JlYXRlKENvbnN0cnVjdG9yLCBOQU1FLCBuZXh0KTtcbiAgdmFyIGdldE1ldGhvZCA9IGZ1bmN0aW9uKGtpbmQpe1xuICAgIGlmKCFCVUdHWSAmJiBraW5kIGluIHByb3RvKXJldHVybiBwcm90b1traW5kXTtcbiAgICBzd2l0Y2goa2luZCl7XG4gICAgICBjYXNlIEtFWVM6IHJldHVybiBmdW5jdGlvbiBrZXlzKCl7IHJldHVybiBuZXcgQ29uc3RydWN0b3IodGhpcywga2luZCk7IH07XG4gICAgICBjYXNlIFZBTFVFUzogcmV0dXJuIGZ1bmN0aW9uIHZhbHVlcygpeyByZXR1cm4gbmV3IENvbnN0cnVjdG9yKHRoaXMsIGtpbmQpOyB9O1xuICAgIH0gcmV0dXJuIGZ1bmN0aW9uIGVudHJpZXMoKXsgcmV0dXJuIG5ldyBDb25zdHJ1Y3Rvcih0aGlzLCBraW5kKTsgfTtcbiAgfTtcbiAgdmFyIFRBRyAgICAgICAgPSBOQU1FICsgJyBJdGVyYXRvcidcbiAgICAsIERFRl9WQUxVRVMgPSBERUZBVUxUID09IFZBTFVFU1xuICAgICwgVkFMVUVTX0JVRyA9IGZhbHNlXG4gICAgLCBwcm90byAgICAgID0gQmFzZS5wcm90b3R5cGVcbiAgICAsICRuYXRpdmUgICAgPSBwcm90b1tJVEVSQVRPUl0gfHwgcHJvdG9bRkZfSVRFUkFUT1JdIHx8IERFRkFVTFQgJiYgcHJvdG9bREVGQVVMVF1cbiAgICAsICRkZWZhdWx0ICAgPSAkbmF0aXZlIHx8IGdldE1ldGhvZChERUZBVUxUKVxuICAgICwgJGVudHJpZXMgICA9IERFRkFVTFQgPyAhREVGX1ZBTFVFUyA/ICRkZWZhdWx0IDogZ2V0TWV0aG9kKCdlbnRyaWVzJykgOiB1bmRlZmluZWRcbiAgICAsICRhbnlOYXRpdmUgPSBOQU1FID09ICdBcnJheScgPyBwcm90by5lbnRyaWVzIHx8ICRuYXRpdmUgOiAkbmF0aXZlXG4gICAgLCBtZXRob2RzLCBrZXksIEl0ZXJhdG9yUHJvdG90eXBlO1xuICAvLyBGaXggbmF0aXZlXG4gIGlmKCRhbnlOYXRpdmUpe1xuICAgIEl0ZXJhdG9yUHJvdG90eXBlID0gZ2V0UHJvdG90eXBlT2YoJGFueU5hdGl2ZS5jYWxsKG5ldyBCYXNlKSk7XG4gICAgaWYoSXRlcmF0b3JQcm90b3R5cGUgIT09IE9iamVjdC5wcm90b3R5cGUpe1xuICAgICAgLy8gU2V0IEBAdG9TdHJpbmdUYWcgdG8gbmF0aXZlIGl0ZXJhdG9yc1xuICAgICAgc2V0VG9TdHJpbmdUYWcoSXRlcmF0b3JQcm90b3R5cGUsIFRBRywgdHJ1ZSk7XG4gICAgICAvLyBmaXggZm9yIHNvbWUgb2xkIGVuZ2luZXNcbiAgICAgIGlmKCFMSUJSQVJZICYmICFoYXMoSXRlcmF0b3JQcm90b3R5cGUsIElURVJBVE9SKSloaWRlKEl0ZXJhdG9yUHJvdG90eXBlLCBJVEVSQVRPUiwgcmV0dXJuVGhpcyk7XG4gICAgfVxuICB9XG4gIC8vIGZpeCBBcnJheSN7dmFsdWVzLCBAQGl0ZXJhdG9yfS5uYW1lIGluIFY4IC8gRkZcbiAgaWYoREVGX1ZBTFVFUyAmJiAkbmF0aXZlICYmICRuYXRpdmUubmFtZSAhPT0gVkFMVUVTKXtcbiAgICBWQUxVRVNfQlVHID0gdHJ1ZTtcbiAgICAkZGVmYXVsdCA9IGZ1bmN0aW9uIHZhbHVlcygpeyByZXR1cm4gJG5hdGl2ZS5jYWxsKHRoaXMpOyB9O1xuICB9XG4gIC8vIERlZmluZSBpdGVyYXRvclxuICBpZigoIUxJQlJBUlkgfHwgRk9SQ0VEKSAmJiAoQlVHR1kgfHwgVkFMVUVTX0JVRyB8fCAhcHJvdG9bSVRFUkFUT1JdKSl7XG4gICAgaGlkZShwcm90bywgSVRFUkFUT1IsICRkZWZhdWx0KTtcbiAgfVxuICAvLyBQbHVnIGZvciBsaWJyYXJ5XG4gIEl0ZXJhdG9yc1tOQU1FXSA9ICRkZWZhdWx0O1xuICBJdGVyYXRvcnNbVEFHXSAgPSByZXR1cm5UaGlzO1xuICBpZihERUZBVUxUKXtcbiAgICBtZXRob2RzID0ge1xuICAgICAgdmFsdWVzOiAgREVGX1ZBTFVFUyA/ICRkZWZhdWx0IDogZ2V0TWV0aG9kKFZBTFVFUyksXG4gICAgICBrZXlzOiAgICBJU19TRVQgICAgID8gJGRlZmF1bHQgOiBnZXRNZXRob2QoS0VZUyksXG4gICAgICBlbnRyaWVzOiAkZW50cmllc1xuICAgIH07XG4gICAgaWYoRk9SQ0VEKWZvcihrZXkgaW4gbWV0aG9kcyl7XG4gICAgICBpZighKGtleSBpbiBwcm90bykpcmVkZWZpbmUocHJvdG8sIGtleSwgbWV0aG9kc1trZXldKTtcbiAgICB9IGVsc2UgJGV4cG9ydCgkZXhwb3J0LlAgKyAkZXhwb3J0LkYgKiAoQlVHR1kgfHwgVkFMVUVTX0JVRyksIE5BTUUsIG1ldGhvZHMpO1xuICB9XG4gIHJldHVybiBtZXRob2RzO1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2l0ZXItZGVmaW5lLmpzXG4vLyBtb2R1bGUgaWQgPSA2OVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJ2YXIgcElFICAgICAgICAgICAgPSByZXF1aXJlKCcuL19vYmplY3QtcGllJylcbiAgLCBjcmVhdGVEZXNjICAgICA9IHJlcXVpcmUoJy4vX3Byb3BlcnR5LWRlc2MnKVxuICAsIHRvSU9iamVjdCAgICAgID0gcmVxdWlyZSgnLi9fdG8taW9iamVjdCcpXG4gICwgdG9QcmltaXRpdmUgICAgPSByZXF1aXJlKCcuL190by1wcmltaXRpdmUnKVxuICAsIGhhcyAgICAgICAgICAgID0gcmVxdWlyZSgnLi9faGFzJylcbiAgLCBJRThfRE9NX0RFRklORSA9IHJlcXVpcmUoJy4vX2llOC1kb20tZGVmaW5lJylcbiAgLCBnT1BEICAgICAgICAgICA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3I7XG5cbmV4cG9ydHMuZiA9IHJlcXVpcmUoJy4vX2Rlc2NyaXB0b3JzJykgPyBnT1BEIDogZnVuY3Rpb24gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKE8sIFApe1xuICBPID0gdG9JT2JqZWN0KE8pO1xuICBQID0gdG9QcmltaXRpdmUoUCwgdHJ1ZSk7XG4gIGlmKElFOF9ET01fREVGSU5FKXRyeSB7XG4gICAgcmV0dXJuIGdPUEQoTywgUCk7XG4gIH0gY2F0Y2goZSl7IC8qIGVtcHR5ICovIH1cbiAgaWYoaGFzKE8sIFApKXJldHVybiBjcmVhdGVEZXNjKCFwSUUuZi5jYWxsKE8sIFApLCBPW1BdKTtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19vYmplY3QtZ29wZC5qc1xuLy8gbW9kdWxlIGlkID0gNzBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiZXhwb3J0cy5mID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scztcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX29iamVjdC1nb3BzLmpzXG4vLyBtb2R1bGUgaWQgPSA3MVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vX2hpZGUnKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3JlZGVmaW5lLmpzXG4vLyBtb2R1bGUgaWQgPSA3MlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJ2YXIgc2hhcmVkID0gcmVxdWlyZSgnLi9fc2hhcmVkJykoJ2tleXMnKVxuICAsIHVpZCAgICA9IHJlcXVpcmUoJy4vX3VpZCcpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihrZXkpe1xuICByZXR1cm4gc2hhcmVkW2tleV0gfHwgKHNoYXJlZFtrZXldID0gdWlkKGtleSkpO1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3NoYXJlZC1rZXkuanNcbi8vIG1vZHVsZSBpZCA9IDczXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsInZhciBnbG9iYWwgPSByZXF1aXJlKCcuL19nbG9iYWwnKVxuICAsIFNIQVJFRCA9ICdfX2NvcmUtanNfc2hhcmVkX18nXG4gICwgc3RvcmUgID0gZ2xvYmFsW1NIQVJFRF0gfHwgKGdsb2JhbFtTSEFSRURdID0ge30pO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihrZXkpe1xuICByZXR1cm4gc3RvcmVba2V5XSB8fCAoc3RvcmVba2V5XSA9IHt9KTtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19zaGFyZWQuanNcbi8vIG1vZHVsZSBpZCA9IDc0XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIDcuMS40IFRvSW50ZWdlclxudmFyIGNlaWwgID0gTWF0aC5jZWlsXG4gICwgZmxvb3IgPSBNYXRoLmZsb29yO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdCl7XG4gIHJldHVybiBpc05hTihpdCA9ICtpdCkgPyAwIDogKGl0ID4gMCA/IGZsb29yIDogY2VpbCkoaXQpO1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3RvLWludGVnZXIuanNcbi8vIG1vZHVsZSBpZCA9IDc1XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIDcuMS4xIFRvUHJpbWl0aXZlKGlucHV0IFssIFByZWZlcnJlZFR5cGVdKVxudmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9faXMtb2JqZWN0Jyk7XG4vLyBpbnN0ZWFkIG9mIHRoZSBFUzYgc3BlYyB2ZXJzaW9uLCB3ZSBkaWRuJ3QgaW1wbGVtZW50IEBAdG9QcmltaXRpdmUgY2FzZVxuLy8gYW5kIHRoZSBzZWNvbmQgYXJndW1lbnQgLSBmbGFnIC0gcHJlZmVycmVkIHR5cGUgaXMgYSBzdHJpbmdcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaXQsIFMpe1xuICBpZighaXNPYmplY3QoaXQpKXJldHVybiBpdDtcbiAgdmFyIGZuLCB2YWw7XG4gIGlmKFMgJiYgdHlwZW9mIChmbiA9IGl0LnRvU3RyaW5nKSA9PSAnZnVuY3Rpb24nICYmICFpc09iamVjdCh2YWwgPSBmbi5jYWxsKGl0KSkpcmV0dXJuIHZhbDtcbiAgaWYodHlwZW9mIChmbiA9IGl0LnZhbHVlT2YpID09ICdmdW5jdGlvbicgJiYgIWlzT2JqZWN0KHZhbCA9IGZuLmNhbGwoaXQpKSlyZXR1cm4gdmFsO1xuICBpZighUyAmJiB0eXBlb2YgKGZuID0gaXQudG9TdHJpbmcpID09ICdmdW5jdGlvbicgJiYgIWlzT2JqZWN0KHZhbCA9IGZuLmNhbGwoaXQpKSlyZXR1cm4gdmFsO1xuICB0aHJvdyBUeXBlRXJyb3IoXCJDYW4ndCBjb252ZXJ0IG9iamVjdCB0byBwcmltaXRpdmUgdmFsdWVcIik7XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fdG8tcHJpbWl0aXZlLmpzXG4vLyBtb2R1bGUgaWQgPSA3NlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJ2YXIgZ2xvYmFsICAgICAgICAgPSByZXF1aXJlKCcuL19nbG9iYWwnKVxuICAsIGNvcmUgICAgICAgICAgID0gcmVxdWlyZSgnLi9fY29yZScpXG4gICwgTElCUkFSWSAgICAgICAgPSByZXF1aXJlKCcuL19saWJyYXJ5JylcbiAgLCB3a3NFeHQgICAgICAgICA9IHJlcXVpcmUoJy4vX3drcy1leHQnKVxuICAsIGRlZmluZVByb3BlcnR5ID0gcmVxdWlyZSgnLi9fb2JqZWN0LWRwJykuZjtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24obmFtZSl7XG4gIHZhciAkU3ltYm9sID0gY29yZS5TeW1ib2wgfHwgKGNvcmUuU3ltYm9sID0gTElCUkFSWSA/IHt9IDogZ2xvYmFsLlN5bWJvbCB8fCB7fSk7XG4gIGlmKG5hbWUuY2hhckF0KDApICE9ICdfJyAmJiAhKG5hbWUgaW4gJFN5bWJvbCkpZGVmaW5lUHJvcGVydHkoJFN5bWJvbCwgbmFtZSwge3ZhbHVlOiB3a3NFeHQuZihuYW1lKX0pO1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3drcy1kZWZpbmUuanNcbi8vIG1vZHVsZSBpZCA9IDc3XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsImV4cG9ydHMuZiA9IHJlcXVpcmUoJy4vX3drcycpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fd2tzLWV4dC5qc1xuLy8gbW9kdWxlIGlkID0gNzhcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwidmFyIGNsYXNzb2YgICA9IHJlcXVpcmUoJy4vX2NsYXNzb2YnKVxuICAsIElURVJBVE9SICA9IHJlcXVpcmUoJy4vX3drcycpKCdpdGVyYXRvcicpXG4gICwgSXRlcmF0b3JzID0gcmVxdWlyZSgnLi9faXRlcmF0b3JzJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vX2NvcmUnKS5nZXRJdGVyYXRvck1ldGhvZCA9IGZ1bmN0aW9uKGl0KXtcbiAgaWYoaXQgIT0gdW5kZWZpbmVkKXJldHVybiBpdFtJVEVSQVRPUl1cbiAgICB8fCBpdFsnQEBpdGVyYXRvciddXG4gICAgfHwgSXRlcmF0b3JzW2NsYXNzb2YoaXQpXTtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2NvcmUuZ2V0LWl0ZXJhdG9yLW1ldGhvZC5qc1xuLy8gbW9kdWxlIGlkID0gNzlcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiJ3VzZSBzdHJpY3QnXG5cbmltcG9ydCBlbnZpcm9ubWVudCBmcm9tICcuL2Jyb3dzZXInXG5pbXBvcnQgeyBEZWZlcnJlZFByb21pc2UgfSBmcm9tICcuLi91dGlsL3Byb21pc2UnXG5cbi8qKlxuICogUmVwbGFjZXMgYSBgdmlkZW9gIGVsZW1lbnQgd2l0aCBhIGNvbnRhaW5lciBmb3IgZW1iZWRkaW5nIGEgRmxhc2ggb2JqZWN0LlxuICpcbiAqIEBwYXJhbSB7RWxlbWVudH0gdGFyZ2V0RWxlbWVudFxuICogQHBhcmFtIHtFbGVtZW50fSB0YXJnZXRQYXJlbnRcbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5leHBvcnQgY29uc3QgZGVmaW5lRW1iZWRFbGVtZW50ID0gKHRhcmdldEVsZW1lbnQsIHRhcmdldFBhcmVudCkgPT4ge1xuICBsZXQgZGZkID0gbmV3IERlZmVycmVkUHJvbWlzZSgpXG4gIGNvbnN0IGVsZW1lbnRJZCA9IHRhcmdldEVsZW1lbnQuaWRcbiAgaWYgKHRhcmdldEVsZW1lbnQubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ3ZpZGVvJykge1xuICAgIGxldCBkaXYgPSBlbnZpcm9ubWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKVxuICAgIGRpdi5pZCA9IGVsZW1lbnRJZCArICdfcnRtcCdcbiAgICB0YXJnZXRQYXJlbnQuYXBwZW5kQ2hpbGQoZGl2KVxuICAgIGlmICh0YXJnZXRFbGVtZW50LnBhcmVudEVsZW1lbnQpIHtcbiAgICAgIHRhcmdldEVsZW1lbnQucGFyZW50RWxlbWVudC5yZW1vdmVDaGlsZCh0YXJnZXRFbGVtZW50KVxuICAgIH1cbiAgICBkZmQucmVzb2x2ZShkaXYuaWQpXG4gIH0gZWxzZSB7XG4gICAgZGZkLnJlc29sdmUoZWxlbWVudElkKVxuICB9XG4gIHJldHVybiBkZmQucHJvbWlzZVxufVxuXG4vKipcbiAqIFJlcXVlc3QgdG8gZW1iZWQgYSBGbGFzaCBvYmplY3QgdXNpbmcgU1dGT2JqZWN0IGxpYnJhcnkuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGlkTmFtZVxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAqICAgICAgICBJbml0aWFsaXphdGlvbiBjb25maWd1cmF0aW9uIG1hcC5cbiAqIEBwYXJhbSB7T2JqZWN0fSBmbGFzaHZhcnNcbiAqICAgICAgICBUaGUgRmxhc2hWYXJzIHRvIHBhc3MgaW50byB0aGUgZW1iZWRkZWQgb2JqZWN0LlxuICogQHBhcmFtIHtPYmplY3R9IHN3Zm9iamVjdFxuICogICAgICAgIFRoZSBsb2FkZWQgU1dGT2JqZWN0IGxpYnJhcnkgdXRpbC5cbiAqIEBwYXJhbSB7U3RyaW5nfSBlbGVtZW50SWRcbiAqICAgICAgICBUaGUgaWQgb2YgdGhlIEVsZW1lbnQgdG8gZW1iZWQuXG4gKiBAcmV0dXJuIHtQcm9taXNlfVxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmV4cG9ydCBjb25zdCBlbWJlZFN3Zk9iamVjdCA9IChpZE5hbWUsIG9wdGlvbnMsIGZsYXNodmFycywgc3dmb2JqZWN0LCBlbGVtZW50SWQpID0+IHtcbiAgbGV0IGRmZCA9IG5ldyBEZWZlcnJlZFByb21pc2UoKVxuICBsZXQgcGFyYW1zID0ge1xuICAgIHF1YWxpdHk6ICdoaWdoJyxcbiAgICB3bW9kZTogJ29wYXF1ZScsXG4gICAgYmdjb2xvcjogb3B0aW9ucy5iYWNrZ3JvdW5kQ29sb3IgfHwgJyMwMDAnLFxuICAgIGFsbG93c2NyaXB0YWNjZXNzOiAnYWx3YXlzJyxcbiAgICBhbGxvd2Z1bGxzY3JlZW46ICd0cnVlJyxcbiAgICBhbGxvd25ldHdvcmtpbmc6ICdhbGwnXG4gIH1cbiAgbGV0IGF0dHJpYnV0ZXMgPSB7XG4gICAgaWQ6IGlkTmFtZSxcbiAgICBuYW1lOiBpZE5hbWUsXG4gICAgYWxpZ246ICdtaWRkbGUnXG4gIH1cbiAgaWYgKHN3Zm9iamVjdC5oYXNGbGFzaFBsYXllclZlcnNpb24ob3B0aW9ucy5taW5GbGFzaFZlcnNpb24pKSB7XG4gICAgc3dmb2JqZWN0LmVtYmVkU1dGKFxuICAgICAgb3B0aW9ucy5zd2YsXG4gICAgICBlbGVtZW50SWQsXG4gICAgICBvcHRpb25zLmVtYmVkV2lkdGggfHwgNjQwLFxuICAgICAgb3B0aW9ucy5lbWJlZEhlaWdodCB8fCA0ODAsXG4gICAgICBvcHRpb25zLm1pbkZsYXNoVmVyc2lvbixcbiAgICAgIG9wdGlvbnMucHJvZHVjdEluc3RhbGxVUkwsXG4gICAgICBmbGFzaHZhcnMsXG4gICAgICBwYXJhbXMsXG4gICAgICBhdHRyaWJ1dGVzLFxuICAgICAgKHJlc3VsdCkgPT4ge1xuICAgICAgICBpZiAocmVzdWx0LnN1Y2Nlc3MpIHtcbiAgICAgICAgICBkZmQucmVzb2x2ZSgpXG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgZGZkLnJlamVjdCgnRmxhc2ggT2JqZWN0IGVtYmVkIGZhaWxlZC4nKVxuICAgICAgICB9XG4gICAgICB9KVxuICB9IGVsc2Uge1xuICAgIGRmZC5yZWplY3QoJ0ZsYXNoIFBsYXllciBWZXJzaW9uIGlzIG5vdCBzdXBwb3J0ZWQuJylcbiAgfVxuICByZXR1cm4gZGZkLnByb21pc2Vcbn1cblxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2pzL2Vudi9lbWJlZC5qcyIsImltcG9ydCBlbnZpcm9ubWVudCBmcm9tICcuL2Jyb3dzZXInXG5jb25zdCB7IHJlcXVlc3RGcmFtZSB9ID0gZW52aXJvbm1lbnRcblxuLyogfHwgVHJhbnNsYXRpb24gU3R5bGVzIHVzZWQgb24gT3JpZW50YXRpb24tY2hhbmdlIG1ldGFkYXRhIGZyb20gTW9iaWxlIGJyb2FkY2FzdGVycy4gfHwgKi9cbmNvbnN0IG9yaWdpbiA9IFtcbiAgJ3dlYmtpdFRyYW5zZm9ybU9yaWdpbicsXG4gICdtb3pUcmFuc2Zvcm1PcmlnaW4nLFxuICAnbXNUcmFuc2Zvcm1PcmlnaW4nLFxuICAnb1RyYW5zZm9ybU9yaWdpbicsXG4gICd0cmFuc2Zvcm1PcmlnaW4nXG5dXG5jb25zdCBzdHlsZXMgPSBbXG4gICd3ZWJraXRUcmFuc2Zvcm0nLFxuICAnbW96VHJhbnNmb3JtJyxcbiAgJ21zVHJhbnNmb3JtJyxcbiAgJ29UcmFuc2Zvcm0nLFxuICAndHJhbnNmb3JtJ1xuXVxuY29uc3QgdHJhbnNpdGlvbiA9IFtcbiAgJ3dlYmtpdFRyYW5zaXRpb24nLFxuICAnbW96VHJhbnNpdGlvbicsXG4gICdtc1RyYW5zaXRpb24nLFxuICAnb1RyYW5zaXRpb24nLFxuICAndHJhbnNpdGlvbidcbl1cbmNvbnN0IHJvdGF0aW9uVHJhbnNsYXRpb25zID0ge1xuICAnMCc6IHtcbiAgICBvcmlnaW46ICdjZW50ZXIgY2VudGVyJyxcbiAgICB0cmFuc2Zvcm06ICdyb3RhdGUoMGRlZyknXG4gIH0sXG4gICc5MCc6IHtcbiAgICBvcmlnaW46ICdsZWZ0IHRvcCcsXG4gICAgdHJhbnNmb3JtOiAncm90YXRlKDkwZGVnKSB0cmFuc2xhdGVZKC0xMDAlKSdcbiAgfSxcbiAgJzE4MCc6IHtcbiAgICBvcmlnaW46ICdjZW50ZXIgY2VudGVyJyxcbiAgICB0cmFuc2Zvcm06ICdyb3RhdGUoMTgwZGVnKSdcbiAgfSxcbiAgJzI3MCc6IHtcbiAgICBvcmlnaW46ICd0b3AgbGVmdCcsXG4gICAgdHJhbnNmb3JtOiAncm90YXRlKDI3MGRlZykgdHJhbnNsYXRlWCgtMTAwJSkgdHJhbnNsYXRlWSgwJSknXG4gIH0sXG4gICctOTAnOiB7XG4gICAgb3JpZ2luOiAnbGVmdCB0b3AnLFxuICAgIHRyYW5zZm9ybTogJ3JvdGF0ZSgtOTBkZWcpIHRyYW5zbGF0ZVgoLTEwMCUpJ1xuICB9LFxuICAnLTE4MCc6IHtcbiAgICBvcmlnaW46ICdjZW50ZXIgY2VudGVyJyxcbiAgICB0cmFuc2Zvcm06ICdyb3RhdGUoLTE4MGRlZyknXG4gIH0sXG4gICctMjcwJzoge1xuICAgIG9yaWdpbjogJ3RvcCBsZWZ0JyxcbiAgICB0cmFuc2Zvcm06ICdyb3RhdGUoLTI3MGRlZykgdHJhbnNsYXRlWSgtMTAwJSknXG4gIH1cbn1cblxuLyogVXRpbGl0eSBtZXRob2QgdG8gdHJhY2sgYW5kIHJlc2l6ZSBhbiBlbGVtZW50IG9uIGVudGVyIGZyYW1lLiAqL1xuY29uc3QgdHJhY2tSZXNpemUgPSAoZWxlbWVudCwgcmFmLCBpc1JvdGF0ZWQgPSBmYWxzZSkgPT4ge1xuICByZXR1cm4gKCkgPT4ge1xuICAgIGNvbnN0IHBhcmVudCA9IGVsZW1lbnQucGFyZW50Tm9kZVxuICAgIGlmIChwYXJlbnQpIHtcbiAgICAgIGNvbnN0IHB3aWR0aCA9IHBhcmVudC5jbGllbnRXaWR0aFxuICAgICAgY29uc3QgcGhlaWdodCA9IHBhcmVudC5jbGllbnRIZWlnaHRcbiAgICAgIGlmIChpc1JvdGF0ZWQpIHtcbiAgICAgICAgZWxlbWVudC5zdHlsZS53aWR0aCA9IHBoZWlnaHQgKyAncHgnXG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgZWxlbWVudC5zdHlsZS53aWR0aCA9IHB3aWR0aCArICdweCdcbiAgICAgIH1cbiAgICAgIGNvbnN0IGV3aWR0aCA9IGVsZW1lbnQuY2xpZW50V2lkdGhcbiAgICAgIGNvbnN0IGVoZWlnaHQgPSBlbGVtZW50LmNsaWVudEhlaWdodFxuICAgICAgY29uc3QgbWFyZ2luID0gKGlzUm90YXRlZCA/IChwd2lkdGggLSBlaGVpZ2h0KSA6IChwd2lkdGggLSBld2lkdGgpKSAqIDAuNVxuICAgICAgZWxlbWVudC5zdHlsZS5wb3NpdGlvbiA9ICdyZWxhdGl2ZSdcbiAgICAgIGVsZW1lbnQuc3R5bGUubGVmdCA9IG1hcmdpbiArICdweCdcbiAgICB9XG4gICAgaWYgKHJhZikge1xuICAgICAgcmFmKHRyYWNrUmVzaXplKGVsZW1lbnQsIHJhZiwgaXNSb3RhdGVkKSlcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IGFwcGx5T3JpZW50YXRpb24gPSAoZWxlbWVudCwgdmFsdWUsIHJlc29sdXRpb24pID0+IHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuICBsZXQgaSwgbGVuZ3RoID0gc3R5bGVzLmxlbmd0aFxuICB2YWx1ZSA9IHZhbHVlICUgMzYwXG4gIGNvbnN0IGlzUm90YXRlZCA9IHZhbHVlICUgMTgwICE9PSAwXG4gIGNvbnN0IHBhcmVudCA9IGVsZW1lbnQucGFyZW50Tm9kZVxuICBjb25zdCBwd2lkdGggPSBlbGVtZW50LndpZHRoID8gZWxlbWVudC53aWR0aCA6IHBhcmVudC5jbGllbnRXaWR0aFxuICBjb25zdCBwaGVpZ2h0ID0gZWxlbWVudC5oZWlnaHQgPyBlbGVtZW50LmhlaWdodCA6IHBhcmVudC5jbGllbnRIZWlnaHRcbiAgY29uc3QgdHJhbnNsYXRpb25zID0gcm90YXRpb25UcmFuc2xhdGlvbnNbdmFsdWUudG9TdHJpbmcoKV1cbiAgZm9yKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICBlbGVtZW50LnN0eWxlW29yaWdpbltpXV0gPSB0cmFuc2xhdGlvbnMub3JpZ2luXG4gICAgZWxlbWVudC5zdHlsZVtzdHlsZXNbaV1dID0gdHJhbnNsYXRpb25zLnRyYW5zZm9ybVxuICAgIGVsZW1lbnQuc3R5bGVbdHJhbnNpdGlvbltpXV0gPSAndHJhbnNmb3JtIDAuMHMgbGluZWFyJ1xuICB9XG4gIGlmIChpc1JvdGF0ZWQpIHtcbiAgICAvLyBjb25zdCBzY2FsZSA9IHB3aWR0aCA+IHBoZWlnaHQgPyBwaGVpZ2h0IC8gcHdpZHRoIDogcHdpZHRoIC8gcGhlaWdodFxuICAgIGVsZW1lbnQuc3R5bGUud2lkdGggPSBwaGVpZ2h0ICsgJ3B4J1xuICAgIHBhcmVudC5zdHlsZS5oZWlnaHQgPSBwaGVpZ2h0ICsgJ3B4J1xuICAgIC8vIGVsZW1lbnQuc3R5bGUuaGVpZ2h0ID0gKHB3aWR0aCAqIHNjYWxlKSArICdweCdcbiAgfVxuICBlbHNlIHtcbiAgICBlbGVtZW50LnN0eWxlLndpZHRoID0gcHdpZHRoICsgJ3B4J1xuICAgIGVsZW1lbnQuc3R5bGUuaGVpZ2h0ID0gcGhlaWdodCArICdweCdcbiAgICAvLyAgICBwYXJlbnQuc3R5bGUud2lkdGggPSBwd2lkdGggKyAncHgnXG4gIH1cblxuICBpZiAoZG9jdW1lbnQuYXR0YWNoRXZlbnQpIHtcbiAgICBwYXJlbnQuYXR0YWNoRXZlbnQoJ3Jlc2l6ZScsIHRyYWNrUmVzaXplKGVsZW1lbnQsIHJlcXVlc3RGcmFtZSwgaXNSb3RhdGVkKSlcbiAgfVxuICBlbHNlIHtcbiAgICB0cmFja1Jlc2l6ZShlbGVtZW50LCByZXF1ZXN0RnJhbWUsIGlzUm90YXRlZCkoKVxuICB9XG59XG5cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9qcy9lbnYvdHJhbnNsYXRpb24tdXRpbC5qcyIsIi8qKlxuICogQ29tbW9uIFB1Ymxpc2hlci1iYXNlZCBldmVudCB0eXBlcy5cbiAqL1xuZXhwb3J0IGNvbnN0IFB1Ymxpc2hlckV2ZW50VHlwZXMgPSBPYmplY3QuZnJlZXplKHtcbiAgQ09OTkVDVF9TVUNDRVNTOiAnQ29ubmVjdC5TdWNjZXNzJyxcbiAgQ09OTkVDVF9GQUlMVVJFOiAnQ29ubmVjdC5GYWlsdXJlJyxcbiAgUFVCTElTSF9TVEFSVDogJ1B1Ymxpc2guU3RhcnQnLFxuICBQVUJMSVNIX0ZBSUw6ICdQdWJsaXNoLkZhaWwnLFxuICBQVUJMSVNIX0lOVkFMSURfTkFNRTogJ1B1Ymxpc2guSW52YWxpZE5hbWUnLFxuICBVTlBVQkxJU0hfU1VDQ0VTUzogJ1VucHVibGlzaC5TdWNjZXNzJyxcbiAgUFVCTElTSF9NRVRBREFUQTogJ1B1Ymxpc2guTWV0YWRhdGEnLFxuICBDT05ORUNUSU9OX0NMT1NFRDogJ1B1Ymxpc2hlci5Db25uZWN0aW9uLkNsb3NlZCcsXG4gIERJTUVOU0lPTl9DSEFOR0U6ICdQdWJsaXNoZXIuVmlkZW8uRGltZW5zaW9uQ2hhbmdlJ1xufSlcblxuLyoqXG4gKiBFdmVudCB0eXBlcyBkaXNwYWN0aGVkIGZyb20gYW5kIHNwZWNpZmljIHRvIGBSZWQ1UHJvUHVibGlzaGVyYC5cbiAqXG4gKiBAc2VlIHtSZWQ1UHJvUHVibGlzaGVyfVxuICovXG5leHBvcnQgY29uc3QgRmFpbG92ZXJQdWJsaXNoZXJFdmVudFR5cGVzID0gT2JqZWN0LmZyZWV6ZSh7XG4gIFBVQkxJU0hFUl9SRUpFQ1Q6ICdQdWJsaXNoZXIuUmVqZWN0JyxcbiAgUFVCTElTSEVSX0FDQ0VQVDogJ1B1Ymxpc2hlci5BY2NlcHQnXG59KVxuXG4vKipcbiAqIEV2ZW50IHR5cGVzIGRpc3BhdGNoZWQgZnJvbSBhbmQgc3BlY2lmaWMgdG8gYFJUQ1B1Ymxpc2hlcmAuXG4gKlxuICogQHNlZSB7UlRDUHVibGlzaGVyfVxuICovXG5leHBvcnQgY29uc3QgUlRDUHVibGlzaGVyRXZlbnRUeXBlcyA9IE9iamVjdC5mcmVlemUoe1xuICBNRURJQV9TVFJFQU1fQVZBSUxBQkxFOiAnV2ViUlRDLk1lZGlhU3RyZWFtLkF2YWlsYWJsZScsXG4gIFBFRVJfQ09OTkVDVElPTl9BVkFJTEFCTEU6ICdXZWJSVEMuUGVlckNvbm5lY3Rpb24uQXZhaWxhYmxlJyxcbiAgT0ZGRVJfU1RBUlQ6ICdXZWJSVEMuT2ZmZXIuU3RhcnQnLFxuICBPRkZFUl9FTkQ6ICdXZWJSVEMuT2ZmZXIuRW5kJyxcbiAgUEVFUl9DQU5ESURBVEVfRU5EOiAnV2ViUlRDLlBlZXJDb25uZWN0aW9uLkNhbmRpZGF0ZUVuZCcsXG4gIElDRV9UUklDS0xFX0NPTVBMRVRFOiAnV2ViUlRDLkljZVRyaWNrbGUuQ29tcGxldGUnXG59KVxuXG4vKipcbiAqIEV2ZW50IHR5cGVzIGRpc3BhdGNoZWQgZnJvbSBhbmQgc3BlY2lmaWMgdG8gYFJUTVBQdWJsaXNoZXJgLlxuICpcbiAqIEBzZWUge1JUTVBQdWJsaXNoZXJ9XG4gKi9cbmV4cG9ydCBjb25zdCBSVE1QUHVibGlzaGVyRXZlbnRUeXBlcyA9IE9iamVjdC5mcmVlemUoe1xuICBFTUJFRF9TVUNDRVNTOiAnRmxhc2hQbGF5ZXIuRW1iZWQuU3VjY2VzcycsXG4gIEVNQkVEX0ZBSUxVUkU6ICdGbGFzaFBsYXllci5FbWJlZC5GYWlsdXJlJ1xufSlcblxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2pzL2V2ZW50L3B1Ymxpc2hlci1ldmVudC5qcyIsIi8qKlxuICogQ29tbW9uIGV2ZW50IHR5cGVzIG9uIGFsbCBTdWJzY3JpYmVycy5cbiAqL1xuZXhwb3J0IGNvbnN0IFN1YnNjcmliZXJFdmVudFR5cGVzID0gT2JqZWN0LmZyZWV6ZSh7XG4gIENPTk5FQ1RfU1VDQ0VTUzogJ0Nvbm5lY3QuU3VjY2VzcycsXG4gIENPTk5FQ1RfRkFJTFVSRTogJ0Nvbm5lY3QuRmFpbHVyZScsXG4gIFNVQlNDUklCRV9TVEFSVDogJ1N1YnNjcmliZS5TdGFydCcsXG4gIFNVQlNDUklCRV9TVE9QOiAnU3Vic2NyaWJlLlN0b3AnLFxuICBTVUJTQ1JJQkVfRkFJTDogJ1N1YnNjcmliZS5GYWlsJyxcbiAgU1VCU0NSSUJFX0lOVkFMSURfTkFNRTogJ1N1YnNjcmliZS5JbnZhbGlkTmFtZScsXG4gIFNVQlNDUklCRV9NRVRBREFUQTogJ1N1YnNjcmliZS5NZXRhZGF0YScsXG4gIFNVQlNDUklCRV9TRU5EX0lOVk9LRTogJ1N1YnNjcmliZS5TZW5kLkludm9rZScsXG4gIFBMQVlfVU5QVUJMSVNIOiAnU3Vic2NyaWJlLlBsYXkuVW5wdWJsaXNoJyxcbiAgQ09OTkVDVElPTl9DTE9TRUQ6ICdTdWJzY3JpYmUuQ29ubmVjdGlvbi5DbG9zZWQnLFxuICBPUklFTlRBVElPTl9DSEFOR0U6ICdTdWJzY3JpYmUuT3JpZW50YXRpb24uQ2hhbmdlJyxcbiAgVk9MVU1FX0NIQU5HRTogJ1N1YnNjcmliZS5Wb2x1bWUuQ2hhbmdlJyxcbiAgUExBWUJBQ0tfVElNRV9VUERBVEU6ICdTdWJzY3JpYmUuVGltZS5VcGRhdGUnLFxuICBQTEFZQkFDS19TVEFURV9DSEFOR0U6ICdTdWJzY3JpYmUuUGxheWJhY2suQ2hhbmdlJyxcbiAgRlVMTF9TQ1JFRU5fU1RBVEVfQ0hBTkdFOiAnU3Vic2NyaWJlLkZ1bGxTY3JlZW4uQ2hhbmdlJ1xufSlcblxuLyoqXG4gKiBFdmVudCB0eXBlcyBkaXNwYXRjaGVkIGZyb20gYW5kIHNwZWNpZmljIHRvIGBSZWQ1UHJvU3Vic2NyaWJlcmAuXG4gKlxuICogQHNlZSB7UmVkNVByb1N1YnNjcmliZXJ9XG4gKi9cbmV4cG9ydCBjb25zdCBGYWlsb3ZlclN1YnNjcmliZXJFdmVudFR5cGVzID0gT2JqZWN0LmZyZWV6ZSh7XG4gIFNVQlNDUklCRVJfUkVKRUNUOiAnU3Vic2NyaWJlci5SZWplY3QnLFxuICBTVUJTQ1JJQkVSX0FDQ0VQVDogJ1N1YnNjcmliZXIuQWNjZXB0J1xufSlcblxuLyoqXG4gKiBFdmVudCB0eXBlcyBkaXNwYXRjaGVkIGZyb20gYW5kIHNwZWNpZmljIHRvIGBSVENTdWJzY3JpYmVyYC5cbiAqXG4gKiBAc2VlIHtSVENTdWJzY3JpYmVyfVxuICovXG5leHBvcnQgY29uc3QgUlRDU3Vic2NyaWJlckV2ZW50VHlwZXMgPSBPYmplY3QuZnJlZXplKHtcbiAgUEVFUl9DT05ORUNUSU9OX0FWQUlMQUJMRTogJ1dlYlJUQy5QZWVyQ29ubmVjdGlvbi5BdmFpbGFibGUnLFxuICBPRkZFUl9TVEFSVDogJ1dlYlJUQy5PZmZlci5TdGFydCcsXG4gIE9GRkVSX0VORDogJ1dlYlJUQy5PZmZlci5FbmQnLFxuICBBTlNXRVJfU1RBUlQ6ICdXZWJSVEMuQW5zd2VyLlN0YXJ0JyxcbiAgQU5TV0VSX0VORDogJ1dlYlJUQy5BbnN3ZXIuRW5kJyxcbiAgQ0FORElEQVRFX1NUQVJUOiAnV2ViUlRDLkNhbmRpZGF0ZS5TdGFydCcsXG4gIENBTkRJREFURV9FTkQ6ICdXZWJSVEMuQ2FuZGlkYXRlLkVuZCcsXG4gIFBFRVJfQ0FORElEQVRFX0VORDogJ1dlYlJUQy5QZWVyQ29ubmVjdGlvbi5DYW5kaWRhdGVFbmQnLFxuICBJQ0VfVFJJQ0tMRV9DT01QTEVURTogJ1dlYlJUQy5JY2VUcmlja2xlLkNvbXBsZXRlJyxcbiAgT05fQUREX1NUUkVBTTogJ1dlYlJUQy5BZGQuU3RyZWFtJ1xufSlcblxuLyoqXG4gKiBFdmVudCB0eXBlIGRpc3BhdGNoZWQgZnJvbSBhbmQgc3BlY2lmaWMgdG8gYFJUTVBTdWJzY3JpYmVyYC5cbiAqXG4gKiBAc2VlIHtSVE1QU3Vic2NyaWJlcn1cbiAqL1xuZXhwb3J0IGNvbnN0IFJUTVBTdWJzY3JpYmVyRXZlbnRUeXBlcyA9IE9iamVjdC5mcmVlemUoe1xuICBFTUJFRF9TVUNDRVNTOiAnRmxhc2hQbGF5ZXIuRW1iZWQuU3VjY2VzcycsXG4gIEVNQkVEX0ZBSUxVUkU6ICdGbGFzaFBsYXllci5FbWJlZC5GYWlsdXJlJyxcbiAgLy8gU3RyZWFtIE1hbmFnZXIgKyBBQlIgU3BlY2lmaWNcbiAgQUJSX0xFVkVMX0NIQU5HRTogJ1JUTVAuQWRhcHRpdmVCaXRyYXRlLkxldmVsJ1xufSlcblxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2pzL2V2ZW50L3N1YnNjcmliZXItZXZlbnQuanMiLCIndXNlIHN0cmljdCdcblxuaW1wb3J0IGVudmlyb25tZW50IGZyb20gJy4uL2Vudi9icm93c2VyJ1xuaW1wb3J0IHsgZGVidWcsIHdhcm4gfSBmcm9tICcuLi9sb2cnXG5cbmNvbnN0IE5BTUUgPSAnUjVQcm9SVE1QU2hhcmVkT2JqZWN0SGFuZGxlcidcblxuLyoqXG4gKiBGbGFzaC1iYXNlZCBTaGFyZWRPYmplY3QgaGFuZGxlci5cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5jbGFzcyBSVE1QU2hhcmVkT2JqZWN0SGFuZGxlciB7XG5cbiAgY29uc3RydWN0b3IgKCkge1xuICAgIHRoaXMuX2VsZW1lbnQgPSB1bmRlZmluZWRcbiAgICB0aGlzLl9yZXNwb25zZUhhbmRsZXJzID0gW11cbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgcmVzcG9uc2UgaGFuZGxlciBmb3IgU2hhcmVkT2JqZWN0IGV2ZW50cy5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGhhbmRsZXJcbiAgICovXG4gIGFkZFJlc3BvbnNlSGFuZGxlciAoaGFuZGxlcikge1xuICAgIHRoaXMuX3Jlc3BvbnNlSGFuZGxlcnMucHVzaChoYW5kbGVyKVxuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgYSByZXNwb25zZSBoYW5kbGVyIGZyb20gU2hhcmVkT2JqZWN0IGV2ZW50cy5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGhhbmRsZXJcbiAgICovXG4gIHJlbW92ZVJlc3BvbnNlSGFuZGxlciAoaGFuZGxlcikge1xuICAgIGxldCBpID0gdGhpcy5fcmVzcG9uc2VIYW5kbGVycy5sZW5ndGhcbiAgICBsZXQgckhhbmRsZXJcbiAgICB3aGlsZSgtLWkgPiAtMSkge1xuICAgICAgckhhbmRsZXIgPSB0aGlzLl9yZXNwb25zZUhhbmRsZXJzW2ldXG4gICAgICBpZiAockhhbmRsZXIgPT09IGhhbmRsZXIpIHtcbiAgICAgICAgdGhpcy5fcmVzcG9uc2VIYW5kbGVycy5zcGxpY2UoaSwgMSlcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZXMgYW4gZXZlbnQgZnJvbSBhIFNoYXJlZE9iamVjdC5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50XG4gICAqL1xuICBoYW5kbGVTaGFyZWRPYmplY3RFdmVudCAoZXZlbnQpIHtcbiAgICBkZWJ1ZyhOQU1FLCAnW3NoYXJlZG9iamVjdDpldmVudF0nKVxuICAgIGxldCBpXG4gICAgbGV0IGxlbmd0aCA9IHRoaXMuX3Jlc3BvbnNlSGFuZGxlcnMubGVuZ3RoXG4gICAgbGV0IGhhbmRsZXJcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZXIgPSB0aGlzLl9yZXNwb25zZUhhbmRsZXJzW2ldXG4gICAgICBpZiAoaGFuZGxlci5yZXNwb25kKEpTT04ucGFyc2UoZXZlbnQpKSkge1xuICAgICAgICBicmVha1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBc3NpZ25zIGEgZ2xvYmFsIHJlc3BvbnNlIGhhbmRsZXIgZm9yIFNoYXJlZE9iamVjdCBjb21tdW5pY2F0aW9uIHRocm91Z2ggRmxhc2ggb2JqZWN0IG92ZXIgRXh0ZXJuYWxJbnRlcmZhY2UuXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gZWxcbiAgICogICAgICAgIFRoZSBvYmplY3QgZW1iZWQgZWxlbWVudC5cbiAgICovXG4gIGFzc2lnblNoYXJlZE9iamVjdFJlc3BvbmRlciAobmFtZSwgZWwpIHtcbiAgICBjb25zdCBfaGFuZGxlU2hhcmVkT2JqZWN0RXZlbnQgPSB0aGlzLmhhbmRsZVNoYXJlZE9iamVjdEV2ZW50LmJpbmQodGhpcylcbiAgICBjb25zdCBlbElkID0gZWwuaWQuc3BsaXQoJy0nKS5qb2luKCdfJylcbiAgICBjb25zdCBoYW5kbGVyTmFtZSA9IFsnaGFuZGxlU2hhcmVkT2JqZWN0RXZlbnQnLCBlbElkXS5qb2luKCdfJylcbiAgICBkZWJ1ZyhOQU1FLCBgW2Fzc2lnbjpzaGFyZWRvYmplY3Q6cmVzcG9uZGVyXSA6OiAke2VsSWR9YClcbiAgICBkZWJ1ZyhOQU1FLCBgW3NoYXJlZG9qZWN0OnJlc3BvbmRlcl0gOjogJHtoYW5kbGVyTmFtZX1gKVxuICAgIGVsLnNldFNoYXJlZE9iamVjdFJlc3BvbmRlcihuYW1lLCBoYW5kbGVyTmFtZSlcbiAgICBlbnZpcm9ubWVudC5zZXRHbG9iYWwoaGFuZGxlck5hbWUsIF9oYW5kbGVTaGFyZWRPYmplY3RFdmVudClcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIGNvbm5lY3QgdG8gU2hhcmVkT2JqZWN0LlxuICAgKi9cbiAgY29ubmVjdCAoc3dmSWQpIHtcbiAgICB0aGlzLl9lbGVtZW50ID0gZW52aXJvbm1lbnQuZ2V0RW1iZWRPYmplY3Qoc3dmSWQpXG4gICAgaWYgKCF0aGlzLl9lbGVtZW50KSB7XG4gICAgICB3YXJuKGBDb3VsZCBub3QgbG9jYXRlIGVtYmVkZGVkIEZsYXNoIG9iamVjdCBmb3IgaWQ6ICR7c3dmSWR9YClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBkaXNjb25uZWN0IHRvIFNoYXJlZE9iamVjdC5cbiAgICovXG4gIGRpc2Nvbm5lY3QgKCkge1xuICAgIHdoaWxlICh0aGlzLl9yZXNwb25zZUhhbmRsZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuX3Jlc3BvbnNlSGFuZGxlcnMuc2hpZnQoKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBdHRlbXB0IHRvIHNlbmQgbWV0aG9kIHVwZGF0ZSB0byBTaGFyZWRPYmplY3QuXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBjYWxsTmFtZVxuICAgKiBAcGFyYW0ge09iamVjdH0gbWVzc2FnZVxuICAgKiAgICAgICAgU3RyaW5nIG9yIE9iamVjdCB0aGF0IHdpbGwgYmUgc2VyaWFsaXplZCB0byBhIEpTT04gc3RyaW5nLlxuICAgKi9cbiAgc2VuZFRvU2hhcmVkT2JqZWN0IChuYW1lLCBjYWxsTmFtZSwgbWVzc2FnZSkge1xuICAgIGRlYnVnKE5BTUUsICdbc2VuZFRvU2hhcmVkT2JqZWN0XScpXG4gICAgdHJ5IHtcbiAgICAgIHRoaXMuX2VsZW1lbnQuc2hhcmVkT2JqZWN0U2VuZChuYW1lLCBjYWxsTmFtZSwgdHlwZW9mIG1lc3NhZ2UgPT09ICdzdHJpbmcnID8gbWVzc2FnZSA6IEpTT04uc3RyaW5naWZ5KG1lc3NhZ2UpKVxuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgd2FybignQ291bGQgbm90IHNlbmQgdG8gc2hhcmVkIG9iamVjdCAoJyArIG5hbWUgKyAnKS4gRXJyb3I6ICcgKyBlLm1lc3NhZ2UpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEF0dGVtcHQgdG8gdXBkYXRlIHByb3BlcnR5IG9uIFNoYXJlZE9iamVjdC5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IGtleVxuICAgKiBAcGFyYW0ge09iamVjdH0gdmFsdWVcbiAgICovXG4gIHNlbmRQcm9wZXJ0eVRvU2hhcmVkT2JqZWN0IChuYW1lLCBrZXksIHZhbHVlKSB7XG4gICAgZGVidWcoTkFNRSwgJ1tzZW5kUHJvcGVydHlUb1NoYXJlZE9iamVjdF0nKVxuICAgIHRyeSB7XG4gICAgICB0aGlzLl9lbGVtZW50LnNoYXJlZE9iamVjdFNlbmRQcm9wZXJ0eShuYW1lLCBrZXksIHZhbHVlKVxuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgd2FybignQ291bGQgbm90IHNlbmQgdG8gc2hhcmVkIG9iamVjdCAoJyArIG5hbWUgKyAnKS4gRXJyb3I6ICcgKyBlLm1lc3NhZ2UpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gZ2V0IHJlbW90ZSBTaGFyZU9iamVjdCBieSBuYW1lLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gc2hhcmVkT2JqZWN0TmFtZVxuICAgKi9cbiAgZ2V0UmVtb3RlU2hhcmVkT2JqZWN0IChzaGFyZWRPYmplY3ROYW1lKSB7XG4gICAgZGVidWcoTkFNRSwgJ1tnZXRSZW1vdGVTaGFyZWRPYmplY3RdJylcbiAgICB0cnkge1xuICAgICAgdGhpcy5hc3NpZ25TaGFyZWRPYmplY3RSZXNwb25kZXIoc2hhcmVkT2JqZWN0TmFtZSwgdGhpcy5fZWxlbWVudClcbiAgICAgIHRoaXMuX2VsZW1lbnQuZ2V0UmVtb3RlU2hhcmVkT2JqZWN0KHNoYXJlZE9iamVjdE5hbWUpXG4gICAgfVxuICAgIGNhdGNoIChlKSB7XG4gICAgICB3YXJuKCdDb3VsZCBub3QgZ2V0IHJlbW90ZSBzaGFyZWQgb2JqZWN0ICgnICsgbmFtZSArICcpLiBFcnJvcjogJyArIGUubWVzc2FnZSlcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBjb25uZWN0IHRvIFNoYXJlZE9iamVjdCBieSBuYW1lLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gc2hhcmVkT2JqZWN0TmFtZVxuICAgKi9cbiAgY29ubmVjdFRvU2hhcmVkT2JqZWN0IChzaGFyZWRPYmplY3ROYW1lKSB7XG4gICAgZGVidWcoTkFNRSwgJ1tjb25uZWN0VG9TaGFyZWRPYmplY3RdJylcbiAgICB0cnkge1xuICAgICAgdGhpcy5fZWxlbWVudC5jb25uZWN0VG9TaGFyZWRPYmplY3Qoc2hhcmVkT2JqZWN0TmFtZSlcbiAgICB9XG4gICAgY2F0Y2ggKGUpIHtcbiAgICAgIHdhcm4oJ0NvdWxkIG5vdCBjb25uZWN0IHRvIHNoYXJlZCBvYmplY3QgKCcgKyBuYW1lICsgJykuIEVycm9yOiAnICsgZS5tZXNzYWdlKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIGNsb3NlIFNoYXJlZE9iamVjdCBjb25uZWN0aW9uIGJ5IG5hbWUuXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzaGFyZWRPYmplY3ROYW1lXG4gICAqL1xuICBjbG9zZVNoYXJlZE9iamVjdCAoc2hhcmVkT2JqZWN0TmFtZSkge1xuICAgIGRlYnVnKE5BTUUsICdbZGlzY29ubmVjdFRvU2hhcmVkT2JqZWN0XScpXG4gICAgdHJ5IHtcbiAgICAgIHRoaXMuX2VsZW1lbnQuZGlzY29ubmVjdEZyb21TaGFyZWRPYmplY3Qoc2hhcmVkT2JqZWN0TmFtZSlcbiAgICB9XG4gICAgY2F0Y2ggKGUpIHtcbiAgICAgIHdhcm4oJ0NvdWxkIG5vdCBkaXNjb25uZWN0IHRvIHNoYXJlZCBvYmplY3QgKCcgKyBuYW1lICsgJykuIEVycm9yOiAnICsgZS5tZXNzYWdlKVxuICAgIH1cbiAgfVxuXG59XG5cbmV4cG9ydCBkZWZhdWx0IFJUTVBTaGFyZWRPYmplY3RIYW5kbGVyXG5cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9qcy9oZWxwZXIvc2hhcmVkb2JqZWN0LWhlbHBlci1ydG1wLmpzIiwiJ3VzZSBzdHJpY3QnXG5cbi8qKlxuICogRWFzeSBkZWNvcmF0b3IgZm9yIHNldHRpbmcgYSBtdXRhYmxlLCBpdGVyYXRhYmxlIHByb3BlcnR5IG9uIGFuIG9iamVjdC5cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5jb25zdCBpbmZsYXRlID0gKG9iaiwgcHJvcCwgdmFsdWUpID0+IHtcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwgcHJvcCwge1xuICAgIHZhbHVlOiB2YWx1ZSxcbiAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICBlbnVtZXJhYmxlOiB0cnVlXG4gIH0pXG59XG5cbi8qKlxuICogRGVmYXVsdCBgZXhhY3RgIHNldHRpbmcgZm9yIGB2aWRlb2Agb24gYE1lZGlhQ29uc3RyYWludGAgZm9yIFdlYlJUQyBicm9hZGNhc3QuXG4gKlxuICogQHByaXZhdGVcbiAqL1xuY2xhc3MgUlRDTWVkaWFWaWRlb0NvbnN0cmFpbnQge1xuXG4gIGNvbnN0cnVjdG9yICgpIHtcbiAgICBpbmZsYXRlKHRoaXMsICd3aWR0aCcsIHtcbiAgICAgIGV4YWN0OiA2NDBcbiAgICB9KVxuICAgIGluZmxhdGUodGhpcywgJ2hlaWdodCcsIHtcbiAgICAgIGV4YWN0OiA0ODBcbiAgICB9KVxuICB9XG5cbn1cblxuLyoqXG4gKiBEZWZhdWx0IFJUTVAgdmlkZW8gc2V0dGluZ3MgZm9yIGJyYW9kY2FzdC5cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5jbGFzcyBSVE1QTWVkaWFWaWRlb0NvbnN0cmFpbnQge1xuXG4gIGNvbnN0cnVjdG9yICgpIHtcbiAgICBpbmZsYXRlKHRoaXMsICd3aWR0aCcsIDY0MClcbiAgICBpbmZsYXRlKHRoaXMsICdoZWlnaHQnLCA0ODApXG4gICAgaW5mbGF0ZSh0aGlzLCAnZm9yY2UnLCBmYWxzZSlcbiAgICBpbmZsYXRlKHRoaXMsICdmcmFtZXJhdGUnLCAxNSlcbiAgICBpbmZsYXRlKHRoaXMsICdiYW5kd2lkdGgnLCA1MDAwMClcbiAgICBpbmZsYXRlKHRoaXMsICdxdWFsaXR5JywgODApXG4gICAgaW5mbGF0ZSh0aGlzLCAncHJvZmlsZScsICdiYXNlbGluZScpXG4gICAgaW5mbGF0ZSh0aGlzLCAnbGV2ZWwnLCAzLjEpXG4gIH1cblxufVxuXG4vKipcbiAqIERlZmF1bHQgV2ViUlRDIG1lZGlhIHNldHRpbmdzIGZvciBicm9hZGNhc3QuXG4gKlxuICogQHByaXZhdGVcbiAqL1xuY2xhc3MgUlRDTWVkaWFDb25zdHJhaW50IHtcblxuICBjb25zdHJ1Y3RvciAoYXVkaW8gPSB0cnVlLCB2aWRlbyA9IHVuZGVmaW5lZCkge1xuICAgIGluZmxhdGUodGhpcywgJ2F1ZGlvJywgYXVkaW8pXG4gICAgaW5mbGF0ZSh0aGlzLCAndmlkZW8nLCB2aWRlbyB8fCBuZXcgUlRDTWVkaWFWaWRlb0NvbnN0cmFpbnQoKSlcbiAgfVxufVxuXG4vKipcbiAqIERlZmF1bHQgUlRNUCBtZWRpYSBzZXR0aW5ncyBmb3IgYnJvYWRjYXN0LlxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmNsYXNzIFJUTVBNZWRpYUNvbnN0cmFpbnQge1xuXG4gIGNvbnN0cnVjdG9yIChhdWRpbyA9IHRydWUsIHZpZGVvID0gdW5kZWZpbmVkKSB7XG4gICAgaW5mbGF0ZSh0aGlzLCAnYXVkaW8nLCBhdWRpbylcbiAgICBpbmZsYXRlKHRoaXMsICd2aWRlbycsIHZpZGVvIHx8IG5ldyBSVE1QTWVkaWFWaWRlb0NvbnN0cmFpbnQoKSlcbiAgfVxufVxuXG5leHBvcnQgeyBSVENNZWRpYUNvbnN0cmFpbnQsIFJUTVBNZWRpYUNvbnN0cmFpbnQgfVxuXG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvanMvcHVibGlzaGVyL2NvbnN0cmFpbnQvaW5kZXguanMiLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi4vLi4vZXZlbnQnXG5cbi8qKlxuICogRXZlbnRzIGZvciBTbGlkZXIgQ29udHJvbC5cbiAqXG4gKiBAc2VlIHtTbGlkZXJDb250cm9sfVxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmNsYXNzIFNsaWRlckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gIGNvbnN0cnVjdG9yICh0eXBlLCBjb250cm9sLCBkYXRhKSB7XG4gICAgc3VwZXIodHlwZSwgZGF0YSlcbiAgICB0aGlzLl9jb250cm9sID0gY29udHJvbFxuICB9XG5cbiAgZ2V0IGNvbnRyb2wgKCkge1xuICAgIHJldHVybiB0aGlzLl9jb250cm9sXG4gIH1cblxufVxuXG4vKipcbiAqIEVudW1lcmF0aW9uIG9mIFNsaWRlciBFdmVudCB0eXBlcy5cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5jb25zdCBTbGlkZXJFdmVudFR5cGVzID0gT2JqZWN0LmZyZWV6ZSh7XG4gIENIQU5HRV9TVEFSVDogJ2NoYW5nZXN0YXJ0JyxcbiAgQ0hBTkdFOiAnY2hhbmdlJyxcbiAgQ0hBTkdFX0NPTVBMRVRFOiAnY2hhbmdlY29tcGxldGUnXG59KVxuXG5leHBvcnQgeyBTbGlkZXJFdmVudCBhcyBTbGlkZXJFdmVudCB9XG5leHBvcnQgeyBTbGlkZXJFdmVudFR5cGVzIGFzIFNsaWRlckV2ZW50VHlwZXMgfVxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2pzL3N1YnNjcmliZXIvY29udHJvbHMvZXZlbnQuanMiLCIndXNlIHN0cmljdCdcblxuaW1wb3J0IHsgRGVmZXJyZWRQcm9taXNlIH0gZnJvbSAnLi9wcm9taXNlJ1xuXG5jb25zdCBtYXAgPSBuZXcgV2Vha01hcCgpXG5cbmNvbnN0IHB2dCA9IChjdHgpID0+IHtcbiAgaWYgKCFtYXAuaGFzKGN0eCkpIHtcbiAgICBtYXAuc2V0KGN0eCwge30pXG4gIH1cblxuICByZXR1cm4gbWFwLmdldChjdHgpXG59XG5cbi8qKlxuICogSW1wbGVtZW50YXRpb24gRmFjdG9yeS5cbiAqXG4gKiBUaGlzIGlzIHVzZWQgYnkgdGhlIGZhaWwtb3ZlciBmb3IgUHVibGlzaGVyIGFuZCBTdWJzY3JpYmVyIHRvIGRldGVybWluZSBicm93c2VyIHN1cHBvcnQgb2Ygb3JkZXIgbGlzdCBvZiBpbXBsZW1lbnRhdGlvbnMuXG4gKlxuICogQHByaXZhdGVcbiAqL1xuZXhwb3J0IGNsYXNzIEltcGxGYWN0b3J5T3JkZXIge1xuXG4gIGNvbnN0cnVjdG9yICgpIHtcbiAgICB0aGlzLmxpc3RvcmRlciA9IChmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24gKiBsaXN0b3JkZXIgKGxpc3QpIHtcbiAgICAgICAgd2hpbGUgKGxpc3QubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHlpZWxkIGxpc3Quc2hpZnQoKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSgpKVxuXG4gICAgLyoqXG4gICAgICogQXR0ZW1wdCB0byBjaGVjayBzdXBwb3J0IGFuZCBpbml0aWFsaXplIENsYXNzIGluc3RhbmNlIHdpdGhpbiB0aGUgb3JkZXIuIE9wdGlvbmFsbHksIGNhbiBpbnZva2UgYW4gaW5pdGlhbGl6YXRpb24gd2l0aCBjb25maWd1cmF0aW9uIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBpdGVyYXRvclxuICAgICAqICAgICAgICBJdGVyYXRvciB1c2VkIGluIGFjY2Vzc2luZyBwb3NzaWJsZSBDbGFzcyBpbnN0YW5jZSBuZXh0IGluIGxpbmtlZCBsaXN0IG9mIG9yZGVyLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBtYXBcbiAgICAgKiAgICAgICAgTWFwIG9mIG9yZGVyIHR5cGUgdG8gQ2xhc3MuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICAgKiAgICAgICAgTWFwIG9mIGluaXRpYWxpemF0aW9uIGNvbmZpZ3VyYXRpb25zIHRvIHR5cGVzLlxuICAgICAqIEBwYXJhbSB7UHJvbWlzZX0gcHJvbWlzZVxuICAgICAqICAgICAgICBUaGUgYFByb21pc2VgIGluc3RhbmNlIHRvIHVzZSBpbiByZXNvbHZlIG9yIHJlamVjdCBvbmNlIGVpdGhlciBhIHZhbGlkIGluc3RhbmNlIGlzIGNyZWF0ZWQgb3Igb3JkZXIgaGFzIGJlZW4gZXhoYXVzdGVkLCByZXNwZWN0aXZlbHkuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaW5pdEZuXG4gICAgICogICAgICAgIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGludm9rZSB1cG9uIGluc3RhbnRpYXRpb24gYXR0ZW1wdC5cbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gbGFzdEVycm9yXG4gICAgICogICAgICAgIE9wdGlvbmFsIC0gYW5kIGNvbXBvdW5kZWQgLSBsYXN0IHN0cmluZyBlcnJvciB0aGF0IGNhdXNlZCBhIGZhaWx1cmUgaW4gZXN0YWJsaXNoaW5nIGEgc3VwcG9ydGVkIGluc3RhbmNlLiBUaGlzIGVycm9yIGlzIGRlbGl2ZXJlZCBvbiB0aGUgcmVqZWN0aW9uIG9mIHRoZSBgUHJvbWlzZWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHB2dCh0aGlzKS5maW5kID0gKGl0ZXJhdG9yLCBtYXAsIG9wdGlvbnMsIHByb21pc2UsIGluaXRGbiA9IG51bGwsIGxhc3RFcnJvciA9IG51bGwpID0+IHtcbiAgICAgIGNvbnN0IFt0eXBlLCBJbXBsXSA9IHB2dCh0aGlzKS5uZXh0KGl0ZXJhdG9yLCBtYXApXG4gICAgICBpZiAoIUltcGwpIHtcbiAgICAgICAgcHJvbWlzZS5yZWplY3QobGFzdEVycm9yKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGV0IHBcbiAgICAgICAgbGV0IHNyYyA9IG9wdGlvbnNbdHlwZV1cbiAgICAgICAgc3JjID0gc3JjIHx8IG9wdGlvbnNcbiAgICAgICAgaWYgKGluaXRGbikge1xuICAgICAgICAgIHAgPSBuZXcgSW1wbCgpW2luaXRGbl0oc3JjKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHAgPSBuZXcgSW1wbChzcmMpXG4gICAgICAgIH1cbiAgICAgICAgcC50aGVuKChjb25jcmV0ZSkgPT4ge1xuICAgICAgICAgIHByb21pc2UucmVzb2x2ZShjb25jcmV0ZSlcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVycm9yID0+IHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuICAgICAgICAgIGxhc3RFcnJvciA9IGVycm9yXG4gICAgICAgICAgcHZ0KHRoaXMpLmZpbmQoaXRlcmF0b3IsIG1hcCwgb3B0aW9ucywgcHJvbWlzZSwgaW5pdEZuLCBsYXN0RXJyb3IpXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSXRlcmF0ZSBuZXh0IGluIG9yZGVyLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBwdnQodGhpcykubmV4dCA9IChvcmRlciwgbWFwKSA9PiB7XG4gICAgICBsZXQgSW1wbFxuICAgICAgbGV0IGtleVxuICAgICAgY29uc3QgbmV4dCA9IG9yZGVyLm5leHQoKVxuICAgICAgaWYgKCFuZXh0LmRvbmUpIHtcbiAgICAgICAga2V5ID0gbmV4dC52YWx1ZVxuICAgICAgICBJbXBsID0gbWFwLmdldChrZXkpXG4gICAgICB9XG4gICAgICByZXR1cm4gW2tleSwgSW1wbF1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBsb2NhdGUgc3VwcG9ydGVkIGltcGxlbWVudGF0aW9uIGFuZCBpbml0aWFsaXplIGl0LCByZXNvbHZpbmcgdGhlIGBQcm9taXNlYCB3aXRoIHRoZSBpbnN0YW5jZS5cbiAgICpcbiAgICogQHBhcmFtIHtBcnJheX0gb3JkZXJcbiAgICogQHBhcmFtIHtPYmplY3R9IG1hcFxuICAgKiAgICAgICAgTWFwIG9mIENsYXNzIHRvIG9yZGVyIHR5cGUuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqICAgICAgICBJbml0aWFsaXphdGlvbiBvYmplY3QgdG8gcGFzcyB0byBjb25zdHJ1Y3RvciBvZiBDbGFzcyBpbiBicm93c2VyIHRlc3Qgb2Ygc3VwcG9ydC5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaW5pdEZuXG4gICAqICAgICAgICBPcHRpb25hbCBpbml0aWFsaXphdGlvbiBmdW5jdGlvbiB0byBpbnZva2Ugd2l0aCB0aGUgYG9wdGlvbnNgIGNvbmZpZy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIGNyZWF0ZSAob3JkZXIsIG1hcCwgb3B0aW9ucywgaW5pdEZuID0gbnVsbCkge1xuICAgIGNvbnN0IHByb21pc2UgPSBuZXcgRGVmZXJyZWRQcm9taXNlKClcbiAgICBwdnQodGhpcykuZmluZCh0aGlzLmxpc3RvcmRlcihvcmRlci5zbGljZSgpKSwgbWFwLCBvcHRpb25zLCBwcm9taXNlLCBpbml0Rm4pXG4gICAgcmV0dXJuIHByb21pc2UucHJvbWlzZVxuICB9XG5cbn1cblxuZXhwb3J0IGRlZmF1bHQgSW1wbEZhY3RvcnlPcmRlclxuXG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvanMvdXRpbC9pbXBsLWZhY3Rvcnktb3JkZXIuanMiLCIndXNlIHN0cmljdCdcblxuLy8gaHR0cDovL2Jsb2cuY2FyYm9uZml2ZS5jb20vMjAxNS8wMS8xNC9nZXR0aW4tZnJlYWt5LWZ1bmN0aW9uYWwtd2N1cnJpZWQtamF2YXNjcmlwdC9cbi8qKlxuICogQmFzaWMgY3VycnkgaW1wbGVtZW50YXRpb24uXG4gKlxuICogQHByaXZhdGVcbiAqL1xuZXhwb3J0IGNvbnN0IGN1cnJ5ID0gKGZ4KSA9PiB7XG4gIGxldCBhcml0eSA9IGZ4Lmxlbmd0aDtcbiAgcmV0dXJuIGZ1bmN0aW9uIGYxKCkge1xuICAgIGNvbnN0IGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDApO1xuICAgIGlmIChhcmdzLmxlbmd0aCA+PSBhcml0eSkge1xuICAgICAgcmV0dXJuIGZ4LmFwcGx5KG51bGwsIGFyZ3MpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbiBmMigpIHtcbiAgICAgICAgY29uc3QgYXJnczIgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDApO1xuICAgICAgICByZXR1cm4gZjEuYXBwbHkobnVsbCwgYXJncy5jb25jYXQoYXJnczIpKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG59XG5cbi8qKlxuICogQmFzaWMgZmlsdGVyIGltcGxlbWVudGF0aW9uLlxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmV4cG9ydCBjb25zdCBmaWx0ZXIgPSBjdXJyeSgoZm4sIGxpc3QpID0+IHtcbiAgdmFyIGlkeCA9IDA7XG4gIHZhciBsZW4gPSBsaXN0Lmxlbmd0aDtcbiAgdmFyIHJlc3VsdCA9IFtdO1xuXG4gIHdoaWxlIChpZHggPCBsZW4pIHtcbiAgICBpZiAoZm4obGlzdFtpZHhdKSkge1xuICAgICAgcmVzdWx0W3Jlc3VsdC5sZW5ndGhdID0gbGlzdFtpZHhdO1xuICAgIH1cbiAgICBpZHggKz0gMTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufSlcblxuLyoqXG4gKiBDb252ZXJ0cyBhIHZhbHVlIHRvIGludGVnZXIuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHZhbHVlXG4gKiBAcmV0dXJucyB7TnVtYmVyfVxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmV4cG9ydCBjb25zdCB0b0ludCA9ICh2YWx1ZSkgPT4ge1xuICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiBwYXJzZUludCh2YWx1ZSwgMTApXG4gIH1cbiAgZWxzZSB7XG4gICAgcmV0dXJuIE1hdGgucm91bmQodmFsdWUpXG4gIH1cbn1cblxuLyoqXG4gKiBDaGVja3MgdHJ1dGh5LW5lc3Mgb2YgYHZhbHVlYCBhbmQgcmV0dXJucyBkZWZhdWx0IGlmIGZhbHNlLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSB2YWx1ZVxuICogQHBhcmFtIHtPYmplY3R9IGRlZmF1bHRWYWx1ZVxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmV4cG9ydCBjb25zdCBnZXRPckVsc2UgPSAodmFsdWUsIGRlZmF1bHRWYWx1ZSkgPT4ge1xuICByZXR1cm4gdmFsdWUgfHwgZGVmYXVsdFZhbHVlXG59XG5cbi8qKlxuICogQ2hlY2tzIHRydXRoeS1uZXNzIG9mIGB2YWx1ZWAgYXMgYSBOdW1iZXIgYW5kIHJldHVybnMgZGVmYXVsdCBpZiBmYWxzZS5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gdmFsdWVcbiAqIEBwYXJhbSB7T2JqZWN0fSBkZWZhdWx0VmFsdWVcbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5leHBvcnQgY29uc3QgZ2V0SW50T3JFbHNlID0gKHZhbHVlLCBkZWZhdWx0VmFsdWUpID0+IHtcbiAgcmV0dXJuICFpc05hTih0b0ludCh2YWx1ZSkpID8gdG9JbnQodmFsdWUpIDogZGVmYXVsdFZhbHVlXG59XG5cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9qcy91dGlsL2luZGV4LmpzIiwibW9kdWxlLmV4cG9ydHMgPSB7IFwiZGVmYXVsdFwiOiByZXF1aXJlKFwiY29yZS1qcy9saWJyYXJ5L2ZuL21hcFwiKSwgX19lc01vZHVsZTogdHJ1ZSB9O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9iYWJlbC1ydW50aW1lL2NvcmUtanMvbWFwLmpzXG4vLyBtb2R1bGUgaWQgPSA4OVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IHsgXCJkZWZhdWx0XCI6IHJlcXVpcmUoXCJjb3JlLWpzL2xpYnJhcnkvZm4vbnVtYmVyL2lzLWZpbml0ZVwiKSwgX19lc01vZHVsZTogdHJ1ZSB9O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9iYWJlbC1ydW50aW1lL2NvcmUtanMvbnVtYmVyL2lzLWZpbml0ZS5qc1xuLy8gbW9kdWxlIGlkID0gOTBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSB7IFwiZGVmYXVsdFwiOiByZXF1aXJlKFwiY29yZS1qcy9saWJyYXJ5L2ZuL29iamVjdC9kZWZpbmUtcHJvcGVydHlcIiksIF9fZXNNb2R1bGU6IHRydWUgfTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vYmFiZWwtcnVudGltZS9jb3JlLWpzL29iamVjdC9kZWZpbmUtcHJvcGVydHkuanNcbi8vIG1vZHVsZSBpZCA9IDkxXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9zZXRcIiksIF9fZXNNb2R1bGU6IHRydWUgfTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vYmFiZWwtcnVudGltZS9jb3JlLWpzL3NldC5qc1xuLy8gbW9kdWxlIGlkID0gOTJcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbnZhciBfZ2V0UHJvdG90eXBlT2YgPSByZXF1aXJlKFwiLi4vY29yZS1qcy9vYmplY3QvZ2V0LXByb3RvdHlwZS1vZlwiKTtcblxudmFyIF9nZXRQcm90b3R5cGVPZjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9nZXRQcm90b3R5cGVPZik7XG5cbnZhciBfZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yID0gcmVxdWlyZShcIi4uL2NvcmUtanMvb2JqZWN0L2dldC1vd24tcHJvcGVydHktZGVzY3JpcHRvclwiKTtcblxudmFyIF9nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZXhwb3J0cy5kZWZhdWx0ID0gZnVuY3Rpb24gZ2V0KG9iamVjdCwgcHJvcGVydHksIHJlY2VpdmVyKSB7XG4gIGlmIChvYmplY3QgPT09IG51bGwpIG9iamVjdCA9IEZ1bmN0aW9uLnByb3RvdHlwZTtcbiAgdmFyIGRlc2MgPSAoMCwgX2dldE93blByb3BlcnR5RGVzY3JpcHRvcjIuZGVmYXVsdCkob2JqZWN0LCBwcm9wZXJ0eSk7XG5cbiAgaWYgKGRlc2MgPT09IHVuZGVmaW5lZCkge1xuICAgIHZhciBwYXJlbnQgPSAoMCwgX2dldFByb3RvdHlwZU9mMi5kZWZhdWx0KShvYmplY3QpO1xuXG4gICAgaWYgKHBhcmVudCA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGdldChwYXJlbnQsIHByb3BlcnR5LCByZWNlaXZlcik7XG4gICAgfVxuICB9IGVsc2UgaWYgKFwidmFsdWVcIiBpbiBkZXNjKSB7XG4gICAgcmV0dXJuIGRlc2MudmFsdWU7XG4gIH0gZWxzZSB7XG4gICAgdmFyIGdldHRlciA9IGRlc2MuZ2V0O1xuXG4gICAgaWYgKGdldHRlciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHJldHVybiBnZXR0ZXIuY2FsbChyZWNlaXZlcik7XG4gIH1cbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2JhYmVsLXJ1bnRpbWUvaGVscGVycy9nZXQuanNcbi8vIG1vZHVsZSBpZCA9IDkzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIlwidXNlIHN0cmljdFwiO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG52YXIgX2Zyb20gPSByZXF1aXJlKFwiLi4vY29yZS1qcy9hcnJheS9mcm9tXCIpO1xuXG52YXIgX2Zyb20yID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZnJvbSk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmV4cG9ydHMuZGVmYXVsdCA9IGZ1bmN0aW9uIChhcnIpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkoYXJyKSkge1xuICAgIGZvciAodmFyIGkgPSAwLCBhcnIyID0gQXJyYXkoYXJyLmxlbmd0aCk7IGkgPCBhcnIubGVuZ3RoOyBpKyspIHtcbiAgICAgIGFycjJbaV0gPSBhcnJbaV07XG4gICAgfVxuXG4gICAgcmV0dXJuIGFycjI7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuICgwLCBfZnJvbTIuZGVmYXVsdCkoYXJyKTtcbiAgfVxufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vYmFiZWwtcnVudGltZS9oZWxwZXJzL3RvQ29uc3VtYWJsZUFycmF5LmpzXG4vLyBtb2R1bGUgaWQgPSA5NFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKipcbiAqICFUaGlzIGlzIGEgc3RyaXBwZWQgZG93biB2ZXJzaW9uIG9mIEJ1bnlhbiB0YXJnZXRlZCBzcGVjaWZpY2FsbHkgZm9yIHRoZSBicm93c2VyXG4gKlxuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxNCBUcmVudCBNaWNrLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogQ29weXJpZ2h0IChjKSAyMDE0IEpveWVudCBJbmMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKlxuICogVGhlIGJ1bnlhbiBsb2dnaW5nIGxpYnJhcnkgZm9yIG5vZGUuanMuXG4gKlxuICogLSotIG1vZGU6IGpzIC0qLVxuICogdmltOiBleHBhbmR0YWI6dHM9NDpzdz00XG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgVkVSU0lPTiA9ICcwLjIuMyc7XG5cbi8vIEJ1bnlhbiBsb2cgZm9ybWF0IHZlcnNpb24uIFRoaXMgYmVjb21lcyB0aGUgJ3YnIGZpZWxkIG9uIGFsbCBsb2cgcmVjb3Jkcy5cbi8vIGAwYCBpcyB1bnRpbCBJIHJlbGVhc2UgYSB2ZXJzaW9uICcxLjAuMCcgb2Ygbm9kZS1idW55YW4uIFRoZXJlYWZ0ZXIsXG4vLyBzdGFydGluZyB3aXRoIGAxYCwgdGhpcyB3aWxsIGJlIGluY3JlbWVudGVkIGlmIHRoZXJlIGlzIGFueSBiYWNrd2FyZFxuLy8gaW5jb21wYXRpYmxlIGNoYW5nZSB0byB0aGUgbG9nIHJlY29yZCBmb3JtYXQuIERldGFpbHMgd2lsbCBiZSBpblxuLy8gJ0NIQU5HRVMubWQnICh0aGUgY2hhbmdlIGxvZykuXG52YXIgTE9HX1ZFUlNJT04gPSAwO1xuXG4vLy0tLS0gSW50ZXJuYWwgc3VwcG9ydCBzdHVmZlxuXG4vKipcbiAqIEEgc2hhbGxvdyBjb3B5IG9mIGFuIG9iamVjdC4gQnVueWFuIGxvZ2dpbmcgYXR0ZW1wdHMgdG8gbmV2ZXIgY2F1c2VcbiAqIGV4Y2VwdGlvbnMsIHNvIHRoaXMgZnVuY3Rpb24gYXR0ZW1wdHMgdG8gaGFuZGxlIG5vbi1vYmplY3RzIGdyYWNlZnVsbHkuXG4gKi9cbmZ1bmN0aW9uIG9iakNvcHkob2JqKSB7XG4gICAgaWYgKHR5cGVvZiBvYmogPT09ICd1bmRlZmluZWQnIHx8IG9iaiA9PT0gbnVsbCkgeyAgLy8gbnVsbCBvciB1bmRlZmluZWRcbiAgICAgICAgcmV0dXJuIG9iajtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkge1xuICAgICAgICByZXR1cm4gb2JqLnNsaWNlKCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgKG9iaikgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIHZhciBjb3B5ID0ge307XG4gICAgICAgIE9iamVjdC5rZXlzKG9iaikuZm9yRWFjaChmdW5jdGlvbiAoaykge1xuICAgICAgICAgICAgY29weVtrXSA9IG9ialtrXTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBjb3B5O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBvYmo7XG4gICAgfVxufVxuXG52YXIgZm9ybWF0ID0gZnVuY3Rpb24oZikge1xuXG4gICAgaWYoZiA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gJ251bGwnO1xuICAgIH1cblxuICAgIGlmKHR5cGVvZiBmICE9PSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gZi50b1N0cmluZygpO1xuICAgIH1cbiAgICB2YXIgZm9ybWF0UmVnRXhwID0gLyVbc2RqJV0vZztcblxuICAgIHZhciBpID0gMTtcbiAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICB2YXIgbGVuID0gYXJncy5sZW5ndGg7XG4gICAgdmFyIHN0ciA9IFN0cmluZyhmKS5yZXBsYWNlKGZvcm1hdFJlZ0V4cCwgZnVuY3Rpb24oeCkge1xuICAgICAgICBpZiAoeCA9PT0gJyUlJykge1xuICAgICAgICAgICAgcmV0dXJuICclJztcbiAgICAgICAgfVxuICAgICAgICBpZiAoaSA+PSBsZW4pIHtcbiAgICAgICAgICAgIHJldHVybiB4O1xuICAgICAgICB9XG4gICAgICAgIHN3aXRjaCAoeCkge1xuICAgICAgICAgICAgY2FzZSAnJXMnOiByZXR1cm4gU3RyaW5nKGFyZ3NbaSsrXSk7XG4gICAgICAgICAgICBjYXNlICclZCc6IHJldHVybiBOdW1iZXIoYXJnc1tpKytdKTtcbiAgICAgICAgICAgIGNhc2UgJyVqJzpcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoYXJnc1tpKytdKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChfKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW0NpcmN1bGFyXSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4geDtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIGZvciAodmFyIHggPSBhcmdzW2ldOyBpIDwgbGVuOyB4ID0gYXJnc1srK2ldKSB7XG4gICAgICAgIHN0ciArPSAnICcgKyB4O1xuICAgIH1cbiAgICByZXR1cm4gc3RyO1xufTtcblxuLyoqXG4gKiBHYXRoZXIgc29tZSBjYWxsZXIgaW5mbyAzIHN0YWNrIGxldmVscyB1cC5cbiAqIFNlZSA8aHR0cDovL2NvZGUuZ29vZ2xlLmNvbS9wL3Y4L3dpa2kvSmF2YVNjcmlwdFN0YWNrVHJhY2VBcGk+LlxuICovXG5mdW5jdGlvbiBnZXRDYWxsZXIzSW5mbygpIHtcbiAgICB2YXIgb2JqID0ge307XG4gICAgdmFyIHNhdmVMaW1pdCA9IEVycm9yLnN0YWNrVHJhY2VMaW1pdDtcbiAgICB2YXIgc2F2ZVByZXBhcmUgPSBFcnJvci5wcmVwYXJlU3RhY2tUcmFjZTtcbiAgICBFcnJvci5zdGFja1RyYWNlTGltaXQgPSAzO1xuICAgIC8vRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgZ2V0Q2FsbGVyM0luZm8pO1xuXG4gICAgRXJyb3IucHJlcGFyZVN0YWNrVHJhY2UgPSBmdW5jdGlvbiAoXywgc3RhY2spIHtcbiAgICAgICAgdmFyIGNhbGxlciA9IHN0YWNrWzJdO1xuICAgICAgICBvYmouZmlsZSA9IGNhbGxlci5nZXRGaWxlTmFtZSgpO1xuICAgICAgICBvYmoubGluZSA9IGNhbGxlci5nZXRMaW5lTnVtYmVyKCk7XG4gICAgICAgIHZhciBmdW5jID0gY2FsbGVyLmdldEZ1bmN0aW9uTmFtZSgpO1xuICAgICAgICBpZiAoZnVuYykge1xuICAgICAgICAgICAgb2JqLmZ1bmMgPSBmdW5jO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBFcnJvci5zdGFja1RyYWNlTGltaXQgPSBzYXZlTGltaXQ7XG4gICAgRXJyb3IucHJlcGFyZVN0YWNrVHJhY2UgPSBzYXZlUHJlcGFyZTtcbiAgICByZXR1cm4gb2JqO1xufVxuXG5cbmZ1bmN0aW9uIF9pbmRlbnQocywgaW5kZW50KSB7XG4gICAgaWYgKCFpbmRlbnQpIHtcbiAgICAgICAgaW5kZW50ID0gJyAgICAnO1xuICAgIH1cbiAgICB2YXIgbGluZXMgPSBzLnNwbGl0KC9cXHI/XFxuL2cpO1xuICAgIHJldHVybiBpbmRlbnQgKyBsaW5lcy5qb2luKCdcXG4nICsgaW5kZW50KTtcbn1cblxuXG4vKipcbiAqIFdhcm4gYWJvdXQgYW4gYnVueWFuIHByb2Nlc3NpbmcgZXJyb3IuXG4gKlxuICogQHBhcmFtIG1zZyB7U3RyaW5nfSBNZXNzYWdlIHdpdGggd2hpY2ggdG8gd2Fybi5cbiAqIEBwYXJhbSBkZWR1cEtleSB7U3RyaW5nfSBPcHRpb25hbC4gQSBzaG9ydCBzdHJpbmcga2V5IGZvciB0aGlzIHdhcm5pbmcgdG9cbiAqICAgICAgaGF2ZSBpdHMgd2FybmluZyBvbmx5IHByaW50ZWQgb25jZS5cbiAqL1xuZnVuY3Rpb24gX3dhcm4obXNnLCBkZWR1cEtleSkge1xuICAgIGlmIChkZWR1cEtleSkge1xuICAgICAgICBpZiAoX3dhcm5lZFtkZWR1cEtleV0pIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBfd2FybmVkW2RlZHVwS2V5XSA9IHRydWU7XG4gICAgfVxuICAgIGNvbnNvbGUuZXJyb3IobXNnICsgJ1xcbicpO1xufVxuZnVuY3Rpb24gX2hhdmVXYXJuZWQoZGVkdXBLZXkpIHtcbiAgICByZXR1cm4gX3dhcm5lZFtkZWR1cEtleV07XG59XG52YXIgX3dhcm5lZCA9IHt9O1xuXG5cbmZ1bmN0aW9uIENvbnNvbGVSYXdTdHJlYW0oKSB7XG59XG5Db25zb2xlUmF3U3RyZWFtLnByb3RvdHlwZS53cml0ZSA9IGZ1bmN0aW9uIChyZWMpIHtcbiAgICBpZiAocmVjLmxldmVsIDwgSU5GTykge1xuICAgICAgICBjb25zb2xlLmxvZyhyZWMpO1xuICAgIH0gZWxzZSBpZiAocmVjLmxldmVsIDwgV0FSTikge1xuICAgICAgICBjb25zb2xlLmluZm8ocmVjKTtcbiAgICB9IGVsc2UgaWYgKHJlYy5sZXZlbCA8IEVSUk9SKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihyZWMpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IocmVjKTtcbiAgICB9XG5cbiAgICBpZihyZWMuZXJyICYmIHJlYy5lcnIuc3RhY2spIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihyZWMuZXJyLnN0YWNrKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBDb25zb2xlRm9ybWF0dGVkU3RyZWFtKCkge31cbkNvbnNvbGVGb3JtYXR0ZWRTdHJlYW0ucHJvdG90eXBlLndyaXRlID0gZnVuY3Rpb24gKHJlYykge1xuXG4gICAgdmFyIGxldmVsQ3NzLCBkZWZhdWx0Q3NzID0gJ2NvbG9yOiBEaW1HcmF5JywgbXNnQ3NzID0gJ2NvbG9yOiBTdGVlbEJsdWUnO1xuXG4gICAgaWYgKHJlYy5sZXZlbCA8IERFQlVHKSB7XG4gICAgICAgIGxldmVsQ3NzID0gJ2NvbG9yOiBEZWVwUGluayc7XG4gICAgfSBlbHNlIGlmIChyZWMubGV2ZWwgPCBJTkZPKSB7XG4gICAgICAgIGxldmVsQ3NzID0gJ2NvbG9yOiBHb2xkZW5Sb2QnO1xuICAgIH0gZWxzZSBpZiAocmVjLmxldmVsIDwgV0FSTikge1xuICAgICAgICBsZXZlbENzcyA9ICdjb2xvcjogRGFya1R1cnF1b2lzZSc7XG4gICAgfSBlbHNlIGlmIChyZWMubGV2ZWwgPCBFUlJPUikge1xuICAgICAgICBsZXZlbENzcyA9ICdjb2xvcjogUHVycGxlJztcbiAgICB9IGVsc2UgaWYgKHJlYy5sZXZlbCA8IEZBVEFMKSB7XG4gICAgICAgIGxldmVsQ3NzID0gJ2NvbG9yOiBDcmltc29uJztcbiAgICB9IGVsc2Uge1xuICAgICAgICBsZXZlbENzcyA9ICdjb2xvcjogQmxhY2snO1xuICAgIH1cblxuICAgIHZhciBsb2dnZXJOYW1lID0gcmVjLmNoaWxkTmFtZSA/IHJlYy5uYW1lICsgJy8nICsgcmVjLmNoaWxkTmFtZSA6IHJlYy5uYW1lO1xuXG4gICAgLy9nZXQgbGV2ZWwgbmFtZSBhbmQgcGFkIHN0YXJ0IHdpdGggc3BhY3NcbiAgICB2YXIgbGV2ZWxOYW1lID0gbmFtZUZyb21MZXZlbFtyZWMubGV2ZWxdLnRvVXBwZXJDYXNlKCk7XG4gICAgbGV2ZWxOYW1lID0gQXJyYXkoNiAtIGxldmVsTmFtZS5sZW5ndGgpLmpvaW4oJyAnKSArIGxldmVsTmFtZTtcblxuICAgIGZ1bmN0aW9uIHBhZFplcm9zKG51bWJlciwgbGVuKSB7XG4gICAgICAgIHJldHVybiBBcnJheSgobGVuICsgMSkgLSAobnVtYmVyICsgJycpLmxlbmd0aCkuam9pbignMCcpICsgbnVtYmVyO1xuICAgIH1cblxuICAgIGNvbnNvbGUubG9nKCdbJXM6JXM6JXM6JXNdICVjJXMlYzogJXM6ICVjJXMnLFxuICAgICAgICBwYWRaZXJvcyhyZWMudGltZS5nZXRIb3VycygpLCAyKSwgcGFkWmVyb3MocmVjLnRpbWUuZ2V0TWludXRlcygpLCAyKSxcbiAgICAgICAgcGFkWmVyb3MocmVjLnRpbWUuZ2V0U2Vjb25kcygpLCAyKSwgcGFkWmVyb3MocmVjLnRpbWUuZ2V0TWlsbGlzZWNvbmRzKCksIDQpLFxuICAgICAgICBsZXZlbENzcywgbGV2ZWxOYW1lLFxuICAgICAgICBkZWZhdWx0Q3NzLCBsb2dnZXJOYW1lLFxuICAgICAgICBtc2dDc3MsIHJlYy5tc2cpO1xuICAgIGlmKHJlYy5lcnIgJiYgcmVjLmVyci5zdGFjaykge1xuICAgICAgICBjb25zb2xlLmxvZygnJWMlcywnLCBsZXZlbENzcywgcmVjLmVyci5zdGFjayk7XG4gICAgfVxufTtcblxuLy8tLS0tIExldmVsc1xuXG52YXIgVFJBQ0UgPSAxMDtcbnZhciBERUJVRyA9IDIwO1xudmFyIElORk8gPSAzMDtcbnZhciBXQVJOID0gNDA7XG52YXIgRVJST1IgPSA1MDtcbnZhciBGQVRBTCA9IDYwO1xuXG52YXIgbGV2ZWxGcm9tTmFtZSA9IHtcbiAgICAndHJhY2UnOiBUUkFDRSxcbiAgICAnZGVidWcnOiBERUJVRyxcbiAgICAnaW5mbyc6IElORk8sXG4gICAgJ3dhcm4nOiBXQVJOLFxuICAgICdlcnJvcic6IEVSUk9SLFxuICAgICdmYXRhbCc6IEZBVEFMXG59O1xudmFyIG5hbWVGcm9tTGV2ZWwgPSB7fTtcbk9iamVjdC5rZXlzKGxldmVsRnJvbU5hbWUpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgICBuYW1lRnJvbUxldmVsW2xldmVsRnJvbU5hbWVbbmFtZV1dID0gbmFtZTtcbn0pO1xuXG5cbi8qKlxuICogUmVzb2x2ZSBhIGxldmVsIG51bWJlciwgbmFtZSAodXBwZXIgb3IgbG93ZXJjYXNlKSB0byBhIGxldmVsIG51bWJlciB2YWx1ZS5cbiAqXG4gKiBAYXBpIHB1YmxpY1xuICovXG5mdW5jdGlvbiByZXNvbHZlTGV2ZWwobmFtZU9yTnVtKSB7XG4gICAgdmFyIGxldmVsID0gKHR5cGVvZiAobmFtZU9yTnVtKSA9PT0gJ3N0cmluZycgPyBsZXZlbEZyb21OYW1lW25hbWVPck51bS50b0xvd2VyQ2FzZSgpXSA6IG5hbWVPck51bSk7XG4gICAgcmV0dXJuIGxldmVsO1xufVxuXG5cbi8vLS0tLSBMb2dnZXIgY2xhc3NcblxuLyoqXG4gKiBDcmVhdGUgYSBMb2dnZXIgaW5zdGFuY2UuXG4gKlxuICogQHBhcmFtIG9wdGlvbnMge09iamVjdH0gU2VlIGRvY3VtZW50YXRpb24gZm9yIGZ1bGwgZGV0YWlscy4gQXQgbWluaW11bVxuICogICAgdGhpcyBtdXN0IGluY2x1ZGUgYSAnbmFtZScgc3RyaW5nIGtleS4gQ29uZmlndXJhdGlvbiBrZXlzOlxuICogICAgICAtIGBzdHJlYW1zYDogc3BlY2lmeSB0aGUgbG9nZ2VyIG91dHB1dCBzdHJlYW1zLiBUaGlzIGlzIGFuIGFycmF5IG9mXG4gKiAgICAgICAgb2JqZWN0cyB3aXRoIHRoZXNlIGZpZWxkczpcbiAqICAgICAgICAgIC0gYHR5cGVgOiBUaGUgc3RyZWFtIHR5cGUuIFNlZSBSRUFETUUubWQgZm9yIGZ1bGwgZGV0YWlscy5cbiAqICAgICAgICAgICAgT2Z0ZW4gdGhpcyBpcyBpbXBsaWVkIGJ5IHRoZSBvdGhlciBmaWVsZHMuIEV4YW1wbGVzIGFyZVxuICogICAgICAgICAgICAnZmlsZScsICdzdHJlYW0nIGFuZCBcInJhd1wiLlxuICogICAgICAgICAgLSBgbGV2ZWxgOiBEZWZhdWx0cyB0byAnaW5mbycuXG4gKiAgICAgICAgICAtIGBwYXRoYCBvciBgc3RyZWFtYDogVGhlIHNwZWNpZnkgdGhlIGZpbGUgcGF0aCBvciB3cml0ZWFibGVcbiAqICAgICAgICAgICAgc3RyZWFtIHRvIHdoaWNoIGxvZyByZWNvcmRzIGFyZSB3cml0dGVuLiBFLmcuXG4gKiAgICAgICAgICAgIGBzdHJlYW06IHByb2Nlc3Muc3Rkb3V0YC5cbiAqICAgICAgICAgIC0gYGNsb3NlT25FeGl0YCAoYm9vbGVhbik6IE9wdGlvbmFsLiBEZWZhdWx0IGlzIHRydWUgZm9yIGFcbiAqICAgICAgICAgICAgJ2ZpbGUnIHN0cmVhbSB3aGVuIGBwYXRoYCBpcyBnaXZlbiwgZmFsc2Ugb3RoZXJ3aXNlLlxuICogICAgICAgIFNlZSBSRUFETUUubWQgZm9yIGZ1bGwgZGV0YWlscy5cbiAqICAgICAgLSBgbGV2ZWxgOiBzZXQgdGhlIGxldmVsIGZvciBhIHNpbmdsZSBvdXRwdXQgc3RyZWFtIChjYW5ub3QgYmUgdXNlZFxuICogICAgICAgIHdpdGggYHN0cmVhbXNgKVxuICogICAgICAtIGBzdHJlYW1gOiB0aGUgb3V0cHV0IHN0cmVhbSBmb3IgYSBsb2dnZXIgd2l0aCBqdXN0IG9uZSwgZS5nLlxuICogICAgICAgIGBwcm9jZXNzLnN0ZG91dGAgKGNhbm5vdCBiZSB1c2VkIHdpdGggYHN0cmVhbXNgKVxuICogICAgICAtIGBzZXJpYWxpemVyc2A6IG9iamVjdCBtYXBwaW5nIGxvZyByZWNvcmQgZmllbGQgbmFtZXMgdG9cbiAqICAgICAgICBzZXJpYWxpemluZyBmdW5jdGlvbnMuIFNlZSBSRUFETUUubWQgZm9yIGRldGFpbHMuXG4gKiAgICAgIC0gYHNyY2A6IEJvb2xlYW4gKGRlZmF1bHQgZmFsc2UpLiBTZXQgdHJ1ZSB0byBlbmFibGUgJ3NyYycgYXV0b21hdGljXG4gKiAgICAgICAgZmllbGQgd2l0aCBsb2cgY2FsbCBzb3VyY2UgaW5mby5cbiAqICAgIEFsbCBvdGhlciBrZXlzIGFyZSBsb2cgcmVjb3JkIGZpZWxkcy5cbiAqXG4gKiBBbiBhbHRlcm5hdGl2ZSAqaW50ZXJuYWwqIGNhbGwgc2lnbmF0dXJlIGlzIHVzZWQgZm9yIGNyZWF0aW5nIGEgY2hpbGQ6XG4gKiAgICBuZXcgTG9nZ2VyKDxwYXJlbnQgbG9nZ2VyPiwgPGNoaWxkIG9wdGlvbnM+WywgPGNoaWxkIG9wdHMgYXJlIHNpbXBsZT5dKTtcbiAqXG4gKiBAcGFyYW0gX2NoaWxkU2ltcGxlIChCb29sZWFuKSBBbiBhc3NlcnRpb24gdGhhdCB0aGUgZ2l2ZW4gYF9jaGlsZE9wdGlvbnNgXG4gKiAgICAoYSkgb25seSBhZGQgZmllbGRzIChubyBjb25maWcpIGFuZCAoYikgbm8gc2VyaWFsaXphdGlvbiBoYW5kbGluZyBpc1xuICogICAgcmVxdWlyZWQgZm9yIHRoZW0uIElPVywgdGhpcyBpcyBhIGZhc3QgcGF0aCBmb3IgZnJlcXVlbnQgY2hpbGRcbiAqICAgIGNyZWF0aW9uLlxuICovXG5mdW5jdGlvbiBMb2dnZXIob3B0aW9ucywgX2NoaWxkT3B0aW9ucywgX2NoaWxkU2ltcGxlKSB7XG4gICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIExvZ2dlcikpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBMb2dnZXIob3B0aW9ucywgX2NoaWxkT3B0aW9ucyk7XG4gICAgfVxuXG4gICAgLy8gSW5wdXQgYXJnIHZhbGlkYXRpb24uXG4gICAgdmFyIHBhcmVudDtcbiAgICBpZiAoX2NoaWxkT3B0aW9ucyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHBhcmVudCA9IG9wdGlvbnM7XG4gICAgICAgIG9wdGlvbnMgPSBfY2hpbGRPcHRpb25zO1xuICAgICAgICBpZiAoIShwYXJlbnQgaW5zdGFuY2VvZiBMb2dnZXIpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgICAgICAgICdpbnZhbGlkIExvZ2dlciBjcmVhdGlvbjogZG8gbm90IHBhc3MgYSBzZWNvbmQgYXJnJyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFvcHRpb25zKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ29wdGlvbnMgKG9iamVjdCkgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG4gICAgaWYgKCFwYXJlbnQpIHtcbiAgICAgICAgaWYgKCFvcHRpb25zLm5hbWUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ29wdGlvbnMubmFtZSAoc3RyaW5nKSBpcyByZXF1aXJlZCcpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKG9wdGlvbnMubmFtZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICAgICAgICAgICAnaW52YWxpZCBvcHRpb25zLm5hbWU6IGNoaWxkIGNhbm5vdCBzZXQgbG9nZ2VyIG5hbWUnKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAob3B0aW9ucy5zdHJlYW0gJiYgb3B0aW9ucy5zdHJlYW1zKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2Nhbm5vdCBtaXggXCJzdHJlYW1zXCIgYW5kIFwic3RyZWFtXCIgb3B0aW9ucycpO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy5zdHJlYW1zICYmICFBcnJheS5pc0FycmF5KG9wdGlvbnMuc3RyZWFtcykpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignaW52YWxpZCBvcHRpb25zLnN0cmVhbXM6IG11c3QgYmUgYW4gYXJyYXknKTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMuc2VyaWFsaXplcnMgJiYgKHR5cGVvZiAob3B0aW9ucy5zZXJpYWxpemVycykgIT09ICdvYmplY3QnIHx8IEFycmF5LmlzQXJyYXkob3B0aW9ucy5zZXJpYWxpemVycykpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2ludmFsaWQgb3B0aW9ucy5zZXJpYWxpemVyczogbXVzdCBiZSBhbiBvYmplY3QnKTtcbiAgICB9XG5cbiAgICB2YXIgZmllbGRzLCBuYW1lLCBpO1xuXG4gICAgLy8gRmFzdCBwYXRoIGZvciBzaW1wbGUgY2hpbGQgY3JlYXRpb24uXG4gICAgaWYgKHBhcmVudCAmJiBfY2hpbGRTaW1wbGUpIHtcbiAgICAgICAgLy8gYF9pc1NpbXBsZUNoaWxkYCBpcyBhIHNpZ25hbCB0byBzdHJlYW0gY2xvc2UgaGFuZGxpbmcgdGhhdCB0aGlzIGNoaWxkXG4gICAgICAgIC8vIG93bnMgbm9uZSBvZiBpdHMgc3RyZWFtcy5cbiAgICAgICAgdGhpcy5faXNTaW1wbGVDaGlsZCA9IHRydWU7XG5cbiAgICAgICAgdGhpcy5fbGV2ZWwgPSBwYXJlbnQuX2xldmVsO1xuICAgICAgICB0aGlzLnN0cmVhbXMgPSBwYXJlbnQuc3RyZWFtcztcbiAgICAgICAgdGhpcy5zZXJpYWxpemVycyA9IHBhcmVudC5zZXJpYWxpemVycztcbiAgICAgICAgdGhpcy5zcmMgPSBwYXJlbnQuc3JjO1xuICAgICAgICBmaWVsZHMgPSB0aGlzLmZpZWxkcyA9IHt9O1xuICAgICAgICB2YXIgcGFyZW50RmllbGROYW1lcyA9IE9iamVjdC5rZXlzKHBhcmVudC5maWVsZHMpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcGFyZW50RmllbGROYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbmFtZSA9IHBhcmVudEZpZWxkTmFtZXNbaV07XG4gICAgICAgICAgICBmaWVsZHNbbmFtZV0gPSBwYXJlbnQuZmllbGRzW25hbWVdO1xuICAgICAgICB9XG4gICAgICAgIHZhciBuYW1lcyA9IE9iamVjdC5rZXlzKG9wdGlvbnMpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIG5hbWUgPSBuYW1lc1tpXTtcbiAgICAgICAgICAgIGZpZWxkc1tuYW1lXSA9IG9wdGlvbnNbbmFtZV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIE51bGwgdmFsdWVzLlxuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICBpZiAocGFyZW50KSB7XG4gICAgICAgIHRoaXMuX2xldmVsID0gcGFyZW50Ll9sZXZlbDtcbiAgICAgICAgdGhpcy5zdHJlYW1zID0gW107XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBwYXJlbnQuc3RyZWFtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHMgPSBvYmpDb3B5KHBhcmVudC5zdHJlYW1zW2ldKTtcbiAgICAgICAgICAgIHMuY2xvc2VPbkV4aXQgPSBmYWxzZTsgLy8gRG9uJ3Qgb3duIHBhcmVudCBzdHJlYW0uXG4gICAgICAgICAgICB0aGlzLnN0cmVhbXMucHVzaChzKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNlcmlhbGl6ZXJzID0gb2JqQ29weShwYXJlbnQuc2VyaWFsaXplcnMpO1xuICAgICAgICB0aGlzLnNyYyA9IHBhcmVudC5zcmM7XG4gICAgICAgIHRoaXMuZmllbGRzID0gb2JqQ29weShwYXJlbnQuZmllbGRzKTtcbiAgICAgICAgaWYgKG9wdGlvbnMubGV2ZWwpIHtcbiAgICAgICAgICAgIHRoaXMubGV2ZWwob3B0aW9ucy5sZXZlbCk7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9sZXZlbCA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICAgICAgdGhpcy5zdHJlYW1zID0gW107XG4gICAgICAgIHRoaXMuc2VyaWFsaXplcnMgPSBudWxsO1xuICAgICAgICB0aGlzLnNyYyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmZpZWxkcyA9IHt9O1xuICAgIH1cblxuICAgIC8vIEhhbmRsZSAqY29uZmlnKiBvcHRpb25zIChpLmUuIG9wdGlvbnMgdGhhdCBhcmUgbm90IGp1c3QgcGxhaW4gZGF0YVxuICAgIC8vIGZvciBsb2cgcmVjb3JkcykuXG4gICAgaWYgKG9wdGlvbnMuc3RyZWFtKSB7XG4gICAgICAgIHNlbGYuYWRkU3RyZWFtKHtcbiAgICAgICAgICAgIHR5cGU6ICdzdHJlYW0nLFxuICAgICAgICAgICAgc3RyZWFtOiBvcHRpb25zLnN0cmVhbSxcbiAgICAgICAgICAgIGNsb3NlT25FeGl0OiBmYWxzZSxcbiAgICAgICAgICAgIGxldmVsOiBvcHRpb25zLmxldmVsXG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5zdHJlYW1zKSB7XG4gICAgICAgIG9wdGlvbnMuc3RyZWFtcy5mb3JFYWNoKGZ1bmN0aW9uIChzKSB7XG4gICAgICAgICAgICBzZWxmLmFkZFN0cmVhbShzLCBvcHRpb25zLmxldmVsKTtcbiAgICAgICAgfSk7XG4gICAgfSBlbHNlIGlmIChwYXJlbnQgJiYgb3B0aW9ucy5sZXZlbCkge1xuICAgICAgICB0aGlzLmxldmVsKG9wdGlvbnMubGV2ZWwpO1xuICAgIH0gZWxzZSBpZiAoIXBhcmVudCkge1xuXG4gICAgICAgIC8qXG4gICAgICAgICAqIEluIHRoZSBicm93c2VyIHdlJ2xsIGJlIGVtaXR0aW5nIHRvIGNvbnNvbGUubG9nIGJ5IGRlZmF1bHQuXG4gICAgICAgICAqIEFueSBjb25zb2xlLmxvZyB3b3J0aCBpdHMgc2FsdCB0aGVzZSBkYXlzIGNhbiBuaWNlbHkgcmVuZGVyXG4gICAgICAgICAqIGFuZCBpbnRyb3NwZWN0IG9iamVjdHMgKGUuZy4gdGhlIEZpcmVmb3ggYW5kIENocm9tZSBjb25zb2xlKVxuICAgICAgICAgKiBzbyBsZXQncyBlbWl0IHRoZSByYXcgbG9nIHJlY29yZC4gQXJlIHRoZXJlIGJyb3dzZXJzIGZvciB3aGljaFxuICAgICAgICAgKiB0aGF0IGJyZWFrcyB0aGluZ3M/XG4gICAgICAgICAqL1xuICAgICAgICBzZWxmLmFkZFN0cmVhbSh7XG4gICAgICAgICAgICB0eXBlOiAncmF3JyxcbiAgICAgICAgICAgIHN0cmVhbTogbmV3IENvbnNvbGVSYXdTdHJlYW0oKSxcbiAgICAgICAgICAgIGNsb3NlT25FeGl0OiBmYWxzZSxcbiAgICAgICAgICAgIGxldmVsOiBvcHRpb25zLmxldmVsXG4gICAgICAgIH0pO1xuXG4gICAgfVxuICAgIGlmIChvcHRpb25zLnNlcmlhbGl6ZXJzKSB7XG4gICAgICAgIHNlbGYuYWRkU2VyaWFsaXplcnMob3B0aW9ucy5zZXJpYWxpemVycyk7XG4gICAgfVxuICAgIGlmIChvcHRpb25zLnNyYykge1xuICAgICAgICB0aGlzLnNyYyA9IHRydWU7XG4gICAgfVxuXG4gICAgLy8gRmllbGRzLlxuICAgIC8vIFRoZXNlIGFyZSB0aGUgZGVmYXVsdCBmaWVsZHMgZm9yIGxvZyByZWNvcmRzIChtaW51cyB0aGUgYXR0cmlidXRlc1xuICAgIC8vIHJlbW92ZWQgaW4gdGhpcyBjb25zdHJ1Y3RvcikuIFRvIGFsbG93IHN0b3JpbmcgcmF3IGxvZyByZWNvcmRzXG4gICAgLy8gKHVucmVuZGVyZWQpLCBgdGhpcy5maWVsZHNgIG11c3QgbmV2ZXIgYmUgbXV0YXRlZC4gQ3JlYXRlIGEgY29weSBmb3JcbiAgICAvLyBhbnkgY2hhbmdlcy5cbiAgICBmaWVsZHMgPSBvYmpDb3B5KG9wdGlvbnMpO1xuICAgIGRlbGV0ZSBmaWVsZHMuc3RyZWFtO1xuICAgIGRlbGV0ZSBmaWVsZHMubGV2ZWw7XG4gICAgZGVsZXRlIGZpZWxkcy5zdHJlYW1zO1xuICAgIGRlbGV0ZSBmaWVsZHMuc2VyaWFsaXplcnM7XG4gICAgZGVsZXRlIGZpZWxkcy5zcmM7XG4gICAgaWYgKHRoaXMuc2VyaWFsaXplcnMpIHtcbiAgICAgICAgdGhpcy5fYXBwbHlTZXJpYWxpemVycyhmaWVsZHMpO1xuICAgIH1cbiAgICBPYmplY3Qua2V5cyhmaWVsZHMpLmZvckVhY2goZnVuY3Rpb24gKGspIHtcbiAgICAgICAgc2VsZi5maWVsZHNba10gPSBmaWVsZHNba107XG4gICAgfSk7XG59XG5cbi8qKlxuICogQWRkIGEgc3RyZWFtXG4gKlxuICogQHBhcmFtIHN0cmVhbSB7T2JqZWN0fS4gT2JqZWN0IHdpdGggdGhlc2UgZmllbGRzOlxuICogICAgLSBgdHlwZWA6IFRoZSBzdHJlYW0gdHlwZS4gU2VlIFJFQURNRS5tZCBmb3IgZnVsbCBkZXRhaWxzLlxuICogICAgICBPZnRlbiB0aGlzIGlzIGltcGxpZWQgYnkgdGhlIG90aGVyIGZpZWxkcy4gRXhhbXBsZXMgYXJlXG4gKiAgICAgICdmaWxlJywgJ3N0cmVhbScgYW5kIFwicmF3XCIuXG4gKiAgICAtIGBwYXRoYCBvciBgc3RyZWFtYDogVGhlIHNwZWNpZnkgdGhlIGZpbGUgcGF0aCBvciB3cml0ZWFibGVcbiAqICAgICAgc3RyZWFtIHRvIHdoaWNoIGxvZyByZWNvcmRzIGFyZSB3cml0dGVuLiBFLmcuXG4gKiAgICAgIGBzdHJlYW06IHByb2Nlc3Muc3Rkb3V0YC5cbiAqICAgIC0gYGxldmVsYDogT3B0aW9uYWwuIEZhbGxzIGJhY2sgdG8gYGRlZmF1bHRMZXZlbGAuXG4gKiAgICAtIGBjbG9zZU9uRXhpdGAgKGJvb2xlYW4pOiBPcHRpb25hbC4gRGVmYXVsdCBpcyB0cnVlIGZvciBhXG4gKiAgICAgICdmaWxlJyBzdHJlYW0gd2hlbiBgcGF0aGAgaXMgZ2l2ZW4sIGZhbHNlIG90aGVyd2lzZS5cbiAqICAgIFNlZSBSRUFETUUubWQgZm9yIGZ1bGwgZGV0YWlscy5cbiAqIEBwYXJhbSBkZWZhdWx0TGV2ZWwge051bWJlcnxTdHJpbmd9IE9wdGlvbmFsLiBBIGxldmVsIHRvIHVzZSBpZlxuICogICAgICBgc3RyZWFtLmxldmVsYCBpcyBub3Qgc2V0LiBJZiBuZWl0aGVyIGlzIGdpdmVuLCB0aGlzIGRlZmF1bHRzIHRvIElORk8uXG4gKi9cbkxvZ2dlci5wcm90b3R5cGUuYWRkU3RyZWFtID0gZnVuY3Rpb24gYWRkU3RyZWFtKHMsIGRlZmF1bHRMZXZlbCkge1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICBpZiAoZGVmYXVsdExldmVsID09PSBudWxsIHx8IGRlZmF1bHRMZXZlbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGRlZmF1bHRMZXZlbCA9IElORk87XG4gICAgfVxuXG4gICAgcyA9IG9iakNvcHkocyk7XG5cbiAgICAvLyBJbXBsaWNpdCAndHlwZScgZnJvbSBvdGhlciBhcmdzLlxuICAgIGlmICghcy50eXBlICYmIHMuc3RyZWFtKSB7XG4gICAgICAgIHMudHlwZSA9ICdyYXcnO1xuICAgIH1cbiAgICBzLnJhdyA9IChzLnR5cGUgPT09ICdyYXcnKTsgIC8vIFBFUkY6IEFsbG93IGZvciBmYXN0ZXIgY2hlY2sgaW4gYF9lbWl0YC5cblxuICAgIGlmIChzLmxldmVsKSB7XG4gICAgICAgIHMubGV2ZWwgPSByZXNvbHZlTGV2ZWwocy5sZXZlbCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcy5sZXZlbCA9IHJlc29sdmVMZXZlbChkZWZhdWx0TGV2ZWwpO1xuICAgIH1cbiAgICBpZiAocy5sZXZlbCA8IHNlbGYuX2xldmVsKSB7XG4gICAgICAgIHNlbGYuX2xldmVsID0gcy5sZXZlbDtcbiAgICB9XG5cbiAgICBzd2l0Y2ggKHMudHlwZSkge1xuICAgICAgICBjYXNlICdzdHJlYW0nOlxuICAgICAgICAgICAgaWYgKCFzLmNsb3NlT25FeGl0KSB7XG4gICAgICAgICAgICAgICAgcy5jbG9zZU9uRXhpdCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3Jhdyc6XG4gICAgICAgICAgICBpZiAoIXMuY2xvc2VPbkV4aXQpIHtcbiAgICAgICAgICAgICAgICBzLmNsb3NlT25FeGl0ID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3Vua25vd24gc3RyZWFtIHR5cGUgXCInICsgcy50eXBlICsgJ1wiJyk7XG4gICAgfVxuXG4gICAgc2VsZi5zdHJlYW1zLnB1c2gocyk7XG4gICAgZGVsZXRlIHNlbGYuaGF2ZU5vblJhd1N0cmVhbXM7ICAvLyByZXNldFxufTtcblxuXG4vKipcbiAqIEFkZCBzZXJpYWxpemVyc1xuICpcbiAqIEBwYXJhbSBzZXJpYWxpemVycyB7T2JqZWN0fSBPcHRpb25hbC4gT2JqZWN0IG1hcHBpbmcgbG9nIHJlY29yZCBmaWVsZCBuYW1lc1xuICogICAgdG8gc2VyaWFsaXppbmcgZnVuY3Rpb25zLiBTZWUgUkVBRE1FLm1kIGZvciBkZXRhaWxzLlxuICovXG5Mb2dnZXIucHJvdG90eXBlLmFkZFNlcmlhbGl6ZXJzID0gZnVuY3Rpb24gYWRkU2VyaWFsaXplcnMoc2VyaWFsaXplcnMpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICBpZiAoIXNlbGYuc2VyaWFsaXplcnMpIHtcbiAgICAgICAgc2VsZi5zZXJpYWxpemVycyA9IHt9O1xuICAgIH1cbiAgICBPYmplY3Qua2V5cyhzZXJpYWxpemVycykuZm9yRWFjaChmdW5jdGlvbiAoZmllbGQpIHtcbiAgICAgICAgdmFyIHNlcmlhbGl6ZXIgPSBzZXJpYWxpemVyc1tmaWVsZF07XG4gICAgICAgIGlmICh0eXBlb2YgKHNlcmlhbGl6ZXIpICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGZvcm1hdChcbiAgICAgICAgICAgICAgICAnaW52YWxpZCBzZXJpYWxpemVyIGZvciBcIiVzXCIgZmllbGQ6IG11c3QgYmUgYSBmdW5jdGlvbicsXG4gICAgICAgICAgICAgICAgZmllbGQpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNlbGYuc2VyaWFsaXplcnNbZmllbGRdID0gc2VyaWFsaXplcjtcbiAgICAgICAgfVxuICAgIH0pO1xufTtcblxuXG4vKipcbiAqIENyZWF0ZSBhIGNoaWxkIGxvZ2dlciwgdHlwaWNhbGx5IHRvIGFkZCBhIGZldyBsb2cgcmVjb3JkIGZpZWxkcy5cbiAqXG4gKiBUaGlzIGNhbiBiZSB1c2VmdWwgd2hlbiBwYXNzaW5nIGEgbG9nZ2VyIHRvIGEgc3ViLWNvbXBvbmVudCwgZS5nLiBhXG4gKiAnd3V6emxlJyBjb21wb25lbnQgb2YgeW91ciBzZXJ2aWNlOlxuICpcbiAqICAgIHZhciB3dXp6bGVMb2cgPSBsb2cuY2hpbGQoe2NvbXBvbmVudDogJ3d1enpsZSd9KVxuICogICAgdmFyIHd1enpsZSA9IG5ldyBXdXp6bGUoey4uLiwgbG9nOiB3dXp6bGVMb2d9KVxuICpcbiAqIFRoZW4gbG9nIHJlY29yZHMgZnJvbSB0aGUgd3V6emxlIGNvZGUgd2lsbCBoYXZlIHRoZSBzYW1lIHN0cnVjdHVyZSBhc1xuICogdGhlIGFwcCBsb2csICpwbHVzIHRoZSBjb21wb25lbnQ9J3d1enpsZScgZmllbGQqLlxuICpcbiAqIEBwYXJhbSBvcHRpb25zIHtPYmplY3R9IE9wdGlvbmFsLiBTZXQgb2Ygb3B0aW9ucyB0byBhcHBseSB0byB0aGUgY2hpbGQuXG4gKiAgICBBbGwgb2YgdGhlIHNhbWUgb3B0aW9ucyBmb3IgYSBuZXcgTG9nZ2VyIGFwcGx5IGhlcmUuIE5vdGVzOlxuICogICAgICAtIFRoZSBwYXJlbnQncyBzdHJlYW1zIGFyZSBpbmhlcml0ZWQgYW5kIGNhbm5vdCBiZSByZW1vdmVkIGluIHRoaXNcbiAqICAgICAgICBjYWxsLiBBbnkgZ2l2ZW4gYHN0cmVhbXNgIGFyZSAqYWRkZWQqIHRvIHRoZSBzZXQgaW5oZXJpdGVkIGZyb21cbiAqICAgICAgICB0aGUgcGFyZW50LlxuICogICAgICAtIFRoZSBwYXJlbnQncyBzZXJpYWxpemVycyBhcmUgaW5oZXJpdGVkLCB0aG91Z2ggY2FuIGVmZmVjdGl2ZWx5IGJlXG4gKiAgICAgICAgb3ZlcndyaXR0ZW4gYnkgdXNpbmcgZHVwbGljYXRlIGtleXMuXG4gKiAgICAgIC0gQ2FuIHVzZSBgbGV2ZWxgIHRvIHNldCB0aGUgbGV2ZWwgb2YgdGhlIHN0cmVhbXMgaW5oZXJpdGVkIGZyb21cbiAqICAgICAgICB0aGUgcGFyZW50LiBUaGUgbGV2ZWwgZm9yIHRoZSBwYXJlbnQgaXMgTk9UIGFmZmVjdGVkLlxuICogQHBhcmFtIHNpbXBsZSB7Qm9vbGVhbn0gT3B0aW9uYWwuIFNldCB0byB0cnVlIHRvIGFzc2VydCB0aGF0IGBvcHRpb25zYFxuICogICAgKGEpIG9ubHkgYWRkIGZpZWxkcyAobm8gY29uZmlnKSBhbmQgKGIpIG5vIHNlcmlhbGl6YXRpb24gaGFuZGxpbmcgaXNcbiAqICAgIHJlcXVpcmVkIGZvciB0aGVtLiBJT1csIHRoaXMgaXMgYSBmYXN0IHBhdGggZm9yIGZyZXF1ZW50IGNoaWxkXG4gKiAgICBjcmVhdGlvbi4gU2VlICd0b29scy90aW1lY2hpbGQuanMnIGZvciBudW1iZXJzLlxuICovXG5Mb2dnZXIucHJvdG90eXBlLmNoaWxkID0gZnVuY3Rpb24gKG9wdGlvbnMsIHNpbXBsZSkge1xuICAgIHJldHVybiBuZXcgKHRoaXMuY29uc3RydWN0b3IpKHRoaXMsIG9wdGlvbnMgfHwge30sIHNpbXBsZSk7XG59O1xuXG4vKipcbiAqIEdldC9zZXQgdGhlIGxldmVsIG9mIGFsbCBzdHJlYW1zIG9uIHRoaXMgbG9nZ2VyLlxuICpcbiAqIEdldCBVc2FnZTpcbiAqICAgIC8vIFJldHVybnMgdGhlIGN1cnJlbnQgbG9nIGxldmVsIChsb3dlc3QgbGV2ZWwgb2YgYWxsIGl0cyBzdHJlYW1zKS5cbiAqICAgIGxvZy5sZXZlbCgpIC0+IElORk9cbiAqXG4gKiBTZXQgVXNhZ2U6XG4gKiAgICBsb2cubGV2ZWwoSU5GTykgICAgICAgLy8gc2V0IGFsbCBzdHJlYW1zIHRvIGxldmVsIElORk9cbiAqICAgIGxvZy5sZXZlbCgnaW5mbycpICAgICAvLyBjYW4gdXNlICdpbmZvJyBldCBhbCBhbGlhc2VzXG4gKi9cbkxvZ2dlci5wcm90b3R5cGUubGV2ZWwgPSBmdW5jdGlvbiBsZXZlbCh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9sZXZlbDtcbiAgICB9XG4gICAgdmFyIG5ld0xldmVsID0gcmVzb2x2ZUxldmVsKHZhbHVlKTtcbiAgICB2YXIgbGVuID0gdGhpcy5zdHJlYW1zLmxlbmd0aDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIHRoaXMuc3RyZWFtc1tpXS5sZXZlbCA9IG5ld0xldmVsO1xuICAgIH1cbiAgICB0aGlzLl9sZXZlbCA9IG5ld0xldmVsO1xufTtcblxuXG4vKipcbiAqIEdldC9zZXQgdGhlIGxldmVsIG9mIGEgcGFydGljdWxhciBzdHJlYW0gb24gdGhpcyBsb2dnZXIuXG4gKlxuICogR2V0IFVzYWdlOlxuICogICAgLy8gUmV0dXJucyBhbiBhcnJheSBvZiB0aGUgbGV2ZWxzIG9mIGVhY2ggc3RyZWFtLlxuICogICAgbG9nLmxldmVscygpIC0+IFtUUkFDRSwgSU5GT11cbiAqXG4gKiAgICAvLyBSZXR1cm5zIGEgbGV2ZWwgb2YgdGhlIGlkZW50aWZpZWQgc3RyZWFtLlxuICogICAgbG9nLmxldmVscygwKSAtPiBUUkFDRSAgICAgIC8vIGxldmVsIG9mIHN0cmVhbSBhdCBpbmRleCAwXG4gKiAgICBsb2cubGV2ZWxzKCdmb28nKSAgICAgICAgICAgLy8gbGV2ZWwgb2Ygc3RyZWFtIHdpdGggbmFtZSAnZm9vJ1xuICpcbiAqIFNldCBVc2FnZTpcbiAqICAgIGxvZy5sZXZlbHMoMCwgSU5GTykgICAgICAgICAvLyBzZXQgbGV2ZWwgb2Ygc3RyZWFtIDAgdG8gSU5GT1xuICogICAgbG9nLmxldmVscygwLCAnaW5mbycpICAgICAgIC8vIGNhbiB1c2UgJ2luZm8nIGV0IGFsIGFsaWFzZXNcbiAqICAgIGxvZy5sZXZlbHMoJ2ZvbycsIFdBUk4pICAgICAvLyBzZXQgc3RyZWFtIG5hbWVkICdmb28nIHRvIFdBUk5cbiAqXG4gKiBTdHJlYW0gbmFtZXM6IFdoZW4gc3RyZWFtcyBhcmUgZGVmaW5lZCwgdGhleSBjYW4gb3B0aW9uYWxseSBiZSBnaXZlblxuICogYSBuYW1lLiBGb3IgZXhhbXBsZSxcbiAqICAgICAgIGxvZyA9IG5ldyBMb2dnZXIoe1xuICogICAgICAgICBzdHJlYW1zOiBbXG4gKiAgICAgICAgICAge1xuICogICAgICAgICAgICAgbmFtZTogJ2ZvbycsXG4gKiAgICAgICAgICAgICBwYXRoOiAnL3Zhci9sb2cvbXktc2VydmljZS9mb28ubG9nJ1xuICogICAgICAgICAgICAgbGV2ZWw6ICd0cmFjZSdcbiAqICAgICAgICAgICB9LFxuICogICAgICAgICAuLi5cbiAqXG4gKiBAcGFyYW0gbmFtZSB7U3RyaW5nfE51bWJlcn0gVGhlIHN0cmVhbSBpbmRleCBvciBuYW1lLlxuICogQHBhcmFtIHZhbHVlIHtOdW1iZXJ8U3RyaW5nfSBUaGUgbGV2ZWwgdmFsdWUgKElORk8pIG9yIGFsaWFzICgnaW5mbycpLlxuICogICAgSWYgbm90IGdpdmVuLCB0aGlzIGlzIGEgJ2dldCcgb3BlcmF0aW9uLlxuICogQHRocm93cyB7RXJyb3J9IElmIHRoZXJlIGlzIG5vIHN0cmVhbSB3aXRoIHRoZSBnaXZlbiBuYW1lLlxuICovXG5Mb2dnZXIucHJvdG90eXBlLmxldmVscyA9IGZ1bmN0aW9uIGxldmVscyhuYW1lLCB2YWx1ZSkge1xuICAgIGlmIChuYW1lID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RyZWFtcy5tYXAoXG4gICAgICAgICAgICBmdW5jdGlvbiAocykge1xuICAgICAgICAgICAgICAgIHJldHVybiBzLmxldmVsO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuICAgIHZhciBzdHJlYW07XG4gICAgaWYgKHR5cGVvZiAobmFtZSkgPT09ICdudW1iZXInKSB7XG4gICAgICAgIHN0cmVhbSA9IHRoaXMuc3RyZWFtc1tuYW1lXTtcbiAgICAgICAgaWYgKHN0cmVhbSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgc3RyZWFtIGluZGV4OiAnICsgbmFtZSk7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgbGVuID0gdGhpcy5zdHJlYW1zLmxlbmd0aDtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgdmFyIHMgPSB0aGlzLnN0cmVhbXNbaV07XG4gICAgICAgICAgICBpZiAocy5uYW1lID09PSBuYW1lKSB7XG4gICAgICAgICAgICAgICAgc3RyZWFtID0gcztcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIXN0cmVhbSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGZvcm1hdCgnbm8gc3RyZWFtIHdpdGggbmFtZSBcIiVzXCInLCBuYW1lKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIHN0cmVhbS5sZXZlbDtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgbmV3TGV2ZWwgPSByZXNvbHZlTGV2ZWwodmFsdWUpO1xuICAgICAgICBzdHJlYW0ubGV2ZWwgPSBuZXdMZXZlbDtcbiAgICAgICAgaWYgKG5ld0xldmVsIDwgdGhpcy5fbGV2ZWwpIHtcbiAgICAgICAgICAgIHRoaXMuX2xldmVsID0gbmV3TGV2ZWw7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5cbi8qKlxuICogQXBwbHkgcmVnaXN0ZXJlZCBzZXJpYWxpemVycyB0byB0aGUgYXBwcm9wcmlhdGUga2V5cyBpbiB0aGUgZ2l2ZW4gZmllbGRzLlxuICpcbiAqIFByZS1jb25kaXRpb246IFRoaXMgaXMgb25seSBjYWxsZWQgaWYgdGhlcmUgaXMgYXQgbGVhc3Qgb25lIHNlcmlhbGl6ZXIuXG4gKlxuICogQHBhcmFtIGZpZWxkcyAoT2JqZWN0KSBUaGUgbG9nIHJlY29yZCBmaWVsZHMuXG4gKiBAcGFyYW0gZXhjbHVkZUZpZWxkcyAoT2JqZWN0KSBPcHRpb25hbCBtYXBwaW5nIG9mIGtleXMgdG8gYHRydWVgIGZvclxuICogICAga2V5cyB0byBOT1QgYXBwbHkgYSBzZXJpYWxpemVyLlxuICovXG5Mb2dnZXIucHJvdG90eXBlLl9hcHBseVNlcmlhbGl6ZXJzID0gZnVuY3Rpb24gKGZpZWxkcywgZXhjbHVkZUZpZWxkcykge1xuICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgIC8vIENoZWNrIGVhY2ggc2VyaWFsaXplciBhZ2FpbnN0IHRoZXNlIChwcmVzdW1pbmcgbnVtYmVyIG9mIHNlcmlhbGl6ZXJzXG4gICAgLy8gaXMgdHlwaWNhbGx5IGxlc3MgdGhhbiBudW1iZXIgb2YgZmllbGRzKS5cbiAgICBPYmplY3Qua2V5cyh0aGlzLnNlcmlhbGl6ZXJzKS5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIGlmIChmaWVsZHNbbmFtZV0gPT09IHVuZGVmaW5lZCB8fFxuICAgICAgICAgICAgKGV4Y2x1ZGVGaWVsZHMgJiYgZXhjbHVkZUZpZWxkc1tuYW1lXSkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgZmllbGRzW25hbWVdID0gc2VsZi5zZXJpYWxpemVyc1tuYW1lXShmaWVsZHNbbmFtZV0pO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIF93YXJuKGZvcm1hdCgnYnVueWFuOiBFUlJPUjogRXhjZXB0aW9uIHRocm93biBmcm9tIHRoZSBcIiVzXCIgJyArXG4gICAgICAgICAgICAgICAgICAgICdCdW55YW4gc2VyaWFsaXplci4gVGhpcyBzaG91bGQgbmV2ZXIgaGFwcGVuLiBUaGlzIGlzIGEgYnVnJyArXG4gICAgICAgICAgICAgICAgICAgICdpbiB0aGF0IHNlcmlhbGl6ZXIgZnVuY3Rpb24uXFxuJXMnLFxuICAgICAgICAgICAgICAgIG5hbWUsIGVyci5zdGFjayB8fCBlcnIpKTtcbiAgICAgICAgICAgIGZpZWxkc1tuYW1lXSA9IGZvcm1hdCgnKEVycm9yIGluIEJ1bnlhbiBsb2cgXCIlc1wiIHNlcmlhbGl6ZXIgYnJva2UgZmllbGQuIFNlZSBzdGRlcnIgZm9yIGRldGFpbHMuKScsIG5hbWUpO1xuICAgICAgICB9XG4gICAgfSk7XG59O1xuXG5cbi8qKlxuICogRW1pdCBhIGxvZyByZWNvcmQuXG4gKlxuICogQHBhcmFtIHJlYyB7bG9nIHJlY29yZH1cbiAqIEBwYXJhbSBub2VtaXQge0Jvb2xlYW59IE9wdGlvbmFsLiBTZXQgdG8gdHJ1ZSB0byBza2lwIGVtaXNzaW9uXG4gKiAgICAgIGFuZCBqdXN0IHJldHVybiB0aGUgSlNPTiBzdHJpbmcuXG4gKi9cbkxvZ2dlci5wcm90b3R5cGUuX2VtaXQgPSBmdW5jdGlvbiAocmVjLCBub2VtaXQpIHtcbiAgICB2YXIgaTtcblxuICAgIC8vIExhemlseSBkZXRlcm1pbmUgaWYgdGhpcyBMb2dnZXIgaGFzIG5vbi0ncmF3JyBzdHJlYW1zLiBJZiB0aGVyZSBhcmVcbiAgICAvLyBhbnksIHRoZW4gd2UgbmVlZCB0byBzdHJpbmdpZnkgdGhlIGxvZyByZWNvcmQuXG4gICAgaWYgKHRoaXMuaGF2ZU5vblJhd1N0cmVhbXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLmhhdmVOb25SYXdTdHJlYW1zID0gZmFsc2U7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnN0cmVhbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5zdHJlYW1zW2ldLnJhdykge1xuICAgICAgICAgICAgICAgIHRoaXMuaGF2ZU5vblJhd1N0cmVhbXMgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gU3RyaW5naWZ5IHRoZSBvYmplY3QuIEF0dGVtcHQgdG8gd2Fybi9yZWNvdmVyIG9uIGVycm9yLlxuICAgIHZhciBzdHI7XG4gICAgaWYgKG5vZW1pdCB8fCB0aGlzLmhhdmVOb25SYXdTdHJlYW1zKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBzdHIgPSBKU09OLnN0cmluZ2lmeShyZWMsIHNhZmVDeWNsZXMoKSkgKyAnXFxuJztcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgdmFyIGRlZHVwS2V5ID0gZS5zdGFjay5zcGxpdCgvXFxuL2csIDIpLmpvaW4oJ1xcbicpO1xuICAgICAgICAgICAgX3dhcm4oJ2J1bnlhbjogRVJST1I6IEV4Y2VwdGlvbiBpbiAnICtcbiAgICAgICAgICAgICAgICAgICAgJ2BKU09OLnN0cmluZ2lmeShyZWMpYC4gWW91IGNhbiBpbnN0YWxsIHRoZSAnICtcbiAgICAgICAgICAgICAgICAgICAgJ1wic2FmZS1qc29uLXN0cmluZ2lmeVwiIG1vZHVsZSB0byBoYXZlIEJ1bnlhbiBmYWxsYmFjayAnICtcbiAgICAgICAgICAgICAgICAgICAgJ3RvIHNhZmVyIHN0cmluZ2lmaWNhdGlvbi4gUmVjb3JkOlxcbicgK1xuICAgICAgICAgICAgICAgICAgICBfaW5kZW50KGZvcm1hdCgnJXNcXG4lcycsIHJlYywgZS5zdGFjaykpLFxuICAgICAgICAgICAgICAgIGRlZHVwS2V5KTtcbiAgICAgICAgICAgIHN0ciA9IGZvcm1hdCgnKEV4Y2VwdGlvbiBpbiBKU09OLnN0cmluZ2lmeShyZWMpOiAlai4gU2VlIHN0ZGVyciBmb3IgZGV0YWlscy4pXFxuJywgZS5tZXNzYWdlKTtcblxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKG5vZW1pdCkge1xuICAgICAgICByZXR1cm4gc3RyO1xuICAgIH1cblxuXG4gICAgdmFyIGxldmVsID0gcmVjLmxldmVsO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnN0cmVhbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHMgPSB0aGlzLnN0cmVhbXNbaV07XG4gICAgICAgIGlmIChzLmxldmVsIDw9IGxldmVsKSB7XG4gICAgICAgICAgICBzLnN0cmVhbS53cml0ZShzLnJhdyA/IHJlYyA6IHN0cik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc3RyO1xufTtcblxuXG4vKipcbiAqIEJ1aWxkIGEgbG9nIGVtaXR0ZXIgZnVuY3Rpb24gZm9yIGxldmVsIG1pbkxldmVsLiBJLmUuIHRoaXMgaXMgdGhlXG4gKiBjcmVhdG9yIG9mIGBsb2cuaW5mb2AsIGBsb2cuZXJyb3JgLCBldGMuXG4gKi9cbmZ1bmN0aW9uIG1rTG9nRW1pdHRlcihtaW5MZXZlbCkge1xuICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBsb2cgPSB0aGlzO1xuXG4gICAgICAgIGZ1bmN0aW9uIG1rUmVjb3JkKGFyZ3MpIHtcbiAgICAgICAgICAgIHZhciBleGNsdWRlRmllbGRzO1xuICAgICAgICAgICAgaWYgKGFyZ3NbMF0gaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgICAgICAgIC8vIGBsb2cuPGxldmVsPihlcnIsIC4uLilgXG4gICAgICAgICAgICAgICAgZmllbGRzID0ge1xuICAgICAgICAgICAgICAgICAgICAvLyBVc2UgdGhpcyBMb2dnZXIncyBlcnIgc2VyaWFsaXplciwgaWYgZGVmaW5lZC5cbiAgICAgICAgICAgICAgICAgICAgZXJyOiAobG9nLnNlcmlhbGl6ZXJzICYmIGxvZy5zZXJpYWxpemVycy5lcnIgPyBsb2cuc2VyaWFsaXplcnMuZXJyKGFyZ3NbMF0pIDogTG9nZ2VyLnN0ZFNlcmlhbGl6ZXJzLmVycihhcmdzWzBdKSlcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGV4Y2x1ZGVGaWVsZHMgPSB7ZXJyOiB0cnVlfTtcbiAgICAgICAgICAgICAgICBpZiAoYXJncy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgbXNnQXJncyA9IFtmaWVsZHMuZXJyLm1lc3NhZ2VdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG1zZ0FyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmdzLCAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiAoYXJnc1swXSkgIT09ICdvYmplY3QnICYmIGFyZ3NbMF0gIT09IG51bGwgfHxcbiAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KGFyZ3NbMF0pKSB7XG4gICAgICAgICAgICAgICAgLy8gYGxvZy48bGV2ZWw+KG1zZywgLi4uKWBcbiAgICAgICAgICAgICAgICBmaWVsZHMgPSBudWxsO1xuICAgICAgICAgICAgICAgIG1zZ0FyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmdzKTtcbiAgICAgICAgICAgIH0gZWxzZSB7ICAvLyBgbG9nLjxsZXZlbD4oZmllbGRzLCBtc2csIC4uLilgXG4gICAgICAgICAgICAgICAgZmllbGRzID0gYXJnc1swXTtcbiAgICAgICAgICAgICAgICBtc2dBcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJncywgMSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJ1aWxkIHVwIHRoZSByZWNvcmQgb2JqZWN0LlxuICAgICAgICAgICAgdmFyIHJlYyA9IG9iakNvcHkobG9nLmZpZWxkcyk7XG4gICAgICAgICAgICByZWMubGV2ZWwgPSBtaW5MZXZlbDtcbiAgICAgICAgICAgIHZhciByZWNGaWVsZHMgPSAoZmllbGRzID8gb2JqQ29weShmaWVsZHMpIDogbnVsbCk7XG4gICAgICAgICAgICBpZiAocmVjRmllbGRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGxvZy5zZXJpYWxpemVycykge1xuICAgICAgICAgICAgICAgICAgICBsb2cuX2FwcGx5U2VyaWFsaXplcnMocmVjRmllbGRzLCBleGNsdWRlRmllbGRzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgT2JqZWN0LmtleXMocmVjRmllbGRzKS5mb3JFYWNoKGZ1bmN0aW9uIChrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlY1trXSA9IHJlY0ZpZWxkc1trXTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlYy5sZXZlbE5hbWUgPSBuYW1lRnJvbUxldmVsW21pbkxldmVsXTtcbiAgICAgICAgICAgIHJlYy5tc2cgPSBmb3JtYXQuYXBwbHkobG9nLCBtc2dBcmdzKTtcbiAgICAgICAgICAgIGlmICghcmVjLnRpbWUpIHtcbiAgICAgICAgICAgICAgICByZWMudGltZSA9IChuZXcgRGF0ZSgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEdldCBjYWxsIHNvdXJjZSBpbmZvXG4gICAgICAgICAgICBpZiAobG9nLnNyYyAmJiAhcmVjLnNyYykge1xuICAgICAgICAgICAgICAgIHJlYy5zcmMgPSBnZXRDYWxsZXIzSW5mbygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVjLnYgPSBMT0dfVkVSU0lPTjtcblxuICAgICAgICAgICAgcmV0dXJuIHJlYztcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBmaWVsZHMgPSBudWxsO1xuICAgICAgICB2YXIgbXNnQXJncyA9IGFyZ3VtZW50cztcbiAgICAgICAgdmFyIHJlYyA9IG51bGw7XG4gICAgICAgIGlmICghdGhpcy5fZW1pdCkge1xuICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAqIFNob3cgdGhpcyBpbnZhbGlkIEJ1bnlhbiB1c2FnZSB3YXJuaW5nICpvbmNlKi5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBTZWUgPGh0dHBzOi8vZ2l0aHViLmNvbS90cmVudG0vbm9kZS1idW55YW4vaXNzdWVzLzEwMD4gZm9yXG4gICAgICAgICAgICAgKiBhbiBleGFtcGxlIG9mIGhvdyB0aGlzIGNhbiBoYXBwZW4uXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHZhciBkZWR1cEtleSA9ICd1bmJvdW5kJztcbiAgICAgICAgICAgIGlmICghX2hhdmVXYXJuZWRbZGVkdXBLZXldKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNhbGxlciA9IGdldENhbGxlcjNJbmZvKCk7XG4gICAgICAgICAgICAgICAgX3dhcm4oZm9ybWF0KCdidW55YW4gdXNhZ2UgZXJyb3I6ICVzOiVzOiBhdHRlbXB0IHRvIGxvZyB3aXRoIGFuIHVuYm91bmQgbG9nIG1ldGhvZDogYHRoaXNgIGlzOiAlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICBjYWxsZXIuZmlsZSwgY2FsbGVyLmxpbmUsIHRoaXMudG9TdHJpbmcoKSksXG4gICAgICAgICAgICAgICAgICAgIGRlZHVwS2V5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7ICAgLy8gYGxvZy48bGV2ZWw+KClgXG4gICAgICAgICAgICByZXR1cm4gKHRoaXMuX2xldmVsIDw9IG1pbkxldmVsKTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLl9sZXZlbCA+IG1pbkxldmVsKSB7XG4gICAgICAgICAgICAvKiBwYXNzIHRocm91Z2ggKi9cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlYyA9IG1rUmVjb3JkKG1zZ0FyZ3MpO1xuICAgICAgICAgICAgdGhpcy5fZW1pdChyZWMpO1xuICAgICAgICB9XG4gICAgfTtcbn1cblxuXG4vKipcbiAqIFRoZSBmdW5jdGlvbnMgYmVsb3cgbG9nIGEgcmVjb3JkIGF0IGEgc3BlY2lmaWMgbGV2ZWwuXG4gKlxuICogVXNhZ2VzOlxuICogICAgbG9nLjxsZXZlbD4oKSAgLT4gYm9vbGVhbiBpcy10cmFjZS1lbmFibGVkXG4gKiAgICBsb2cuPGxldmVsPig8RXJyb3I+IGVyciwgWzxzdHJpbmc+IG1zZywgLi4uXSlcbiAqICAgIGxvZy48bGV2ZWw+KDxzdHJpbmc+IG1zZywgLi4uKVxuICogICAgbG9nLjxsZXZlbD4oPG9iamVjdD4gZmllbGRzLCA8c3RyaW5nPiBtc2csIC4uLilcbiAqXG4gKiB3aGVyZSA8bGV2ZWw+IGlzIHRoZSBsb3dlcmNhc2UgdmVyc2lvbiBvZiB0aGUgbG9nIGxldmVsLiBFLmcuOlxuICpcbiAqICAgIGxvZy5pbmZvKClcbiAqXG4gKiBAcGFyYW1zIGZpZWxkcyB7T2JqZWN0fSBPcHRpb25hbCBzZXQgb2YgYWRkaXRpb25hbCBmaWVsZHMgdG8gbG9nLlxuICogQHBhcmFtcyBtc2cge1N0cmluZ30gTG9nIG1lc3NhZ2UuIFRoaXMgY2FuIGJlIGZvbGxvd2VkIGJ5IGFkZGl0aW9uYWxcbiAqICAgIGFyZ3VtZW50cyB0aGF0IGFyZSBoYW5kbGVkIGxpa2VcbiAqICAgIFt1dGlsLmZvcm1hdF0oaHR0cDovL25vZGVqcy5vcmcvZG9jcy9sYXRlc3QvYXBpL2FsbC5odG1sI3V0aWwuZm9ybWF0KS5cbiAqL1xuTG9nZ2VyLnByb3RvdHlwZS50cmFjZSA9IG1rTG9nRW1pdHRlcihUUkFDRSk7XG5Mb2dnZXIucHJvdG90eXBlLmRlYnVnID0gbWtMb2dFbWl0dGVyKERFQlVHKTtcbkxvZ2dlci5wcm90b3R5cGUuaW5mbyA9IG1rTG9nRW1pdHRlcihJTkZPKTtcbkxvZ2dlci5wcm90b3R5cGUud2FybiA9IG1rTG9nRW1pdHRlcihXQVJOKTtcbkxvZ2dlci5wcm90b3R5cGUuZXJyb3IgPSBta0xvZ0VtaXR0ZXIoRVJST1IpO1xuTG9nZ2VyLnByb3RvdHlwZS5mYXRhbCA9IG1rTG9nRW1pdHRlcihGQVRBTCk7XG5cblxuLy8tLS0tIFN0YW5kYXJkIHNlcmlhbGl6ZXJzXG4vLyBBIHNlcmlhbGl6ZXIgaXMgYSBmdW5jdGlvbiB0aGF0IHNlcmlhbGl6ZXMgYSBKYXZhU2NyaXB0IG9iamVjdCB0byBhXG4vLyBKU09OIHJlcHJlc2VudGF0aW9uIGZvciBsb2dnaW5nLiBUaGVyZSBpcyBhIHN0YW5kYXJkIHNldCBvZiBwcmVzdW1lZFxuLy8gaW50ZXJlc3Rpbmcgb2JqZWN0cyBpbiBub2RlLmpzLWxhbmQuXG5cbkxvZ2dlci5zdGRTZXJpYWxpemVycyA9IHt9O1xuXG4vKlxuICogVGhpcyBmdW5jdGlvbiBkdW1wcyBsb25nIHN0YWNrIHRyYWNlcyBmb3IgZXhjZXB0aW9ucyBoYXZpbmcgYSBjYXVzZSgpXG4gKiBtZXRob2QuIFRoZSBlcnJvciBjbGFzc2VzIGZyb21cbiAqIFt2ZXJyb3JdKGh0dHBzOi8vZ2l0aHViLmNvbS9kYXZlcGFjaGVjby9ub2RlLXZlcnJvcikgYW5kXG4gKiBbcmVzdGlmeSB2Mi4wXShodHRwczovL2dpdGh1Yi5jb20vbWNhdmFnZS9ub2RlLXJlc3RpZnkpIGFyZSBleGFtcGxlcy5cbiAqXG4gKiBCYXNlZCBvbiBgZHVtcEV4Y2VwdGlvbmAgaW5cbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9kYXZlcGFjaGVjby9ub2RlLWV4dHNwcmludGYvYmxvYi9tYXN0ZXIvbGliL2V4dHNwcmludGYuanNcbiAqL1xuZnVuY3Rpb24gZ2V0RnVsbEVycm9yU3RhY2soZXgpIHtcbiAgICB2YXIgcmV0ID0gZXguc3RhY2sgfHwgZXgudG9TdHJpbmcoKTtcbiAgICBpZiAoZXguY2F1c2UgJiYgdHlwZW9mIChleC5jYXVzZSkgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdmFyIGNleCA9IGV4LmNhdXNlKCk7XG4gICAgICAgIGlmIChjZXgpIHtcbiAgICAgICAgICAgIHJldCArPSAnXFxuQ2F1c2VkIGJ5OiAnICsgZ2V0RnVsbEVycm9yU3RhY2soY2V4KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gKHJldCk7XG59XG5cbi8vIFNlcmlhbGl6ZSBhbiBFcnJvciBvYmplY3Rcbi8vIChDb3JlIGVycm9yIHByb3BlcnRpZXMgYXJlIGVudW1lcmFibGUgaW4gbm9kZSAwLjQsIG5vdCBpbiAwLjYpLlxuTG9nZ2VyLnN0ZFNlcmlhbGl6ZXJzLmVyciA9IGZ1bmN0aW9uKGVycikge1xuICAgIGlmICghZXJyIHx8ICFlcnIuc3RhY2spIHtcbiAgICAgICAgcmV0dXJuIGVycjtcbiAgICB9XG5cbiAgICB2YXIgb2JqID0ge1xuICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgbmFtZTogZXJyLm5hbWUsXG4gICAgICAgIHN0YWNrOiBnZXRGdWxsRXJyb3JTdGFjayhlcnIpLFxuICAgICAgICBjb2RlOiBlcnIuY29kZSxcbiAgICAgICAgc2lnbmFsOiBlcnIuc2lnbmFsXG4gICAgfTtcbiAgICByZXR1cm4gb2JqO1xufTtcblxuXG4vLyBBIEpTT04gc3RyaW5naWZpZXIgdGhhdCBoYW5kbGVzIGN5Y2xlcyBzYWZlbHkuXG4vLyBVc2FnZTogSlNPTi5zdHJpbmdpZnkob2JqLCBzYWZlQ3ljbGVzKCkpXG5mdW5jdGlvbiBzYWZlQ3ljbGVzKCkge1xuICAgIHZhciBzZWVuID0gW107XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChrZXksIHZhbCkge1xuICAgICAgICBpZiAoIXZhbCB8fCB0eXBlb2YgKHZhbCkgIT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzZWVuLmluZGV4T2YodmFsKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHJldHVybiAnW0NpcmN1bGFyXSc7XG4gICAgICAgIH1cbiAgICAgICAgc2Vlbi5wdXNoKHZhbCk7XG4gICAgICAgIHJldHVybiB2YWw7XG4gICAgfTtcbn1cblxuLy8tLS0tIEV4cG9ydHNcblxubW9kdWxlLmV4cG9ydHMgPSBMb2dnZXI7XG5cbm1vZHVsZS5leHBvcnRzLlRSQUNFID0gVFJBQ0U7XG5tb2R1bGUuZXhwb3J0cy5ERUJVRyA9IERFQlVHO1xubW9kdWxlLmV4cG9ydHMuSU5GTyA9IElORk87XG5tb2R1bGUuZXhwb3J0cy5XQVJOID0gV0FSTjtcbm1vZHVsZS5leHBvcnRzLkVSUk9SID0gRVJST1I7XG5tb2R1bGUuZXhwb3J0cy5GQVRBTCA9IEZBVEFMO1xubW9kdWxlLmV4cG9ydHMucmVzb2x2ZUxldmVsID0gcmVzb2x2ZUxldmVsO1xubW9kdWxlLmV4cG9ydHMubGV2ZWxGcm9tTmFtZSA9IGxldmVsRnJvbU5hbWU7XG5tb2R1bGUuZXhwb3J0cy5uYW1lRnJvbUxldmVsID0gbmFtZUZyb21MZXZlbDtcblxubW9kdWxlLmV4cG9ydHMuVkVSU0lPTiA9IFZFUlNJT047XG5tb2R1bGUuZXhwb3J0cy5MT0dfVkVSU0lPTiA9IExPR19WRVJTSU9OO1xuXG5tb2R1bGUuZXhwb3J0cy5jcmVhdGVMb2dnZXIgPSBmdW5jdGlvbiBjcmVhdGVMb2dnZXIob3B0aW9ucykge1xuICAgIHJldHVybiBuZXcgTG9nZ2VyKG9wdGlvbnMpO1xufTtcblxuLy8gVXNlZnVsIGZvciBjdXN0b20gYHR5cGUgPT0gJ3JhdydgIHN0cmVhbXMgdGhhdCBtYXkgZG8gSlNPTiBzdHJpbmdpZmljYXRpb25cbi8vIG9mIGxvZyByZWNvcmRzIHRoZW1zZWx2ZXMuIFVzYWdlOlxuLy8gICAgdmFyIHN0ciA9IEpTT04uc3RyaW5naWZ5KHJlYywgYnVueWFuLnNhZmVDeWNsZXMoKSk7XG5tb2R1bGUuZXhwb3J0cy5zYWZlQ3ljbGVzID0gc2FmZUN5Y2xlcztcblxuLy9zdHJlYW1zXG5tb2R1bGUuZXhwb3J0cy5Db25zb2xlRm9ybWF0dGVkU3RyZWFtID0gQ29uc29sZUZvcm1hdHRlZFN0cmVhbTtcbm1vZHVsZS5leHBvcnRzLkNvbnNvbGVSYXdTdHJlYW0gPSBDb25zb2xlUmF3U3RyZWFtO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9icm93c2VyLWJ1bnlhbi9saWIvYnVueWFuLmpzXG4vLyBtb2R1bGUgaWQgPSA5NVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIndXNlIHN0cmljdCc7XG52YXIgZFAgICAgICAgICAgPSByZXF1aXJlKCcuL19vYmplY3QtZHAnKS5mXG4gICwgY3JlYXRlICAgICAgPSByZXF1aXJlKCcuL19vYmplY3QtY3JlYXRlJylcbiAgLCByZWRlZmluZUFsbCA9IHJlcXVpcmUoJy4vX3JlZGVmaW5lLWFsbCcpXG4gICwgY3R4ICAgICAgICAgPSByZXF1aXJlKCcuL19jdHgnKVxuICAsIGFuSW5zdGFuY2UgID0gcmVxdWlyZSgnLi9fYW4taW5zdGFuY2UnKVxuICAsIGRlZmluZWQgICAgID0gcmVxdWlyZSgnLi9fZGVmaW5lZCcpXG4gICwgZm9yT2YgICAgICAgPSByZXF1aXJlKCcuL19mb3Itb2YnKVxuICAsICRpdGVyRGVmaW5lID0gcmVxdWlyZSgnLi9faXRlci1kZWZpbmUnKVxuICAsIHN0ZXAgICAgICAgID0gcmVxdWlyZSgnLi9faXRlci1zdGVwJylcbiAgLCBzZXRTcGVjaWVzICA9IHJlcXVpcmUoJy4vX3NldC1zcGVjaWVzJylcbiAgLCBERVNDUklQVE9SUyA9IHJlcXVpcmUoJy4vX2Rlc2NyaXB0b3JzJylcbiAgLCBmYXN0S2V5ICAgICA9IHJlcXVpcmUoJy4vX21ldGEnKS5mYXN0S2V5XG4gICwgU0laRSAgICAgICAgPSBERVNDUklQVE9SUyA/ICdfcycgOiAnc2l6ZSc7XG5cbnZhciBnZXRFbnRyeSA9IGZ1bmN0aW9uKHRoYXQsIGtleSl7XG4gIC8vIGZhc3QgY2FzZVxuICB2YXIgaW5kZXggPSBmYXN0S2V5KGtleSksIGVudHJ5O1xuICBpZihpbmRleCAhPT0gJ0YnKXJldHVybiB0aGF0Ll9pW2luZGV4XTtcbiAgLy8gZnJvemVuIG9iamVjdCBjYXNlXG4gIGZvcihlbnRyeSA9IHRoYXQuX2Y7IGVudHJ5OyBlbnRyeSA9IGVudHJ5Lm4pe1xuICAgIGlmKGVudHJ5LmsgPT0ga2V5KXJldHVybiBlbnRyeTtcbiAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGdldENvbnN0cnVjdG9yOiBmdW5jdGlvbih3cmFwcGVyLCBOQU1FLCBJU19NQVAsIEFEREVSKXtcbiAgICB2YXIgQyA9IHdyYXBwZXIoZnVuY3Rpb24odGhhdCwgaXRlcmFibGUpe1xuICAgICAgYW5JbnN0YW5jZSh0aGF0LCBDLCBOQU1FLCAnX2knKTtcbiAgICAgIHRoYXQuX2kgPSBjcmVhdGUobnVsbCk7IC8vIGluZGV4XG4gICAgICB0aGF0Ll9mID0gdW5kZWZpbmVkOyAgICAvLyBmaXJzdCBlbnRyeVxuICAgICAgdGhhdC5fbCA9IHVuZGVmaW5lZDsgICAgLy8gbGFzdCBlbnRyeVxuICAgICAgdGhhdFtTSVpFXSA9IDA7ICAgICAgICAgLy8gc2l6ZVxuICAgICAgaWYoaXRlcmFibGUgIT0gdW5kZWZpbmVkKWZvck9mKGl0ZXJhYmxlLCBJU19NQVAsIHRoYXRbQURERVJdLCB0aGF0KTtcbiAgICB9KTtcbiAgICByZWRlZmluZUFsbChDLnByb3RvdHlwZSwge1xuICAgICAgLy8gMjMuMS4zLjEgTWFwLnByb3RvdHlwZS5jbGVhcigpXG4gICAgICAvLyAyMy4yLjMuMiBTZXQucHJvdG90eXBlLmNsZWFyKClcbiAgICAgIGNsZWFyOiBmdW5jdGlvbiBjbGVhcigpe1xuICAgICAgICBmb3IodmFyIHRoYXQgPSB0aGlzLCBkYXRhID0gdGhhdC5faSwgZW50cnkgPSB0aGF0Ll9mOyBlbnRyeTsgZW50cnkgPSBlbnRyeS5uKXtcbiAgICAgICAgICBlbnRyeS5yID0gdHJ1ZTtcbiAgICAgICAgICBpZihlbnRyeS5wKWVudHJ5LnAgPSBlbnRyeS5wLm4gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgZGVsZXRlIGRhdGFbZW50cnkuaV07XG4gICAgICAgIH1cbiAgICAgICAgdGhhdC5fZiA9IHRoYXQuX2wgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoYXRbU0laRV0gPSAwO1xuICAgICAgfSxcbiAgICAgIC8vIDIzLjEuMy4zIE1hcC5wcm90b3R5cGUuZGVsZXRlKGtleSlcbiAgICAgIC8vIDIzLjIuMy40IFNldC5wcm90b3R5cGUuZGVsZXRlKHZhbHVlKVxuICAgICAgJ2RlbGV0ZSc6IGZ1bmN0aW9uKGtleSl7XG4gICAgICAgIHZhciB0aGF0ICA9IHRoaXNcbiAgICAgICAgICAsIGVudHJ5ID0gZ2V0RW50cnkodGhhdCwga2V5KTtcbiAgICAgICAgaWYoZW50cnkpe1xuICAgICAgICAgIHZhciBuZXh0ID0gZW50cnkublxuICAgICAgICAgICAgLCBwcmV2ID0gZW50cnkucDtcbiAgICAgICAgICBkZWxldGUgdGhhdC5faVtlbnRyeS5pXTtcbiAgICAgICAgICBlbnRyeS5yID0gdHJ1ZTtcbiAgICAgICAgICBpZihwcmV2KXByZXYubiA9IG5leHQ7XG4gICAgICAgICAgaWYobmV4dCluZXh0LnAgPSBwcmV2O1xuICAgICAgICAgIGlmKHRoYXQuX2YgPT0gZW50cnkpdGhhdC5fZiA9IG5leHQ7XG4gICAgICAgICAgaWYodGhhdC5fbCA9PSBlbnRyeSl0aGF0Ll9sID0gcHJldjtcbiAgICAgICAgICB0aGF0W1NJWkVdLS07XG4gICAgICAgIH0gcmV0dXJuICEhZW50cnk7XG4gICAgICB9LFxuICAgICAgLy8gMjMuMi4zLjYgU2V0LnByb3RvdHlwZS5mb3JFYWNoKGNhbGxiYWNrZm4sIHRoaXNBcmcgPSB1bmRlZmluZWQpXG4gICAgICAvLyAyMy4xLjMuNSBNYXAucHJvdG90eXBlLmZvckVhY2goY2FsbGJhY2tmbiwgdGhpc0FyZyA9IHVuZGVmaW5lZClcbiAgICAgIGZvckVhY2g6IGZ1bmN0aW9uIGZvckVhY2goY2FsbGJhY2tmbiAvKiwgdGhhdCA9IHVuZGVmaW5lZCAqLyl7XG4gICAgICAgIGFuSW5zdGFuY2UodGhpcywgQywgJ2ZvckVhY2gnKTtcbiAgICAgICAgdmFyIGYgPSBjdHgoY2FsbGJhY2tmbiwgYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQsIDMpXG4gICAgICAgICAgLCBlbnRyeTtcbiAgICAgICAgd2hpbGUoZW50cnkgPSBlbnRyeSA/IGVudHJ5Lm4gOiB0aGlzLl9mKXtcbiAgICAgICAgICBmKGVudHJ5LnYsIGVudHJ5LmssIHRoaXMpO1xuICAgICAgICAgIC8vIHJldmVydCB0byB0aGUgbGFzdCBleGlzdGluZyBlbnRyeVxuICAgICAgICAgIHdoaWxlKGVudHJ5ICYmIGVudHJ5LnIpZW50cnkgPSBlbnRyeS5wO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgLy8gMjMuMS4zLjcgTWFwLnByb3RvdHlwZS5oYXMoa2V5KVxuICAgICAgLy8gMjMuMi4zLjcgU2V0LnByb3RvdHlwZS5oYXModmFsdWUpXG4gICAgICBoYXM6IGZ1bmN0aW9uIGhhcyhrZXkpe1xuICAgICAgICByZXR1cm4gISFnZXRFbnRyeSh0aGlzLCBrZXkpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGlmKERFU0NSSVBUT1JTKWRQKEMucHJvdG90eXBlLCAnc2l6ZScsIHtcbiAgICAgIGdldDogZnVuY3Rpb24oKXtcbiAgICAgICAgcmV0dXJuIGRlZmluZWQodGhpc1tTSVpFXSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIEM7XG4gIH0sXG4gIGRlZjogZnVuY3Rpb24odGhhdCwga2V5LCB2YWx1ZSl7XG4gICAgdmFyIGVudHJ5ID0gZ2V0RW50cnkodGhhdCwga2V5KVxuICAgICAgLCBwcmV2LCBpbmRleDtcbiAgICAvLyBjaGFuZ2UgZXhpc3RpbmcgZW50cnlcbiAgICBpZihlbnRyeSl7XG4gICAgICBlbnRyeS52ID0gdmFsdWU7XG4gICAgLy8gY3JlYXRlIG5ldyBlbnRyeVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGF0Ll9sID0gZW50cnkgPSB7XG4gICAgICAgIGk6IGluZGV4ID0gZmFzdEtleShrZXksIHRydWUpLCAvLyA8LSBpbmRleFxuICAgICAgICBrOiBrZXksICAgICAgICAgICAgICAgICAgICAgICAgLy8gPC0ga2V5XG4gICAgICAgIHY6IHZhbHVlLCAgICAgICAgICAgICAgICAgICAgICAvLyA8LSB2YWx1ZVxuICAgICAgICBwOiBwcmV2ID0gdGhhdC5fbCwgICAgICAgICAgICAgLy8gPC0gcHJldmlvdXMgZW50cnlcbiAgICAgICAgbjogdW5kZWZpbmVkLCAgICAgICAgICAgICAgICAgIC8vIDwtIG5leHQgZW50cnlcbiAgICAgICAgcjogZmFsc2UgICAgICAgICAgICAgICAgICAgICAgIC8vIDwtIHJlbW92ZWRcbiAgICAgIH07XG4gICAgICBpZighdGhhdC5fZil0aGF0Ll9mID0gZW50cnk7XG4gICAgICBpZihwcmV2KXByZXYubiA9IGVudHJ5O1xuICAgICAgdGhhdFtTSVpFXSsrO1xuICAgICAgLy8gYWRkIHRvIGluZGV4XG4gICAgICBpZihpbmRleCAhPT0gJ0YnKXRoYXQuX2lbaW5kZXhdID0gZW50cnk7XG4gICAgfSByZXR1cm4gdGhhdDtcbiAgfSxcbiAgZ2V0RW50cnk6IGdldEVudHJ5LFxuICBzZXRTdHJvbmc6IGZ1bmN0aW9uKEMsIE5BTUUsIElTX01BUCl7XG4gICAgLy8gYWRkIC5rZXlzLCAudmFsdWVzLCAuZW50cmllcywgW0BAaXRlcmF0b3JdXG4gICAgLy8gMjMuMS4zLjQsIDIzLjEuMy44LCAyMy4xLjMuMTEsIDIzLjEuMy4xMiwgMjMuMi4zLjUsIDIzLjIuMy44LCAyMy4yLjMuMTAsIDIzLjIuMy4xMVxuICAgICRpdGVyRGVmaW5lKEMsIE5BTUUsIGZ1bmN0aW9uKGl0ZXJhdGVkLCBraW5kKXtcbiAgICAgIHRoaXMuX3QgPSBpdGVyYXRlZDsgIC8vIHRhcmdldFxuICAgICAgdGhpcy5fayA9IGtpbmQ7ICAgICAgLy8ga2luZFxuICAgICAgdGhpcy5fbCA9IHVuZGVmaW5lZDsgLy8gcHJldmlvdXNcbiAgICB9LCBmdW5jdGlvbigpe1xuICAgICAgdmFyIHRoYXQgID0gdGhpc1xuICAgICAgICAsIGtpbmQgID0gdGhhdC5fa1xuICAgICAgICAsIGVudHJ5ID0gdGhhdC5fbDtcbiAgICAgIC8vIHJldmVydCB0byB0aGUgbGFzdCBleGlzdGluZyBlbnRyeVxuICAgICAgd2hpbGUoZW50cnkgJiYgZW50cnkucillbnRyeSA9IGVudHJ5LnA7XG4gICAgICAvLyBnZXQgbmV4dCBlbnRyeVxuICAgICAgaWYoIXRoYXQuX3QgfHwgISh0aGF0Ll9sID0gZW50cnkgPSBlbnRyeSA/IGVudHJ5Lm4gOiB0aGF0Ll90Ll9mKSl7XG4gICAgICAgIC8vIG9yIGZpbmlzaCB0aGUgaXRlcmF0aW9uXG4gICAgICAgIHRoYXQuX3QgPSB1bmRlZmluZWQ7XG4gICAgICAgIHJldHVybiBzdGVwKDEpO1xuICAgICAgfVxuICAgICAgLy8gcmV0dXJuIHN0ZXAgYnkga2luZFxuICAgICAgaWYoa2luZCA9PSAna2V5cycgIClyZXR1cm4gc3RlcCgwLCBlbnRyeS5rKTtcbiAgICAgIGlmKGtpbmQgPT0gJ3ZhbHVlcycpcmV0dXJuIHN0ZXAoMCwgZW50cnkudik7XG4gICAgICByZXR1cm4gc3RlcCgwLCBbZW50cnkuaywgZW50cnkudl0pO1xuICAgIH0sIElTX01BUCA/ICdlbnRyaWVzJyA6ICd2YWx1ZXMnICwgIUlTX01BUCwgdHJ1ZSk7XG5cbiAgICAvLyBhZGQgW0BAc3BlY2llc10sIDIzLjEuMi4yLCAyMy4yLjIuMlxuICAgIHNldFNwZWNpZXMoTkFNRSk7XG4gIH1cbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19jb2xsZWN0aW9uLXN0cm9uZy5qc1xuLy8gbW9kdWxlIGlkID0gOTZcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8gaHR0cHM6Ly9naXRodWIuY29tL0RhdmlkQnJ1YW50L01hcC1TZXQucHJvdG90eXBlLnRvSlNPTlxudmFyIGNsYXNzb2YgPSByZXF1aXJlKCcuL19jbGFzc29mJylcbiAgLCBmcm9tICAgID0gcmVxdWlyZSgnLi9fYXJyYXktZnJvbS1pdGVyYWJsZScpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihOQU1FKXtcbiAgcmV0dXJuIGZ1bmN0aW9uIHRvSlNPTigpe1xuICAgIGlmKGNsYXNzb2YodGhpcykgIT0gTkFNRSl0aHJvdyBUeXBlRXJyb3IoTkFNRSArIFwiI3RvSlNPTiBpc24ndCBnZW5lcmljXCIpO1xuICAgIHJldHVybiBmcm9tKHRoaXMpO1xuICB9O1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2NvbGxlY3Rpb24tdG8tanNvbi5qc1xuLy8gbW9kdWxlIGlkID0gOTdcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL19nbG9iYWwnKS5kb2N1bWVudCAmJiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19odG1sLmpzXG4vLyBtb2R1bGUgaWQgPSA5OFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9ICFyZXF1aXJlKCcuL19kZXNjcmlwdG9ycycpICYmICFyZXF1aXJlKCcuL19mYWlscycpKGZ1bmN0aW9uKCl7XG4gIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkocmVxdWlyZSgnLi9fZG9tLWNyZWF0ZScpKCdkaXYnKSwgJ2EnLCB7Z2V0OiBmdW5jdGlvbigpeyByZXR1cm4gNzsgfX0pLmEgIT0gNztcbn0pO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9faWU4LWRvbS1kZWZpbmUuanNcbi8vIG1vZHVsZSBpZCA9IDk5XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIGNoZWNrIG9uIGRlZmF1bHQgQXJyYXkgaXRlcmF0b3JcbnZhciBJdGVyYXRvcnMgID0gcmVxdWlyZSgnLi9faXRlcmF0b3JzJylcbiAgLCBJVEVSQVRPUiAgID0gcmVxdWlyZSgnLi9fd2tzJykoJ2l0ZXJhdG9yJylcbiAgLCBBcnJheVByb3RvID0gQXJyYXkucHJvdG90eXBlO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGl0KXtcbiAgcmV0dXJuIGl0ICE9PSB1bmRlZmluZWQgJiYgKEl0ZXJhdG9ycy5BcnJheSA9PT0gaXQgfHwgQXJyYXlQcm90b1tJVEVSQVRPUl0gPT09IGl0KTtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pcy1hcnJheS1pdGVyLmpzXG4vLyBtb2R1bGUgaWQgPSAxMDBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8gNy4yLjIgSXNBcnJheShhcmd1bWVudClcbnZhciBjb2YgPSByZXF1aXJlKCcuL19jb2YnKTtcbm1vZHVsZS5leHBvcnRzID0gQXJyYXkuaXNBcnJheSB8fCBmdW5jdGlvbiBpc0FycmF5KGFyZyl7XG4gIHJldHVybiBjb2YoYXJnKSA9PSAnQXJyYXknO1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2lzLWFycmF5LmpzXG4vLyBtb2R1bGUgaWQgPSAxMDFcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8gY2FsbCBzb21ldGhpbmcgb24gaXRlcmF0b3Igc3RlcCB3aXRoIHNhZmUgY2xvc2luZyBvbiBlcnJvclxudmFyIGFuT2JqZWN0ID0gcmVxdWlyZSgnLi9fYW4tb2JqZWN0Jyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGl0ZXJhdG9yLCBmbiwgdmFsdWUsIGVudHJpZXMpe1xuICB0cnkge1xuICAgIHJldHVybiBlbnRyaWVzID8gZm4oYW5PYmplY3QodmFsdWUpWzBdLCB2YWx1ZVsxXSkgOiBmbih2YWx1ZSk7XG4gIC8vIDcuNC42IEl0ZXJhdG9yQ2xvc2UoaXRlcmF0b3IsIGNvbXBsZXRpb24pXG4gIH0gY2F0Y2goZSl7XG4gICAgdmFyIHJldCA9IGl0ZXJhdG9yWydyZXR1cm4nXTtcbiAgICBpZihyZXQgIT09IHVuZGVmaW5lZClhbk9iamVjdChyZXQuY2FsbChpdGVyYXRvcikpO1xuICAgIHRocm93IGU7XG4gIH1cbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pdGVyLWNhbGwuanNcbi8vIG1vZHVsZSBpZCA9IDEwMlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJ2YXIgSVRFUkFUT1IgICAgID0gcmVxdWlyZSgnLi9fd2tzJykoJ2l0ZXJhdG9yJylcbiAgLCBTQUZFX0NMT1NJTkcgPSBmYWxzZTtcblxudHJ5IHtcbiAgdmFyIHJpdGVyID0gWzddW0lURVJBVE9SXSgpO1xuICByaXRlclsncmV0dXJuJ10gPSBmdW5jdGlvbigpeyBTQUZFX0NMT1NJTkcgPSB0cnVlOyB9O1xuICBBcnJheS5mcm9tKHJpdGVyLCBmdW5jdGlvbigpeyB0aHJvdyAyOyB9KTtcbn0gY2F0Y2goZSl7IC8qIGVtcHR5ICovIH1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihleGVjLCBza2lwQ2xvc2luZyl7XG4gIGlmKCFza2lwQ2xvc2luZyAmJiAhU0FGRV9DTE9TSU5HKXJldHVybiBmYWxzZTtcbiAgdmFyIHNhZmUgPSBmYWxzZTtcbiAgdHJ5IHtcbiAgICB2YXIgYXJyICA9IFs3XVxuICAgICAgLCBpdGVyID0gYXJyW0lURVJBVE9SXSgpO1xuICAgIGl0ZXIubmV4dCA9IGZ1bmN0aW9uKCl7IHJldHVybiB7ZG9uZTogc2FmZSA9IHRydWV9OyB9O1xuICAgIGFycltJVEVSQVRPUl0gPSBmdW5jdGlvbigpeyByZXR1cm4gaXRlcjsgfTtcbiAgICBleGVjKGFycik7XG4gIH0gY2F0Y2goZSl7IC8qIGVtcHR5ICovIH1cbiAgcmV0dXJuIHNhZmU7XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9faXRlci1kZXRlY3QuanNcbi8vIG1vZHVsZSBpZCA9IDEwM1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGRvbmUsIHZhbHVlKXtcbiAgcmV0dXJuIHt2YWx1ZTogdmFsdWUsIGRvbmU6ICEhZG9uZX07XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9faXRlci1zdGVwLmpzXG4vLyBtb2R1bGUgaWQgPSAxMDRcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiJ3VzZSBzdHJpY3QnO1xuLy8gMTkuMS4yLjEgT2JqZWN0LmFzc2lnbih0YXJnZXQsIHNvdXJjZSwgLi4uKVxudmFyIGdldEtleXMgID0gcmVxdWlyZSgnLi9fb2JqZWN0LWtleXMnKVxuICAsIGdPUFMgICAgID0gcmVxdWlyZSgnLi9fb2JqZWN0LWdvcHMnKVxuICAsIHBJRSAgICAgID0gcmVxdWlyZSgnLi9fb2JqZWN0LXBpZScpXG4gICwgdG9PYmplY3QgPSByZXF1aXJlKCcuL190by1vYmplY3QnKVxuICAsIElPYmplY3QgID0gcmVxdWlyZSgnLi9faW9iamVjdCcpXG4gICwgJGFzc2lnbiAgPSBPYmplY3QuYXNzaWduO1xuXG4vLyBzaG91bGQgd29yayB3aXRoIHN5bWJvbHMgYW5kIHNob3VsZCBoYXZlIGRldGVybWluaXN0aWMgcHJvcGVydHkgb3JkZXIgKFY4IGJ1Zylcbm1vZHVsZS5leHBvcnRzID0gISRhc3NpZ24gfHwgcmVxdWlyZSgnLi9fZmFpbHMnKShmdW5jdGlvbigpe1xuICB2YXIgQSA9IHt9XG4gICAgLCBCID0ge31cbiAgICAsIFMgPSBTeW1ib2woKVxuICAgICwgSyA9ICdhYmNkZWZnaGlqa2xtbm9wcXJzdCc7XG4gIEFbU10gPSA3O1xuICBLLnNwbGl0KCcnKS5mb3JFYWNoKGZ1bmN0aW9uKGspeyBCW2tdID0gazsgfSk7XG4gIHJldHVybiAkYXNzaWduKHt9LCBBKVtTXSAhPSA3IHx8IE9iamVjdC5rZXlzKCRhc3NpZ24oe30sIEIpKS5qb2luKCcnKSAhPSBLO1xufSkgPyBmdW5jdGlvbiBhc3NpZ24odGFyZ2V0LCBzb3VyY2UpeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gIHZhciBUICAgICA9IHRvT2JqZWN0KHRhcmdldClcbiAgICAsIGFMZW4gID0gYXJndW1lbnRzLmxlbmd0aFxuICAgICwgaW5kZXggPSAxXG4gICAgLCBnZXRTeW1ib2xzID0gZ09QUy5mXG4gICAgLCBpc0VudW0gICAgID0gcElFLmY7XG4gIHdoaWxlKGFMZW4gPiBpbmRleCl7XG4gICAgdmFyIFMgICAgICA9IElPYmplY3QoYXJndW1lbnRzW2luZGV4KytdKVxuICAgICAgLCBrZXlzICAgPSBnZXRTeW1ib2xzID8gZ2V0S2V5cyhTKS5jb25jYXQoZ2V0U3ltYm9scyhTKSkgOiBnZXRLZXlzKFMpXG4gICAgICAsIGxlbmd0aCA9IGtleXMubGVuZ3RoXG4gICAgICAsIGogICAgICA9IDBcbiAgICAgICwga2V5O1xuICAgIHdoaWxlKGxlbmd0aCA+IGopaWYoaXNFbnVtLmNhbGwoUywga2V5ID0ga2V5c1tqKytdKSlUW2tleV0gPSBTW2tleV07XG4gIH0gcmV0dXJuIFQ7XG59IDogJGFzc2lnbjtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX29iamVjdC1hc3NpZ24uanNcbi8vIG1vZHVsZSBpZCA9IDEwNVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyAxOS4xLjIuNyAvIDE1LjIuMy40IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKE8pXG52YXIgJGtleXMgICAgICA9IHJlcXVpcmUoJy4vX29iamVjdC1rZXlzLWludGVybmFsJylcbiAgLCBoaWRkZW5LZXlzID0gcmVxdWlyZSgnLi9fZW51bS1idWcta2V5cycpLmNvbmNhdCgnbGVuZ3RoJywgJ3Byb3RvdHlwZScpO1xuXG5leHBvcnRzLmYgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyB8fCBmdW5jdGlvbiBnZXRPd25Qcm9wZXJ0eU5hbWVzKE8pe1xuICByZXR1cm4gJGtleXMoTywgaGlkZGVuS2V5cyk7XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LWdvcG4uanNcbi8vIG1vZHVsZSBpZCA9IDEwNlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyAxOS4xLjIuOSAvIDE1LjIuMy4yIE9iamVjdC5nZXRQcm90b3R5cGVPZihPKVxudmFyIGhhcyAgICAgICAgID0gcmVxdWlyZSgnLi9faGFzJylcbiAgLCB0b09iamVjdCAgICA9IHJlcXVpcmUoJy4vX3RvLW9iamVjdCcpXG4gICwgSUVfUFJPVE8gICAgPSByZXF1aXJlKCcuL19zaGFyZWQta2V5JykoJ0lFX1BST1RPJylcbiAgLCBPYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbm1vZHVsZS5leHBvcnRzID0gT2JqZWN0LmdldFByb3RvdHlwZU9mIHx8IGZ1bmN0aW9uKE8pe1xuICBPID0gdG9PYmplY3QoTyk7XG4gIGlmKGhhcyhPLCBJRV9QUk9UTykpcmV0dXJuIE9bSUVfUFJPVE9dO1xuICBpZih0eXBlb2YgTy5jb25zdHJ1Y3RvciA9PSAnZnVuY3Rpb24nICYmIE8gaW5zdGFuY2VvZiBPLmNvbnN0cnVjdG9yKXtcbiAgICByZXR1cm4gTy5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gIH0gcmV0dXJuIE8gaW5zdGFuY2VvZiBPYmplY3QgPyBPYmplY3RQcm90byA6IG51bGw7XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LWdwby5qc1xuLy8gbW9kdWxlIGlkID0gMTA3XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsInZhciBoYXMgICAgICAgICAgPSByZXF1aXJlKCcuL19oYXMnKVxuICAsIHRvSU9iamVjdCAgICA9IHJlcXVpcmUoJy4vX3RvLWlvYmplY3QnKVxuICAsIGFycmF5SW5kZXhPZiA9IHJlcXVpcmUoJy4vX2FycmF5LWluY2x1ZGVzJykoZmFsc2UpXG4gICwgSUVfUFJPVE8gICAgID0gcmVxdWlyZSgnLi9fc2hhcmVkLWtleScpKCdJRV9QUk9UTycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKG9iamVjdCwgbmFtZXMpe1xuICB2YXIgTyAgICAgID0gdG9JT2JqZWN0KG9iamVjdClcbiAgICAsIGkgICAgICA9IDBcbiAgICAsIHJlc3VsdCA9IFtdXG4gICAgLCBrZXk7XG4gIGZvcihrZXkgaW4gTylpZihrZXkgIT0gSUVfUFJPVE8paGFzKE8sIGtleSkgJiYgcmVzdWx0LnB1c2goa2V5KTtcbiAgLy8gRG9uJ3QgZW51bSBidWcgJiBoaWRkZW4ga2V5c1xuICB3aGlsZShuYW1lcy5sZW5ndGggPiBpKWlmKGhhcyhPLCBrZXkgPSBuYW1lc1tpKytdKSl7XG4gICAgfmFycmF5SW5kZXhPZihyZXN1bHQsIGtleSkgfHwgcmVzdWx0LnB1c2goa2V5KTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX29iamVjdC1rZXlzLWludGVybmFsLmpzXG4vLyBtb2R1bGUgaWQgPSAxMDhcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiJ3VzZSBzdHJpY3QnO1xudmFyIGdsb2JhbCAgICAgID0gcmVxdWlyZSgnLi9fZ2xvYmFsJylcbiAgLCBjb3JlICAgICAgICA9IHJlcXVpcmUoJy4vX2NvcmUnKVxuICAsIGRQICAgICAgICAgID0gcmVxdWlyZSgnLi9fb2JqZWN0LWRwJylcbiAgLCBERVNDUklQVE9SUyA9IHJlcXVpcmUoJy4vX2Rlc2NyaXB0b3JzJylcbiAgLCBTUEVDSUVTICAgICA9IHJlcXVpcmUoJy4vX3drcycpKCdzcGVjaWVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oS0VZKXtcbiAgdmFyIEMgPSB0eXBlb2YgY29yZVtLRVldID09ICdmdW5jdGlvbicgPyBjb3JlW0tFWV0gOiBnbG9iYWxbS0VZXTtcbiAgaWYoREVTQ1JJUFRPUlMgJiYgQyAmJiAhQ1tTUEVDSUVTXSlkUC5mKEMsIFNQRUNJRVMsIHtcbiAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbigpeyByZXR1cm4gdGhpczsgfVxuICB9KTtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19zZXQtc3BlY2llcy5qc1xuLy8gbW9kdWxlIGlkID0gMTA5XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsInZhciBjdHggICAgICAgICAgICAgICAgPSByZXF1aXJlKCcuL19jdHgnKVxuICAsIGludm9rZSAgICAgICAgICAgICA9IHJlcXVpcmUoJy4vX2ludm9rZScpXG4gICwgaHRtbCAgICAgICAgICAgICAgID0gcmVxdWlyZSgnLi9faHRtbCcpXG4gICwgY2VsICAgICAgICAgICAgICAgID0gcmVxdWlyZSgnLi9fZG9tLWNyZWF0ZScpXG4gICwgZ2xvYmFsICAgICAgICAgICAgID0gcmVxdWlyZSgnLi9fZ2xvYmFsJylcbiAgLCBwcm9jZXNzICAgICAgICAgICAgPSBnbG9iYWwucHJvY2Vzc1xuICAsIHNldFRhc2sgICAgICAgICAgICA9IGdsb2JhbC5zZXRJbW1lZGlhdGVcbiAgLCBjbGVhclRhc2sgICAgICAgICAgPSBnbG9iYWwuY2xlYXJJbW1lZGlhdGVcbiAgLCBNZXNzYWdlQ2hhbm5lbCAgICAgPSBnbG9iYWwuTWVzc2FnZUNoYW5uZWxcbiAgLCBjb3VudGVyICAgICAgICAgICAgPSAwXG4gICwgcXVldWUgICAgICAgICAgICAgID0ge31cbiAgLCBPTlJFQURZU1RBVEVDSEFOR0UgPSAnb25yZWFkeXN0YXRlY2hhbmdlJ1xuICAsIGRlZmVyLCBjaGFubmVsLCBwb3J0O1xudmFyIHJ1biA9IGZ1bmN0aW9uKCl7XG4gIHZhciBpZCA9ICt0aGlzO1xuICBpZihxdWV1ZS5oYXNPd25Qcm9wZXJ0eShpZCkpe1xuICAgIHZhciBmbiA9IHF1ZXVlW2lkXTtcbiAgICBkZWxldGUgcXVldWVbaWRdO1xuICAgIGZuKCk7XG4gIH1cbn07XG52YXIgbGlzdGVuZXIgPSBmdW5jdGlvbihldmVudCl7XG4gIHJ1bi5jYWxsKGV2ZW50LmRhdGEpO1xufTtcbi8vIE5vZGUuanMgMC45KyAmIElFMTArIGhhcyBzZXRJbW1lZGlhdGUsIG90aGVyd2lzZTpcbmlmKCFzZXRUYXNrIHx8ICFjbGVhclRhc2spe1xuICBzZXRUYXNrID0gZnVuY3Rpb24gc2V0SW1tZWRpYXRlKGZuKXtcbiAgICB2YXIgYXJncyA9IFtdLCBpID0gMTtcbiAgICB3aGlsZShhcmd1bWVudHMubGVuZ3RoID4gaSlhcmdzLnB1c2goYXJndW1lbnRzW2krK10pO1xuICAgIHF1ZXVlWysrY291bnRlcl0gPSBmdW5jdGlvbigpe1xuICAgICAgaW52b2tlKHR5cGVvZiBmbiA9PSAnZnVuY3Rpb24nID8gZm4gOiBGdW5jdGlvbihmbiksIGFyZ3MpO1xuICAgIH07XG4gICAgZGVmZXIoY291bnRlcik7XG4gICAgcmV0dXJuIGNvdW50ZXI7XG4gIH07XG4gIGNsZWFyVGFzayA9IGZ1bmN0aW9uIGNsZWFySW1tZWRpYXRlKGlkKXtcbiAgICBkZWxldGUgcXVldWVbaWRdO1xuICB9O1xuICAvLyBOb2RlLmpzIDAuOC1cbiAgaWYocmVxdWlyZSgnLi9fY29mJykocHJvY2VzcykgPT0gJ3Byb2Nlc3MnKXtcbiAgICBkZWZlciA9IGZ1bmN0aW9uKGlkKXtcbiAgICAgIHByb2Nlc3MubmV4dFRpY2soY3R4KHJ1biwgaWQsIDEpKTtcbiAgICB9O1xuICAvLyBCcm93c2VycyB3aXRoIE1lc3NhZ2VDaGFubmVsLCBpbmNsdWRlcyBXZWJXb3JrZXJzXG4gIH0gZWxzZSBpZihNZXNzYWdlQ2hhbm5lbCl7XG4gICAgY2hhbm5lbCA9IG5ldyBNZXNzYWdlQ2hhbm5lbDtcbiAgICBwb3J0ICAgID0gY2hhbm5lbC5wb3J0MjtcbiAgICBjaGFubmVsLnBvcnQxLm9ubWVzc2FnZSA9IGxpc3RlbmVyO1xuICAgIGRlZmVyID0gY3R4KHBvcnQucG9zdE1lc3NhZ2UsIHBvcnQsIDEpO1xuICAvLyBCcm93c2VycyB3aXRoIHBvc3RNZXNzYWdlLCBza2lwIFdlYldvcmtlcnNcbiAgLy8gSUU4IGhhcyBwb3N0TWVzc2FnZSwgYnV0IGl0J3Mgc3luYyAmIHR5cGVvZiBpdHMgcG9zdE1lc3NhZ2UgaXMgJ29iamVjdCdcbiAgfSBlbHNlIGlmKGdsb2JhbC5hZGRFdmVudExpc3RlbmVyICYmIHR5cGVvZiBwb3N0TWVzc2FnZSA9PSAnZnVuY3Rpb24nICYmICFnbG9iYWwuaW1wb3J0U2NyaXB0cyl7XG4gICAgZGVmZXIgPSBmdW5jdGlvbihpZCl7XG4gICAgICBnbG9iYWwucG9zdE1lc3NhZ2UoaWQgKyAnJywgJyonKTtcbiAgICB9O1xuICAgIGdsb2JhbC5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgbGlzdGVuZXIsIGZhbHNlKTtcbiAgLy8gSUU4LVxuICB9IGVsc2UgaWYoT05SRUFEWVNUQVRFQ0hBTkdFIGluIGNlbCgnc2NyaXB0Jykpe1xuICAgIGRlZmVyID0gZnVuY3Rpb24oaWQpe1xuICAgICAgaHRtbC5hcHBlbmRDaGlsZChjZWwoJ3NjcmlwdCcpKVtPTlJFQURZU1RBVEVDSEFOR0VdID0gZnVuY3Rpb24oKXtcbiAgICAgICAgaHRtbC5yZW1vdmVDaGlsZCh0aGlzKTtcbiAgICAgICAgcnVuLmNhbGwoaWQpO1xuICAgICAgfTtcbiAgICB9O1xuICAvLyBSZXN0IG9sZCBicm93c2Vyc1xuICB9IGVsc2Uge1xuICAgIGRlZmVyID0gZnVuY3Rpb24oaWQpe1xuICAgICAgc2V0VGltZW91dChjdHgocnVuLCBpZCwgMSksIDApO1xuICAgIH07XG4gIH1cbn1cbm1vZHVsZS5leHBvcnRzID0ge1xuICBzZXQ6ICAgc2V0VGFzayxcbiAgY2xlYXI6IGNsZWFyVGFza1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3Rhc2suanNcbi8vIG1vZHVsZSBpZCA9IDExMFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKipcbiAqIE1haW4gZW50cnkgb2YgU0RLLCBhY2Nlc3NpYmxlIG9uIHRoZSBgd2luZG93YCBnbG9iYWwgYXQgYHJlZDVwcm9zZGtgLlxuICpcbiAqIEBmaWxlIHJlZDVwcm8ubWluLmpzXG4gKiBAbW9kdWxlIHJlZDVwcm9zZGtcbiAqXG4gKlxuICovXG5cbi8vIFNES19WRVJTSU9OLCBMT0dfTEVWRUwgaW5qZWN0ZWQgZnJvbSB3ZWJwYWNrIGJ1aWxkLlxuaW1wb3J0IHsgTEVWRUxTLCBlc3RhYmxpc2hMb2dnZXIgfSBmcm9tICcuL2xvZydcbmltcG9ydCB7IGdldExvZ2dlciBhcyBfZ2V0TG9nZ2VyIH0gZnJvbSAnLi9sb2cnXG5pbXBvcnQgKiBhcyBzdWJzY3JpYmVyTGliIGZyb20gJy4vc3Vic2NyaWJlci9pbmRleCdcbmltcG9ydCAqIGFzIHB1Ymxpc2hlckxpYiBmcm9tICcuL3B1Ymxpc2hlci9pbmRleCdcbmltcG9ydCAqIGFzIHNoYXJlZE9iamVjdExpYiBmcm9tICcuL3NoYXJlZG9iamVjdC9pbmRleCdcbmltcG9ydCAqIGFzIHBsYXliYWNrRW51bSBmcm9tICcuL2VudW0vcGxheWJhY2snXG5pbXBvcnQgKiBhcyB3ZWJydGNFbnVtIGZyb20gJy4vZW51bS93ZWJydGMnXG5pbXBvcnQgKiBhcyBwdWJsaXNoZXJFdmVudCBmcm9tICcuL2V2ZW50L3B1Ymxpc2hlci1ldmVudCdcbmltcG9ydCAqIGFzIHN1YnNjcmliZXJFdmVudCBmcm9tICcuL2V2ZW50L3N1YnNjcmliZXItZXZlbnQnXG5pbXBvcnQgKiBhcyBzaGFyZWRvYmplY3RFdmVudCBmcm9tICcuL2V2ZW50L3NoYXJlZG9iamVjdC1ldmVudCdcbmltcG9ydCBQbGF5YmFja1ZpZXcgZnJvbSAnLi92aWV3L3BsYXliYWNrJ1xuaW1wb3J0IFB1Ymxpc2hlclZpZXcgZnJvbSAnLi92aWV3L3B1Ymxpc2gnXG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gICovXG4vKiBTdWJzY3JpcHRpb24gcmVsYXRlZCByZWZlcmVuY2VzLiAqL1xuLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgKi9cblxuLyoqXG4gKiBUaGUgZmFpbC1vdmVyIGVuYWJsZWQgU3Vic2NyaWJlciBGYWN0b3J5LlxuICogQHNlZSBSZWQ1UHJvU3Vic2NyaWJlclxuICovXG5leHBvcnQgY29uc3QgUmVkNVByb1N1YnNjcmliZXIgPSBzdWJzY3JpYmVyTGliLlJlZDVQcm9TdWJzY3JpYmVyXG4vKipcbiAqIFRoZSBXZWJSVEMgYmFzZWQgU3Vic2NyaWJlci5cbiAqXG4gKiBBbiBpbnN0YW5jZSBvZiBgUlRDU3Vic2NyaWJlcmAgY2FuIGJlIGNyZWF0ZWQgZXhwbGljaXRseSB1c2luZyB0aGlzIGNsYXNzLCBvciBieSB0aGUgYFJlZDVQcm9TdWJzY3JpYmVyYCBmYWlsLW92ZXIgZmFjdG9yeS5cbiAqIEBzZWUgUlRDU3Vic2NyaWJlclxuICovXG5leHBvcnQgY29uc3QgUlRDU3Vic2NyaWJlciA9IHN1YnNjcmliZXJMaWIuUlRDU3Vic2NyaWJlclxuLyoqXG4gKiBUaGUgRmxhc2ggKHV0aWxpemluZyBSVE1QIHByb3RvY29sKSBiYXNlZCBTdWJzY3JpYmVyLlxuICpcbiAqIEFuIGluc3RhbmNlIG9mIGBSVE1QU3Vic2NyaWJlcmAgY2FuIGJlIGNyZWF0ZWQgZXhwbGljaXRseSB1c2luZyB0aGlzIGNsYXNzLCBvciBieSB0aGUgYFJlZDVQcm9TdWJzY3JpYmVyYCBmYWlsLW92ZXIgZmFjdG9yeS5cbiAqIEBzZWUgUlRNUFN1YnNjcmliZXJcbiAqL1xuZXhwb3J0IGNvbnN0IFJUTVBTdWJzY3JpYmVyID0gc3Vic2NyaWJlckxpYi5SVE1QU3Vic2NyaWJlclxuLyoqXG4gKiBUaGUgSExTIChIVFRQIExpdmUgU3RyZWFtKSBiYXNlZCBTdWJzY3JpYmVyLlxuICpcbiAqIEFuIGluc3RhbmNlIG9mIGBITFNTdWJzY3JpYmVyYCBjYW4gYmUgY3JlYXRlZCBleHBsaWNpdGx5IHVzaW5nIHRoaXMgY2xhc3MsIG9yIGJ5IHRoZSBgUmVkNVByb1N1YnNjcmliZXJgIGZhaWwtb3ZlciBmYWN0b3J5LlxuICogQHNlZSBITFNTdWJzY3JpYmVyXG4gKi9cbmV4cG9ydCBjb25zdCBITFNTdWJzY3JpYmVyID0gc3Vic2NyaWJlckxpYi5ITFNTdWJzY3JpYmVyXG4vKipcbiAqIFN0aWxsIHVzZWQsIGJ1dCBBUEktZGVwcmVjYXRlZCBWaWV3IGluc3RhbmNlIGZvciBwbGF5YmFjay4gSGFzIGRlZmF1bHQgc2V0dXAgaW4gdmVyc2lvbiA0LjAuMC5cbiAqIEBwcml2YXRlXG4gKi9cbmV4cG9ydCB7IFBsYXliYWNrVmlldyB9XG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gICovXG4vKiBCcm9hZGNhc3QgcmVsYXRlZCByZWZlcmVuY2VzLiAqL1xuLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgKi9cblxuLyoqXG4gKiBUaGUgZmFpbC1vdmVyIGVuYWJsZWQgUHVibGlzaGVyIEZhY3RvcnkuXG4gKiBAc2VlIFJlZDVQcm9QdWJsaXNoZXJcbiAqL1xuZXhwb3J0IGNvbnN0IFJlZDVQcm9QdWJsaXNoZXIgPSBwdWJsaXNoZXJMaWIuUmVkNVByb1B1Ymxpc2hlclxuLyoqXG4gKiBUaGUgV2ViUlRDIGJhc2VkIFB1Ymxpc2hlci48YnI+QW4gaW5zdGFuY2Ugb2YgYFJUQ1B1Ymxpc2hlcmAgY2FuIGJlIGNyZWF0ZWQgZXhwbGljaXRseSB1c2luZyB0aGlzIGNsYXNzLCBvciBieSB0aGUgYFJlZDVQcm9QdWJsaXNoZXJgIGZhaWwtb3ZlciBmYWN0b3J5LlxuICogQHNlZSBSVENQdWJsaXNoZXJcbiAqL1xuZXhwb3J0IGNvbnN0IFJUQ1B1Ymxpc2hlciA9IHB1Ymxpc2hlckxpYi5SVENQdWJsaXNoZXJcbi8qKlxuICogVGhlIEZsYXNoICh1dGlsaXppbmcgUlRNUCBwcm90b2NvbCkgYmFzZWQgUHVibGlzaGVyLlxuICpcbiAqIEFuIGluc3RhbmNlIG9mIGBSVE1QUHVibGlzaGVyYCBjYW4gYmUgY3JlYXRlZCBleHBsaWNpdGx5IHVzaW5nIHRoaXMgY2xhc3MsIG9yIGJ5IHRoZSBgUmVkNVByb1B1Ymxpc2hlcmAgZmFpbC1vdmVyIGZhY3RvcnkuXG4gKiBAc2VlIFJUTVBQdWJsaXNoZXJcbiAqL1xuZXhwb3J0IGNvbnN0IFJUTVBQdWJsaXNoZXIgPSBwdWJsaXNoZXJMaWIuUlRNUFB1Ymxpc2hlclxuLyoqXG4gKiBTdGlsbCB1c2VkLCBidXQgQVBJLWRlcHJlY2F0ZWQgVmlldyBpbnN0YW5jZSBmb3IgYnJvYWRjYXN0L3ByZXZpZXcuIEhhcyBkZWZhdWx0IHNldHVwIGluIHZlcnNpb24gNC4wLjAuXG4gKiBAcHJpdmF0ZVxuICovXG5leHBvcnQgeyBQdWJsaXNoZXJWaWV3IH1cblxuLyogUGxheWJhY2sgY29udHJvbHMgaW50ZXJmYWNlLiAqL1xuZXhwb3J0IHsgUGxheWJhY2tDb250cm9scyBhcyBQbGF5YmFja0NvbnRyb2xzIH0gZnJvbSAnLi9zdWJzY3JpYmVyL2NvbnRyb2xzL2luZGV4J1xuXG4vKiBTaGFyZWQgT2JqZWN0IHJlZmVyZW5jZXMuICovXG4vKipcbiAqIFRoZSBTaGFyZE9iamVjdCBjbGFzcy5cbiAqIEBzZWUgUmVkNVByb1NoYXJlZE9iamVjdFxuICovXG5leHBvcnQgY29uc3QgUmVkNVByb1NoYXJlZE9iamVjdCA9IHNoYXJlZE9iamVjdExpYi5SZWQ1UHJvU2hhcmVkT2JqZWN0XG5cbi8qIEV2ZW50cyAqL1xuLyoqXG4gKiBFbnVtZXJhdGlvbiBvZiBjb21tb24gUHVibGlzaGVyIEV2ZW50cy5cbiAqL1xuZXhwb3J0IGNvbnN0IFB1Ymxpc2hlckV2ZW50VHlwZXMgPSBwdWJsaXNoZXJFdmVudC5QdWJsaXNoZXJFdmVudFR5cGVzXG4vKipcbiAqIEVudWVyYXRpb24gb2YgZXZlbnRzIHNwZWNpZmljIHRvIFdlYlJUQy1iYXNlZCBQdWJsaXNoZXJzLlxuICovXG5leHBvcnQgY29uc3QgUlRDUHVibGlzaGVyRXZlbnRUeXBlcyA9IHB1Ymxpc2hlckV2ZW50LlJUQ1B1Ymxpc2hlckV2ZW50VHlwZXNcbi8qKlxuICogRW51bWVyYXRpb24gb2YgZXZlbnRzIHNwZWNpZmljIHRvIGZhaWwtb3ZlciBQdWJsaXNoZXIgZmFjdG9yeS5cbiAqL1xuZXhwb3J0IGNvbnN0IEZhaWxvdmVyUHVibGlzaGVyRXZlbnRUeXBlcyA9IHB1Ymxpc2hlckV2ZW50LkZhaWxvdmVyUHVibGlzaGVyRXZlbnRUeXBlc1xuLyoqXG4gKiBFbnVtZXJhaXRvbiBvZiBjb21tb24gU3Vic2NyaWJlciBFdmVudHMuXG4gKi9cbmV4cG9ydCBjb25zdCBTdWJzY3JpYmVyRXZlbnRUeXBlcyA9IHN1YnNjcmliZXJFdmVudC5TdWJzY3JpYmVyRXZlbnRUeXBlc1xuLyoqXG4gKiBFbnVtZXJhdGlvbiBvZiBldmVudHMgc3BlY2lmaWMgdG8gV2ViUlRDLWJhc2VkIFN1YnNjcmliZXJzLlxuICovXG5leHBvcnQgY29uc3QgUlRDU3Vic2NyaWJlckV2ZW50VHlwZXMgPSBzdWJzY3JpYmVyRXZlbnQuUlRDU3Vic2NyaWJlckV2ZW50VHlwZXNcbi8qKlxuICogRW51bWVyYXRpb24gb2YgZXZlbnRzIHNwZWNpZmljIHRvIFJUTVAtYmFzZWQgU3Vic2NyaWJlcnMuXG4gKi9cbmV4cG9ydCBjb25zdCBSVE1QU3Vic2NyaWJlckV2ZW50VHlwZXMgPSBzdWJzY3JpYmVyRXZlbnQuUlRDU3Vic2NyaWJlckV2ZW50VHlwZXNcbi8qKlxuICogRW51bWVyYXRpb24gb2YgZXZlbnRzIHNwZWNpZmljIHRvIGZhaWwtb3ZlciBTdWJzY3JpYmVyIGZhY3RvcnkuXG4gKi9cbmV4cG9ydCBjb25zdCBGYWlsb3ZlclN1YnNjcmliZXJFdmVudFR5cGVzID0gc3Vic2NyaWJlckV2ZW50LkZhaWxvdmVyU3Vic2NyaWJlckV2ZW50VHlwZXNcbi8qKlxuICogRW51bWVyYXRpb24gb2YgZXZlbnRzIGZvciBTaGFyZWQgT2JqZWN0cy5cbiAqL1xuZXhwb3J0IGNvbnN0IFNoYXJlZE9iamVjdEV2ZW50VHlwZXMgPSBzaGFyZWRvYmplY3RFdmVudC5TaGFyZWRPYmplY3RFdmVudFR5cGVzXG5cbi8qIEVudW1zICovXG4vKipcbiAqIEVudW1lcmF0ZSBBdWRpbyBFbmNvZGVyIG9wdGlvbnMgZm9yIFN1YnNjcmliZXJzLlxuICogICogYE9QVVNgXG4gKiAgKiBgUENNVWBcbiAqICAqIGBQQ01BYFxuICogICogYFNQRUVYYFxuICogICogYE5PTkVgXG4gKi9cbmV4cG9ydCBjb25zdCBQbGF5YmFja0F1ZGlvRW5jb2RlciA9IHBsYXliYWNrRW51bS5QbGF5YmFja0F1ZGlvRW5jb2RlclxuLyoqXG4gKiBFbnVtZXJhdGVkIFZpZGVvIEVuY29kZXIgb3B0aW9ucyBmb3IgU3Vic2NyaWJlcnMuXG4gKiAgKiBgVlA4YFxuICogICogYEgyNjRgXG4gKiAgKiBgTk9ORWBcbiAqL1xuZXhwb3J0IGNvbnN0IFBsYXliYWNrVmlkZW9FbmNvZGVyID0gcGxheWJhY2tFbnVtLlBsYXliYWNrVmlkZW9FbmNvZGVyXG5cbi8qKlxuICogRW51bWVyYXRlIElDRSBUcmFuc3BvcnQgb3B0aW9ucyBmb3IgUHVibGlzaGVycyBhbmQgU3Vic2NyaWJlcnMuXG4gKiAqIGBVRFBgXG4gKiAqIGBUQ1BgXG4gKi9cbmV4cG9ydCBjb25zdCBJY2VUcmFuc3BvcnRUeXBlcyA9IHdlYnJ0Y0VudW0uSWNlVHJhbnNwb3J0VHlwZXNcblxuZXN0YWJsaXNoTG9nZ2VyKGAke0xPR19MRVZFTH1gIHx8IExFVkVMUy5ERUJVRykgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bmRlZlxuXG4vKipcbiAqIFNldHMgdGhlIGxvZyBsZXZlbCBmb3IgbG9ncyBmcm9tIHRoZSBTREtcbiAqIEBwYXJhbSB7c3RyaW5nfSBsZXZlbFxuICogICAgVGhlIHNwZWNpZmllZCBsb2cgbGV2ZWwuXG4gKiBAc2VlIExPR19MRVZFTFNcbiAqL1xuZXhwb3J0IGNvbnN0IHNldExvZ0xldmVsID0gKGxldmVsKSA9PiB7XG4gIGlmIChMRVZFTFMuaGFzT3duUHJvcGVydHkobGV2ZWwudG9VcHBlckNhc2UoKSkpIHtcbiAgICBlc3RhYmxpc2hMb2dnZXIobGV2ZWwpXG4gICAgaWYgKGNvbnNvbGUpIHtcbiAgICAgIGNvbnNvbGUubG9nKGBSZWQ1IFBybyBTREsgVmVyc2lvbiAke1NES19WRVJTSU9OfWApIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWYsbm8tY29uc29sZVxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFRoZSBlbnVtZXJhdGVkIGxvZyBsZXZlbCBTdHJpbmdzLlxuICogICAgKiBgVFJBQ0VgXG4gKiAgICAqIGBJTkZPYFxuICogICAgKiBgREVCVUdgXG4gKiAgICAqIGBXQVJOYFxuICogICAgKiBgRVJST1JgXG4gKiAgICAqIGBGQVRBTGBcbiAqL1xuZXhwb3J0IGNvbnN0IExPR19MRVZFTFMgPSBMRVZFTFNcbi8qKlxuICogUmV0cmlldmVzIHRoZSBMb2dnZXIgaW5zdGFuY2UgdXNlZCBieSB0aGUgU0RLLlxuICpcbiAqIEByZXR1cm5zIHtMb2dnZXJ9XG4gKiAgICAgICAgICBUaGUgbG9nZ2VyLlxuICovXG5leHBvcnQgY29uc3QgZ2V0TG9nZ2VyID0gX2dldExvZ2dlclxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2pzL2luZGV4LmpzIiwiJ3VzZSBzdHJpY3QnXG5cbmNvbnN0IGpzb25BdHRyID0gL1snXCJdKC4qPylbJ1wiXTovZ2lcbmNvbnN0IGpzb25WYWwgPSAvOlsnXCJdKC4qPylbJ1wiXS9naVxuXG4vKipcbiAqIFJlYWRzIHRoZSBVVEYgc3RyaW5nIG9mIHRoZSBkYXRhIHBhc3NlZCBpbi5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gZGF0YVxuICogQHBhcmFtIHtOdW1iZXJ9IHN0YXJ0XG4gKiBAcGFyYW0ge051bWJlcn0gbGVuXG4gKlxuICogQHJldHVybiB7U3RyaW5nfVxuICogICAgICAgICBUaGUgUGFyc2VkIGluZm9ybWF0aW9uLlxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHJlYWRVVEYgKGRhdGEsc3RhcnQsbGVuKSB7XG4gIGxldCByZXN1bHQgPSAnJywgb2Zmc2V0ID0gc3RhcnQsIGVuZCA9IHN0YXJ0ICsgbGVuXG4gIGRvIHtcbiAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShkYXRhW29mZnNldCsrXSlcbiAgfVxuICB3aGlsZShvZmZzZXQgPCBlbmQpXG4gIHJldHVybiByZXN1bHRcbn1cblxuLyoqXG4gKiBQYXJzZXMgYW5kIGludGVycHJldHMgdGhlIG9yaWVudGF0aW9uIGRhdGEgZnJvbSBwYXNzZWQgaW4gSlNPTiBzdHJpbmcuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHRleHRcbiAqXG4gKiBAcmV0dXJuIHtPYmplY3R9XG4gKiAgICAgICAgICBUaGUgcGFyc2VkIG9iamVjdCB3aXRoIGFuIGBvcmllbnRhdGlvbmAgcHJvcGVydHkgaWYgcGFyc2VkIHByb3Blcmx5LlxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHBhcnNlSlNPTkZvck9yaWVudGF0aW9uICh0ZXh0KSB7XG4gIHRyeSB7XG4gICAgbGV0IHZhbHVlID0gSlNPTi5wYXJzZSh0ZXh0KVxuICAgIGlmICh2YWx1ZS5oYXNPd25Qcm9wZXJ0eSgnb3JpZW50YXRpb24nKSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgb3JpZW50YXRpb246IHBhcnNlSW50KHZhbHVlLm9yaWVudGF0aW9uKVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkXG4gIH1cbiAgY2F0Y2ggKGUpIHtcbiAgICBsZXQgbWF0Y2ggPSBqc29uQXR0ci5leGVjKHRleHQpXG4gICAgbGV0IG1hdGNoMlxuICAgIGlmIChtYXRjaCAmJiBtYXRjaC5sZW5ndGggPiAxKSB7XG4gICAgICBtYXRjaDIgPSBqc29uVmFsLmV4ZWModGV4dClcbiAgICAgIGlmIChtYXRjaFsxXSA9PT0gJ29yaWVudGF0aW9uJyAmJiBtYXRjaDIgJiYgbWF0Y2gyLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBvcmllbnRhdGlvbjogcGFyc2VJbnQobWF0Y2gyWzFdKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWRcbiAgfVxufVxuXG4vKipcbiAqIEV2ZW50IGhhbmRsZXIgZm9yIG1ldGFkYXRhIHJlbGF0ZWQgdG8gb3JpZW50YXRpb24gaW5mb3JtYXRpb24uXG4gKlxuICogQHBhcmFtIHtFbGVtZW50fSBwbGF5ZXJcbiAqICAgICAgICBUaGUgbWVkaWEgZWxlbWVudCByZWxhdGVkIHRvIHRoZSBtZXRhZGF0YS5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gKiAgICAgICAgVGhlIGNhbGxiYWNrIHRvIGludm9rZSB3aXRoIHRoZSBwYXJzZWQgb3JpZW50YXRpb24gaW5mb3JtYXRpb24uXG4gKlxuICogQHByaXZhdGVcbiAqL1xuZXhwb3J0IGNvbnN0IG9uT3JpZW50YXRpb25NZXRhZGF0YSA9IChwbGF5ZXIsIGNhbGxiYWNrKSA9PiB7XG5cbiAgY29uc3QgdGV4dFRyYWNrcyA9IHR5cGVvZiBwbGF5ZXIudGV4dFRyYWNrcyA9PT0gJ2Z1bmN0aW9uJyA/IHBsYXllci50ZXh0VHJhY2tzKCkgOiBwbGF5ZXIudGV4dFRyYWNrc1xuXG4gIGlmICh0ZXh0VHJhY2tzKSB7XG5cbiAgICBwbGF5ZXIuYWRkVGV4dFRyYWNrKCdtZXRhZGF0YScpXG5cbiAgICB0ZXh0VHJhY2tzLmFkZEV2ZW50TGlzdGVuZXIoJ2FkZHRyYWNrJywgYWRkVHJhY2tFdmVudCA9PiB7XG5cbiAgICAgIGxldCB0cmFjayA9IGFkZFRyYWNrRXZlbnQudHJhY2tcbiAgICAgIHRyYWNrLm1vZGUgPSAnaGlkZGVuJ1xuICAgICAgdHJhY2suYWRkRXZlbnRMaXN0ZW5lcignY3VlY2hhbmdlJywgY3VlQ2hhbmdlRXZlbnQgPT4ge1xuICAgICAgICBsZXQgY3Vlc1xuICAgICAgICBsZXQgaVxuICAgICAgICAvLyBNb3N0bHkgQ2hyb21lLlxuICAgICAgICBpZiAoY3VlQ2hhbmdlRXZlbnQgJiYgY3VlQ2hhbmdlRXZlbnQuY3VycmVudFRhcmdldCkge1xuICAgICAgICAgIGN1ZXMgPSBjdWVDaGFuZ2VFdmVudC5jdXJyZW50VGFyZ2V0LmN1ZXNcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh1bmRlZmluZWQgPT09IHRoaXMpIHtcbiAgICAgICAgICBjdWVzID0gdHJhY2suY3Vlc1xuICAgICAgICAgIGN1ZXMgPSBjdWVzICYmIGN1ZXMubGVuZ3RoID4gMCA/IGN1ZXMgOiB0cmFjay5hY3RpdmVDdWVzXG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodW5kZWZpbmVkICE9PSB0aGlzKSB7XG4gICAgICAgICAgLy8gTW9zdGx5IEZpcmVmb3ggJiBTYWZhcmkuXG4gICAgICAgICAgY3VlcyA9IGN1ZXMgJiYgY3Vlcy5sZW5ndGggPiAwID8gY3VlcyA6IHRoaXMuYWN0aXZlQ3Vlc1xuICAgICAgICB9XG4gICAgICAgIC8vIE1vc3RseSBmYWlsdXJlLlxuICAgICAgICBjdWVzID0gY3VlcyB8fCBbXVxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY3Vlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGxldCBkYXRhID0gY3Vlc1tpXVxuICAgICAgICAgIGlmIChkYXRhLnZhbHVlKSB7XG4gICAgICAgICAgICBsZXQgdGV4dCA9IHR5cGVvZiBkYXRhLnZhbHVlLmRhdGEgPT09ICdzdHJpbmcnID8gZGF0YS52YWx1ZS5kYXRhIDogcmVhZFVURiggZGF0YS52YWx1ZS5kYXRhICwgMCAsIGRhdGEuc2l6ZSlcbiAgICAgICAgICAgIGxldCBvcmllbnRhdGlvbiA9IHBhcnNlSlNPTkZvck9yaWVudGF0aW9uKHRleHQpXG4gICAgICAgICAgICBpZiAodHlwZW9mIG9yaWVudGF0aW9uICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICBjYWxsYmFjayhvcmllbnRhdGlvbilcbiAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pXG5cbiAgICB9KVxuXG4gIH1cbn1cblxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2pzL2Vudi9tZXRhZGF0YS11dGlsLmpzIiwiJ3VzZSBzdHJpY3QnXG5cbi8qKlxuICogRXhjZXB0aW9uIGZvciBtaXNzaW5nIGVsZW1lbnQgd2hlbiBhc3NpZ25pbmcgUHJlc2VudGF0aW9uIENvbnRyb2xsZXJzIGZvciBQdWJsaXNoZXJzIGFuZCBTdWJzY3JpYmVycy5cbiAqL1xuZXhwb3J0IGNsYXNzIE5vRWxlbWVudEZvdW5kRXJyb3Ige1xuICBjb25zdHJ1Y3RvciAobWVzc2FnZSkge1xuICAgIHRoaXMubmFtZSA9ICdOb0VsZW1lbnRGb3VuZCdcbiAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlXG4gIH1cbn1cblxuLyoqXG4gKiBFeGNlcHRpb24gd2hlbiByZXF1ZXN0aW5nIG1lZGlhIHdpdGggYSBgTWVkaWFDb25zdHJhaW50YCB0aGF0IHRoZSBicm93c2VyIGNhbm5vdCBzdXBwb3J0LlxuICogV2ViUlRDIE9ubHkuXG4gKi9cbmV4cG9ydCBjbGFzcyBOb1N1cHBvcnRlZENhbWVyYVJlc29sdXRpb25zRXJyb3Ige1xuICBjb25zdHJ1Y3RvciAobWVzc2FnZSkge1xuICAgIHRoaXMubmFtZSA9ICdOb1N1cHBvcnRlZENhbWVyYVJlc29sdXRpb25zRXJyb3InXG4gICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZVxuICB9XG59XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvanMvZXhjZXB0aW9uL2Vycm9ycy5qcyIsIid1c2Ugc3RyaWN0J1xuXG5pbXBvcnQgU29ja2V0SGVscGVyIGZyb20gJy4vc29ja2V0LWhlbHBlcidcbmltcG9ydCB7IGlzT2JqZWN0RW1wdHkgfSBmcm9tICcuLi91dGlsL29iamVjdCdcbmltcG9ydCB7IHdhcm4sIGVycm9yIH0gZnJvbSAnLi4vbG9nJ1xuXG5jb25zdCBOQU1FID0gJ1I1UHJvUHVibGlzaGVyU29ja2V0J1xuXG4vKipcbiAqIFB1Ymxpc2hlci1iYXNlZCBleHRlbnNpb24gb2YgYFNvY2tldEhlbHBlcmAuXG4gKlxuICogQGV4dGVuZHMge1NvY2tldEhlbHBlcn1cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5jbGFzcyBQdWJsaXNoZXJTb2NrZXRIZWxwZXIgZXh0ZW5kcyBTb2NrZXRIZWxwZXIge1xuXG4gIGNvbnN0cnVjdG9yIChyZXNwb25kZXIpIHtcbiAgICBzdXBlcihyZXNwb25kZXIsIE5BTUUpXG4gIH1cblxuICAvKipcbiAgICogT3ZlcnJpZGUgdG8gcmVzcG9uZCB0byBtZXNzYWdlcyBjb21pbmcgb3ZlciBXZWJTb2NrZXQuXG4gICAqL1xuICByZXNwb25kIChtZXNzYWdlKSB7XG4gICAgaWYgKG1lc3NhZ2UuZGF0YSkge1xuICAgICAgbGV0IGpzb24gPSB0aGlzLmdldEpzb25Gcm9tU29ja2V0TWVzc2FnZShtZXNzYWdlKVxuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKCFzdXBlci5yZXNwb25kKG1lc3NhZ2UpKSB7XG4gICAgICAgICAgaWYgKGpzb24uZGF0YSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBpZiAoanNvbi5kYXRhLnNkcCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgIGlmIChqc29uLmRhdGEuc2RwLnR5cGUgPT09ICdhbnN3ZXInKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVzcG9uZGVyLm9uU0RQQW5zd2VyKGpzb24uZGF0YSlcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGpzb24uZGF0YS5jYW5kaWRhdGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBpZiAoaXNPYmplY3RFbXB0eShqc29uLmRhdGEuY2FuZGlkYXRlKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3Jlc3BvbmRlci5vbkVtcHR5Q2FuZGlkYXRlKClcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9yZXNwb25kZXIub25BZGRJY2VDYW5kaWRhdGUoanNvbi5kYXRhLmNhbmRpZGF0ZSlcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGpzb24uZGF0YS50eXBlID09PSAnc3RhdHVzJykge1xuICAgICAgICAgICAgICBpZiAoanNvbi5kYXRhLmNvZGUgPT09ICdOZXRDb25uZWN0aW9uLklDRS5UcmljbGVDb21wbGV0ZWQnIHx8XG4gICAgICAgICAgICAgICAgIGpzb24uZGF0YS5jb2RlID09PSAnTmV0Q29ubmVjdGlvbi5JQ0UuVHJpY2tsZUNvbXBsZXRlZCcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9yZXNwb25kZXIub25Tb2NrZXRJY2VDYW5kaWRhdGVFbmQoKVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuX3Jlc3BvbmRlci5vblB1Ymxpc2hlclN0YXR1cyhqc29uLmRhdGEpXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgZXJyb3IoTkFNRSwgYFt3cy5vbm1lc3NhZ2VdIC0gRXJyb3IgaW4gYWNjZXNzaW5nIG1lc3NhZ2UgZGF0YSBhcyBKU09OLiAke2UubWVzc2FnZX1gKVxuICAgICAgICB0aGlzLl9yZXNwb25kZXIub25Tb2NrZXRNZXNzYWdlRXJyb3IoYFt3cy5vbm1lc3NhZ2VdIC0gRXJyb3IgaW4gYWNjZXNzaW5nIG1lc3NhZ2UgZGF0YSBhcyBKU09OLiAke2UubWVzc2FnZX1gKVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB3YXJuKE5BTUUsICdbd3Mub25tZXNzYWdlXSAtIE5vIE1lc3NhZ2UgRGF0YS4nKVxuICAgIH1cbiAgfVxuXG59XG5cbmV4cG9ydCBkZWZhdWx0IFB1Ymxpc2hlclNvY2tldEhlbHBlclxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2pzL2hlbHBlci9zb2NrZXQtaGVscGVyLXB1Yi5qcyIsIid1c2Ugc3RyaWN0J1xuXG5pbXBvcnQgU29ja2V0SGVscGVyIGZyb20gJy4vc29ja2V0LWhlbHBlcidcbmltcG9ydCB7IGlzT2JqZWN0RW1wdHkgfSBmcm9tICcuLi91dGlsL29iamVjdCdcbmltcG9ydCB7IHdhcm4sIGVycm9yIH0gZnJvbSAnLi4vbG9nJ1xuXG5jb25zdCBOQU1FID0gJ1I1UHJvU3Vic2NyaXB0aW9uU29ja2V0J1xuXG4vKipcbiAqIFN1YnNjcmliZXItYmFzZWQgZXh0ZW5zaW9uIG9mIGBTb2NrZXRIZWxwZXJgLlxuICpcbiAqIEBleHRlbmRzIHtTb2NrZXRIZWxwZXJ9XG4gKlxuICogQHByaXZhdGVcbiAqL1xuY2xhc3MgU3Vic2NyaXB0aW9uU29ja2V0SGVscGVyIGV4dGVuZHMgU29ja2V0SGVscGVyIHtcblxuICBjb25zdHJ1Y3RvciAocmVzcG9uZGVyKSB7XG4gICAgc3VwZXIocmVzcG9uZGVyLCBOQU1FKVxuICB9XG5cbiAgLyoqXG4gICAqIE92ZXJyaWRlIHRvIHJlc3BvbmQgdG8gbWVzc2FnZXMgY29taW5nIG92ZXIgV2ViU29ja2V0LlxuICAgKi9cbiAgcmVzcG9uZCAobWVzc2FnZSkge1xuICAgIGlmIChtZXNzYWdlLmRhdGEpIHtcbiAgICAgIGxldCBqc29uID0gdGhpcy5nZXRKc29uRnJvbVNvY2tldE1lc3NhZ2UobWVzc2FnZSlcbiAgICAgIHRyeSB7XG4gICAgICAgIGlmICghc3VwZXIucmVzcG9uZChtZXNzYWdlKSkge1xuICAgICAgICAgIGlmIChqc29uLmRhdGEgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYgKGpzb24uZGF0YS5zZHAgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBpZiAoanNvbi5kYXRhLnNkcC50eXBlID09PSAnb2ZmZXInKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVzcG9uZGVyLm9uU0RQT2ZmZXIoanNvbi5kYXRhKVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoanNvbi5kYXRhLmNhbmRpZGF0ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgIGlmIChpc09iamVjdEVtcHR5KGpzb24uZGF0YS5jYW5kaWRhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVzcG9uZGVyLm9uRW1wdHlDYW5kaWRhdGUoKVxuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuX3Jlc3BvbmRlci5vbkFkZEljZUNhbmRpZGF0ZShqc29uLmRhdGEuY2FuZGlkYXRlKVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoanNvbi5kYXRhLnR5cGUgPT09ICdzdGF0dXMnKSB7XG4gICAgICAgICAgICAgIGlmIChqc29uLmRhdGEuY29kZSA9PT0gJ05ldENvbm5lY3Rpb24uSUNFLlRyaWNsZUNvbXBsZXRlZCcgfHxcbiAgICAgICAgICAgICAgICAganNvbi5kYXRhLmNvZGUgPT09ICdOZXRDb25uZWN0aW9uLklDRS5Ucmlja2xlQ29tcGxldGVkJykge1xuICAgICAgICAgICAgICAgIHRoaXMuX3Jlc3BvbmRlci5vblNvY2tldEljZUNhbmRpZGF0ZUVuZCgpXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZWxzZSBpZiAoanNvbi5kYXRhLmNvZGUgPT09ICdOZXRTdHJlYW0uUGxheS5VbnB1Ymxpc2hOb3RpZnknKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVzcG9uZGVyLm9uVW5wdWJsaXNoKClcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBlbHNlIGlmIChqc29uLmRhdGEuY29kZSA9PT0gJ05ldENvbm5lY3Rpb24uQ29ubmVjdC5DbG9zZWQnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVzcG9uZGVyLm9uQ29ubmVjdGlvbkNsb3NlZCgpXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVzcG9uZGVyLm9uU3Vic2NyaWJlclN0YXR1cyhqc29uLmRhdGEpXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChqc29uLmRhdGEuaGFzT3duUHJvcGVydHkoJ3N0YXR1cycpKSB7XG4gICAgICAgICAgICAgIGlmIChqc29uLmRhdGEuc3RhdHVzID09PSAnTmV0U3RyZWFtLlBsYXkuVW5wdWJsaXNoTm90aWZ5Jykge1xuICAgICAgICAgICAgICAgIHRoaXMuX3Jlc3BvbmRlci5vblVucHVibGlzaCgpXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChqc29uLnR5cGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBpZiAoanNvbi50eXBlID09PSAnbWV0YWRhdGEnKSB7XG4gICAgICAgICAgICAgICAgLy8gSXQgaXMgYSBgc2VuZGAgQVBJIGludm9jYXRpb24uXG4gICAgICAgICAgICAgICAgaWYgKGpzb24ubWV0aG9kICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgIHRoaXMuX3Jlc3BvbmRlci5vblNlbmRSZWNlaXZlZChqc29uLm1ldGhvZCwganNvbi5kYXRhKVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBFbHNlIGl0IGlzIG5vcm1hbCBtZXRhZGF0YS5cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIHRoaXMuX3Jlc3BvbmRlci5vbk1ldGFEYXRhKGpzb24uZGF0YSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsc2UgaWYgKGpzb24udHlwZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBpZiAoanNvbi50eXBlID09PSAnbWV0YWRhdGEnKSB7XG4gICAgICAgICAgICAgIHRoaXMuX3Jlc3BvbmRlci5vbk1ldGFEYXRhKGpzb24ubWV0YWRhdGEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBlcnJvcihOQU1FLCBgW3dzLm9ubWVzc2FnZV0gLSBFcnJvciBpbiBhY2Nlc3NpbmcgbWVzc2FnZSBkYXRhIGFzIEpTT04uICR7ZS5tZXNzYWdlfWApXG4gICAgICAgIHRoaXMuX3Jlc3BvbmRlci5vblNvY2tldE1lc3NhZ2VFcnJvcihgW3dzLm9ubWVzc2FnZV0gLSBFcnJvciBpbiBhY2Nlc3NpbmcgbWVzc2FnZSBkYXRhIGFzIEpTT04uICR7ZS5tZXNzYWdlfWApXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHdhcm4oTkFNRSwgJ1t3cy5vbm1lc3NhZ2VdIC0gTm8gTWVzc2FnZSBEYXRhLicpXG4gICAgfVxuICB9XG5cbn1cbmV4cG9ydCBkZWZhdWx0IFN1YnNjcmlwdGlvblNvY2tldEhlbHBlclxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2pzL2hlbHBlci9zb2NrZXQtaGVscGVyLXN1Yi5qcyIsIid1c2Ugc3RyaWN0J1xuaW1wb3J0ICogYXMgd2VicnRjIGZyb20gJy4uL2FkYXB0ZXIvd2VicnRjJ1xuaW1wb3J0IHsgRGVmZXJyZWRQcm9taXNlIH0gZnJvbSAnLi4vdXRpbC9wcm9taXNlJ1xuaW1wb3J0IHsgZGVidWcsIHdhcm4gfSBmcm9tICcuLi9sb2cnXG5cbmNvbnN0IE5BTUUgPSAnUjVQcm9QdWJsaXNoUGVlcidcblxuLyoqXG4gKiBQcm94eSB0byBQZWVyIENvbm5lY3Rpb24gZm9yIFB1Ymxpc2hlcnMuXG4gKlxuICogQHByaXZhdGVcbiAqL1xuY2xhc3MgUHVibGlzaGVyUGVlckhlbHBlciB7XG5cbiAgY29uc3RydWN0b3IgKHJlc3BvbmRlcikge1xuICAgIHRoaXMuX3Jlc3BvbmRlciA9IHJlc3BvbmRlclxuICAgIHRoaXMuX3BlZXJDb25uZWN0aW9uID0gdW5kZWZpbmVkXG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyBoYW5kbGVycyBhc3NpZ25lZCB0byB0aGUgcGVlciBjb25uZWN0aW9uIGluc3RhbmNlLlxuICAgKlxuICAgKiBAcGFyYW0ge1JUQ1BlZXJDb25uZWN0aW9ufSBjb25uZWN0aW9uXG4gICAqL1xuICBfcmVtb3ZlQ29ubmVjdGlvbkhhbmRsZXJzIChjb25uZWN0aW9uKSB7XG4gICAgY29ubmVjdGlvbi5vbmNvbm5lY3Rpb25zdGF0ZWNoYW5nZSA9IHVuZGVmaW5lZFxuICAgIGNvbm5lY3Rpb24ub25pY2Vjb25uZWN0aW9uc3RhdGVjaGFuZ2UgPSB1bmRlZmluZWRcbiAgICBjb25uZWN0aW9uLm9uaWNlY2FuZGlkYXRlID0gdW5kZWZpbmVkXG4gIH1cblxuICAvKipcbiAgICogQXNzaWducyBoYW5kbGVycyB0byBldmVudHMgb24gdGhlIHBlZXIgY29ubmVjdGlvbiBpbnN0YW5jZS5cbiAgICpcbiAgICogQHBhcmFtIHtSVENQZWVyQ29ubmVjdGlvbn0gY29ubmVjdGlvblxuICAgKiBAcGFyYW0ge1Byb21pc2V9IHByb21pc2VcbiAgICogICAgICAgIFRoZSBgUHJvbWlzZWAgdG8gcmVzb2x2ZSBvciByZWplY3Qgb24gc3VjY2VzcyBvZiBjb25uZWN0aW9uLlxuICAgKi9cbiAgX2FkZENvbm5lY3Rpb25IYW5kbGVycyAoY29ubmVjdGlvbiwgcHJvbWlzZSkge1xuXG4gICAgbGV0IHJlY29ubmVjdFRpbWVvdXRcbiAgICBjb25zdCB0aW1lb3V0TGltaXQgPSA1MDAwXG5cbiAgICBjb25uZWN0aW9uLm9uY29ubmVjdGlvbnN0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgZGVidWcoTkFNRSwgYFtwZWVyLm9uY29ubmVjdGlvbnN0YXRlY2hhbmdlXSAtIFN0YXRlOiAke2Nvbm5lY3Rpb24uY29ubmVjdGlvblN0YXRlfWApXG4gICAgICBpZiAoY29ubmVjdGlvbi5jb25uZWN0aW9uU3RhdGUgPT09ICdjb25uZWN0ZWQnKSB7XG4gICAgICAgIGRlYnVnKE5BTUUsICdbcGVlcmNvbm5lY3Rpb246b3Blbl0nKVxuICAgICAgICBpZiAocHJvbWlzZSkge1xuICAgICAgICAgIHByb21pc2UucmVzb2x2ZSh0aGlzKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBlbHNlIGlmIChjb25uZWN0aW9uLmNvbm5lY3Rpb25TdGF0ZSA9PT0gJ2ZhaWxlZCcgfHxcbiAgICAgICAgY29ubmVjdGlvbi5jb25uZWN0aW9uU3RhdGUgPT09ICdkaXNjb25uZWN0ZWQnKSB7XG4gICAgICAgIHdhcm4oTkFNRSwgJ1twZWVyY29ubmVjdGlvbjplcnJvcl0nKVxuICAgICAgICBpZiAocHJvbWlzZSkge1xuICAgICAgICAgIHByb21pc2UucmVqZWN0KClcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIGRlYnVnKE5BTUUsIGBbcGVlcmNvbm5lY3Rpb246JHtjb25uZWN0aW9uLmNvbm5lY3Rpb25TdGF0ZX1dYClcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25uZWN0aW9uLm9uaWNlY2FuZGlkYXRlID0gKGV2ZW50KSA9PiB7XG4gICAgICBkZWJ1ZyhOQU1FLCBgW3BlZXIub25pY2VjYW5kaWRhdGVdIC0gUGVlciBDYW5kaWRhdGU6ICR7ZXZlbnQuY2FuZGlkYXRlfWApXG4gICAgICBpZiAoZXZlbnQuY2FuZGlkYXRlKSB7XG4gICAgICAgIHRoaXMuX3Jlc3BvbmRlci5vbkljZUNhbmRpZGF0ZShldmVudC5jYW5kaWRhdGUpXG4gICAgICB9IGVsc2UgaWYgKGV2ZW50LmNhbmRpZGF0ZSA9PT0gbnVsbCkge1xuICAgICAgICAvLyBudWxsIG1lYW5zIHRoZXkgaGF2ZSBmaW5pc2hlZCBzZW5kaW5nIGNhbmRpZGF0ZXMgYmFjayBhbmQgZm9ydGg/XG4gICAgICAgIC8vIE1vdmVkIHRvIG5vdGlmaWNhdGlvbiBmcm9tIHNlcnZlciBvbiB0cmlja2xlIGVuZCBldmVudC5cbiAgICAgICAgLy8gdGhpcy5fcmVzcG9uZGVyLm9uSWNlQ2FuZGlkYXRlVHJpY2tsZUVuZCgpXG4gICAgICB9XG4gICAgfVxuXG4gICAgY29ubmVjdGlvbi5vbmljZWNvbm5lY3Rpb25zdGF0ZWNoYW5nZSA9IChldmVudCkgPT4ge1xuICAgICAgY29uc3Qgc3RhdGUgPSBjb25uZWN0aW9uLmljZUNvbm5lY3Rpb25TdGF0ZVxuICAgICAgZGVidWcoTkFNRSwgYFtwZWVyLm9uaWNlY29ubmVjdGlvbnN0YXRlY2hhbmdlXSAtIFN0YXRlOiAke3N0YXRlfWApXG4gICAgICBpZiAoc3RhdGUgPT09ICdmYWlsZWQnKSB7XG4gICAgICAgIGlmIChyZWNvbm5lY3RUaW1lb3V0KSB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KHJlY29ubmVjdFRpbWVvdXQpXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcmVzcG9uZGVyLm9uUGVlckNvbm5lY3Rpb25DbG9zZShldmVudClcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKHN0YXRlID09PSAnZGlzY29ubmVjdGVkJykge1xuICAgICAgICAvLyBtYXkgcmVjZWl2ZSBhIGRpc2Nvbm5lY3QgdGVtcG9yYXJpbHkgdGhhdCB3aWxsIHRoZW4gcmV0dXJuIHRvIGEgY29ubmVjdGlvbi5cbiAgICAgICAgcmVjb25uZWN0VGltZW91dCA9IHNldFRpbWVvdXQoICgpID0+IHtcbiAgICAgICAgICBkZWJ1ZyhOQU1FLCBgW3BlZXIub25pY2Vjb25uZWN0aW9uc3RhdGVjaGFuZ2VdIC0gUmVjb25uZWN0IHRpbWVvdXQgcmVhY2hlZC4gQ2xvc2luZyBQZWVyQ29ubmVjdGlvbi5gKVxuICAgICAgICAgIGNsZWFyVGltZW91dChyZWNvbm5lY3RUaW1lb3V0KVxuICAgICAgICAgIHRoaXMuX3Jlc3BvbmRlci5vblBlZXJDb25uZWN0aW9uQ2xvc2UoZXZlbnQpXG4gICAgICAgIH0sIHRpbWVvdXRMaW1pdClcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBpZiAocmVjb25uZWN0VGltZW91dCkge1xuICAgICAgICAgIGRlYnVnKE5BTUUsIGBbcGVlci5vbmljZWNvbm5lY3Rpb25zdGF0ZWNoYW5nZV0gLSBDbGVhcmluZyB0aW1lb3V0IGZvciByZWNvbm5lY3QuYClcbiAgICAgICAgICBjbGVhclRpbWVvdXQocmVjb25uZWN0VGltZW91dClcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbm5lY3Rpb24ub25zaWduYWxpbmdzdGF0ZWNoYW5nZSA9IChldmVudCkgPT4geyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gICAgICBjb25zdCBzdGF0ZSA9IGNvbm5lY3Rpb24uc2lnbmFsaW5nU3RhdGVcbiAgICAgIGRlYnVnKE5BTUUsIGBbcGVlci5vbnNpZ25hbGluZ3N0YXRlY2hhbmdlXSAtIFN0YXRlOiAke3N0YXRlfWApXG4gICAgfVxuXG4gICAgY29ubmVjdGlvbi5vbmljZWdhdGhlcmluZ3N0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgY29uc3Qgc3RhdGUgPSBjb25uZWN0aW9uLmljZUdhdGhlcmluZ1N0YXRlXG4gICAgICBkZWJ1ZyhOQU1FLCBgW3BlZXIub25pY2VnYXRoZXJpbmdzdGF0ZWNoYW5nZV0gLSBTdGF0ZTogJHtzdGF0ZX1gKVxuICAgICAgaWYgKHN0YXRlID09PSAnY29tcGxldGUnKSB7XG4gICAgICAgIHRoaXMuX3Jlc3BvbmRlci5vblBlZXJHYXRoZXJpbmdDb21wbGV0ZSgpXG4gICAgICB9XG4gICAgfVxuXG4gICAgY29ubmVjdGlvbi5vbnJlbW92ZXN0cmVhbSA9ICgpID0+IHtcbiAgICAgIGRlYnVnKE5BTUUsIGBbcGVlci5vbnJlbW92ZXN0cmVhbV1gKVxuICAgIH1cblxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gYGdldFVzZXJNZWRpYWAgb24gYnJvd3Nlci5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbnRyYWludHNcbiAgICogICAgICAgIFRoZSBgTWVkaWFDb25zdHJhaW50c2Agb2JqZWN0LlxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKi9cbiAgZ2V0VXNlck1lZGlhIChjb25zdHJhaW50cykge1xuICAgIHJldHVybiB3ZWJydGMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzKVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gZm9yY2UgYGdldFVzZXJNZWRpYWAgcmVxdWVzdCB1c2luZyB0aGUgcHJvdmlkZWQgY29uc3RyYWludHMuXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBjb25zdHJhaW50c1xuICAgKiAgICAgICAgVGhlIGBNZWRpYUNvbnN0cmFpbnRzYCB0byBmb3JjZSBpbiByZXF1ZXN0IG9uIGBnZXRVc2VyTWVkaWFgLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKi9cbiAgZm9yY2VVc2VyTWVkaWEgKGNvbnN0cmFpbnRzKSB7XG4gICAgcmV0dXJuIHdlYnJ0Yy5mb3JjZVVzZXJNZWRpYShjb25zdHJhaW50cylcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIGNyZWF0ZSBhbiBPZmZlciB0aHJvdWdoIHRoZSBQZWVyIENvbm5lY3Rpb24uXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBiYW5kd2lkdGhcbiAgICogICAgICAgIFRoZSBvcHRpb25hbCBiYW5kd2lkdGggY29uZmlndXJhdGlvbiB0byB1c2UgaW4gbXVuZ2luZyBTRFAgYmVmb3JlIHNlbmRpbmcgb2ZmZXIuXG4gICAqIEBwYXJhbSB7UHJvbWlzZX0gcHJvbWlzZVxuICAgKiAgICAgICAgVGhlIGBQcm9taXNlYCB0byByZXNvbHZlIG9yIHJlamVjdCBvbiBzdWNjZXNzIG9mIHNlbmRpbmcgb2ZmZXIgb24gUGVlciBDb25uZWN0aW9uLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKi9cbiAgY3JlYXRlT2ZmZXIgKGJhbmR3aWR0aCA9IG51bGwsIG9mZmVyUHJvbWlzZSA9IG51bGwpIHtcbiAgICBkZWJ1ZyhOQU1FLCAnW2NyZWF0ZW9mZmVyXScpXG4gICAgY29uc3QgcCA9IG9mZmVyUHJvbWlzZSB8fCBuZXcgRGVmZXJyZWRQcm9taXNlKClcbiAgICB0aGlzLl9wZWVyQ29ubmVjdGlvbi5jcmVhdGVPZmZlcigpXG4gICAgICAudGhlbigoc2Vzc2lvbkRlc2NyaXB0aW9uKSA9PiB7XG4gICAgICAgIHRoaXMuc2V0TG9jYWxEZXNjcmlwdGlvbihzZXNzaW9uRGVzY3JpcHRpb24sIGJhbmR3aWR0aClcbiAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICBpZiAoYmFuZHdpZHRoKSB7XG4gICAgICAgICAgICAgIHNlc3Npb25EZXNjcmlwdGlvbi5zZHAgPSB3ZWJydGMudXBkYXRlQmFuZHdpZHRoKGJhbmR3aWR0aCwgc2Vzc2lvbkRlc2NyaXB0aW9uLnNkcClcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3Jlc3BvbmRlci5vblNEUFN1Y2Nlc3MoKVxuICAgICAgICAgICAgcC5yZXNvbHZlKHNlc3Npb25EZXNjcmlwdGlvbilcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICAgICAgICB0aGlzLl9yZXNwb25kZXIub25TRFBFcnJvcihlcnIpXG4gICAgICAgICAgICBwLnJlamVjdChlcnIpXG4gICAgICAgICAgfSlcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgZGVidWcoTkFNRSwgJ1tjcmVhdGVvZmZlcjplcnJvcl0nKVxuICAgICAgICBwLnJlamVjdChlcnIpXG4gICAgICB9KVxuICAgIHJldHVybiBwLmhhc093blByb3BlcnR5KCdwcm9taXNlJykgPyBwLnByb21pc2UgOiBwXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBzZXQgbG9jYWwgZGVzY3JpcHRpb24gb24gdGhlIFBlZXIgQ29ubmVjdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IHNlc3Npb25EZXNjcmlwdGlvblxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKi9cbiAgc2V0TG9jYWxEZXNjcmlwdGlvbiAoc2Vzc2lvbkRlc2NyaXB0aW9uKSB7XG4gICAgZGVidWcoTkFNRSwgJ1tzZXRsb2NhbGRlc2NyaXB0aW9uXScpXG4gICAgcmV0dXJuIHRoaXMuX3BlZXJDb25uZWN0aW9uLnNldExvY2FsRGVzY3JpcHRpb24oc2Vzc2lvbkRlc2NyaXB0aW9uKVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gc2V0IHJlbW90ZSBkZXNjcmlwdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IHNkcFxuICAgKiAgICAgICAgVGhlIFNlc3Npb24gRGVzY3JpcHRpb24gdG90IHNldCBvbiB0aGUgUGVlciBDb25uZWN0aW9uLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKi9cbiAgc2V0UmVtb3RlRGVzY3JpcHRpb24gKHNkcCkge1xuICAgIGRlYnVnKE5BTUUsICdbc2V0cmVtb3RlZGVzY3JpcHRpb25dJylcbiAgICByZXR1cm4gdGhpcy5fcGVlckNvbm5lY3Rpb24uc2V0UmVtb3RlRGVzY3JpcHRpb24obmV3IHdlYnJ0Yy5SVENTZXNzaW9uRGVzY3JpcHRpb24oc2RwKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIGFkZCBJQ0UgY2FuZGlkYXRlIHRvIFBlZXIgQ29ubmVjdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNhbmRpZGF0ZVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKi9cbiAgYWRkSWNlQ2FuZGlkYXRlIChjYW5kaWRhdGUpIHtcbiAgICBkZWJ1ZyhOQU1FLCAnW2FkZGNhbmRpZGF0ZV0nKVxuICAgIHJldHVybiB0aGlzLl9wZWVyQ29ubmVjdGlvbi5hZGRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlKVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gc2V0dXAgdGhlIHByb3hpZWQgUGVlciBDb25uZWN0aW9uIGluc3RhbmNlLlxuICAgKlxuICAgKiBAcGFyYW0ge0FycmF5fSBpY2VTZXJ2ZXJzXG4gICAqICAgICAgICBMaXN0IG9mIElDRSBzZXJ2ZXJzIHRvIHVzZSBpbiB0aGUgY29ubmVjdGlvbi5cbiAgICogQHBhcmFtIHtQcm9taXNlfSBzZXRVcFByb21pc2VcbiAgICogICAgICAgIFRoZSBgUHJvbWlzZWAgdG8gcmVzb2x2ZSBvciByZWplY3Qgb24gaW4gc3VjY2VzcyBpbiBzZXR0aW5nIHVwIHRoZSBQZWVyIENvbm5lY3Rpb24uXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBydGNwTXV4UG9saWN5XG4gICAqICAgICAgICBUaGUgdHlwZSBvZiBtdXggcG9saWN5IHRvIHVzZS5cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICovXG4gIHNldFVwIChpY2VTZXJ2ZXJzLCBzZXRVcFByb21pc2UgPSB1bmRlZmluZWQsIHJ0Y3BNdXhQb2xpY3kgPSB1bmRlZmluZWQpIHtcbiAgICB0aGlzLnRlYXJEb3duKClcbiAgICBjb25zdCBwID0gc2V0VXBQcm9taXNlIHx8IG5ldyBEZWZlcnJlZFByb21pc2UoKVxuICAgIHRyeSB7XG4gICAgICBsZXQgcGVlckNvbmZpZyA9IHtcbiAgICAgICAgaWNlU2VydmVyczogaWNlU2VydmVycyxcbiAgICAgICAgaWNlQ2FuZGlkYXRlUG9vbFNpemU6IDIsXG4gICAgICAgIGJ1bmRsZVBvbGljeTogJ21heC1idW5kbGUnXG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIHJ0Y3BNdXhQb2xpY3kgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHBlZXJDb25maWcucnRjcE11eFBvbGljeSA9IHJ0Y3BNdXhQb2xpY3lcbiAgICAgIH1cbiAgICAgIGRlYnVnKE5BTUUsIGBbcGVlcmNvbm5lY3Rpb246c2V0dXBdOiAke0pTT04uc3RyaW5naWZ5KHBlZXJDb25maWcsIG51bGwsIDIpfWApXG4gICAgICBsZXQgcGVlciA9IG5ldyB3ZWJydGMuUlRDUGVlckNvbm5lY3Rpb24ocGVlckNvbmZpZyxcbiAgICAgICAge1xuICAgICAgICAgIG9wdGlvbmFsOiBbXG4gICAgICAgICAgICB7UnRwRGF0YUNoYW5uZWxzOiBmYWxzZX0sXG4gICAgICAgICAgICB7Z29vZ0NwdU92ZXJ1c2VEZXRlY3Rpb246IHRydWV9XG4gICAgICAgICAgXVxuICAgICAgICB9KVxuICAgICAgdGhpcy5fYWRkQ29ubmVjdGlvbkhhbmRsZXJzKHBlZXIpXG4gICAgICB0aGlzLl9wZWVyQ29ubmVjdGlvbiA9IHBlZXJcbiAgICAgIHAucmVzb2x2ZShwZWVyKVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHdhcm4oTkFNRSwgYENvdWxkIG5vdCBlc3RhYmxpc2ggYSBQZWVyQ29ubmVjdGlvbi4gJHtlLm1lc3NhZ2V9YClcbiAgICAgIHAucmVqZWN0KGUubWVzc2FnZSlcbiAgICB9XG4gICAgcmV0dXJuIHAuaGFzT3duUHJvcGVydHkoJ3Byb21pc2UnKSA/IHAucHJvbWlzZSA6IHBcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIHRlYXIgZG93biBwcm94aWVkIFBlZXIgQ29ubmVjdGlvbiBpbnN0YW5jZS5cbiAgICovXG4gIHRlYXJEb3duICgpIHtcbiAgICBpZiAodGhpcy5fcGVlckNvbm5lY3Rpb24pIHtcbiAgICAgIGRlYnVnKE5BTUUsICdbdGVhcmRvd25dJylcbiAgICAgIHRoaXMuX3JlbW92ZUNvbm5lY3Rpb25IYW5kbGVycyh0aGlzLl9wZWVyQ29ubmVjdGlvbilcbiAgICAgIHRyeSB7XG4gICAgICAgIHRoaXMuX3BlZXJDb25uZWN0aW9uLmNsb3NlKClcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgd2FybihOQU1FLCBgW3BlZXJjb25uZWN0aW9uLmNsb3NlXSBlcnJvcjogJHtlLm1lc3NhZ2V9YClcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIHRoaXMuX3BlZXJDb25uZWN0aW9uID0gdW5kZWZpbmVkXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFjY2Vzc29yIGZvciB0aGUgcHJveGllZCBSVENQZWVyQ29ubmVjdGlvbiBpbnN0YW5jZS5cbiAgICpcbiAgICogQHJldHVybiB7UlRDUGVlckNvbm5lY3Rpb259XG4gICAqL1xuICBnZXQgY29ubmVjdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3BlZXJDb25uZWN0aW9uXG4gIH1cblxufVxuXG5leHBvcnQgZGVmYXVsdCBQdWJsaXNoZXJQZWVySGVscGVyXG5cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9qcy9oZWxwZXIvd2VicnRjLWhlbHBlci1wdWIuanMiLCIndXNlIHN0cmljdCdcblxuaW1wb3J0ICogYXMgd2VicnRjIGZyb20gJy4uL2FkYXB0ZXIvd2VicnRjJ1xuaW1wb3J0IHsgRGVmZXJyZWRQcm9taXNlIH0gZnJvbSAnLi4vdXRpbC9wcm9taXNlJ1xuaW1wb3J0IHsgZGVidWcsIHdhcm4sIGVycm9yIH0gZnJvbSAnLi4vbG9nJ1xuXG5jb25zdCBOQU1FID0gJ1I1UHJvU3Vic2NyaXB0aW9uUGVlcidcblxuLyoqXG4gKiBVdGlsaXR5IHRvIGNoZWNrIGlmIGNhbmRpZGF0ZSBpcyBlbXB0eSwgYW5kIGNvbnNpZGVyZWQgdGhlIGVuZCBvZiB0aGUgdHJpY2tsZSBuZWdvdGlhdGlvbiBmb3IgYSBzdWJzY3JpYmVyLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBjYW5kaWRhdGVcbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5jb25zdCBpc0VtcHR5Q2FuZGlkYXRlID0gKGNhbmRpZGF0ZSkgPT4ge1xuICByZXR1cm4gdHlwZW9mIGNhbmRpZGF0ZSA9PT0gJ3VuZGVmaW5lZCcgfHxcbiAgICAodHlwZW9mIGNhbmRpZGF0ZSA9PT0gJ3N0cmluZycgJiYgY2FuZGlkYXRlLmxlbmd0aCA9PT0gMClcbn1cblxuLyoqXG4gKiBQcm94eSB0byBQZWVyIENvbm5lY3Rpb24gZm9yIFN1YnNjcmliZXJzLlxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmNsYXNzIFN1YnNjcmlwdGlvblBlZXJIZWxwZXIge1xuXG4gIGNvbnN0cnVjdG9yIChyZXNwb25kZXIpIHtcbiAgICB0aGlzLl9yZXNwb25kZXIgPSByZXNwb25kZXJcbiAgICB0aGlzLl9wZWVyQ29ubmVjdGlvbiA9IHVuZGVmaW5lZFxuICAgIHRoaXMuX3BlbmRpbmdNZWRpYVN0cmVhbSA9IHVuZGVmaW5lZFxuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgaGFuZGxlcnMgYXNzaWduZWQgdG8gdGhlIHBlZXIgY29ubmVjdGlvbiBpbnN0YW5jZS5cbiAgICpcbiAgICogQHBhcmFtIHtSVENQZWVyQ29ubmVjdGlvbn0gY29ubmVjdGlvblxuICAgKi9cbiAgX3JlbW92ZUNvbm5lY3Rpb25IYW5kbGVycyAoY29ubmVjdGlvbikge1xuICAgIGNvbm5lY3Rpb24ub25jb25uZWN0aW9uc3RhdGVjaGFuZ2UgPSB1bmRlZmluZWRcbiAgICBjb25uZWN0aW9uLm9uaWNlY29ubmVjdGlvbnN0YXRlY2hhbmdlID0gdW5kZWZpbmVkXG4gICAgY29ubmVjdGlvbi5vbmljZWNhbmRpZGF0ZSA9IHVuZGVmaW5lZFxuLy8gICAgY29ubmVjdGlvbi5vbmFkZHN0cmVhbSA9IHVuZGVmaW5lZFxuICAgIGNvbm5lY3Rpb24ub250cmFjayA9IHVuZGVmaW5lZFxuICB9XG5cbiAgLyoqXG4gICAqIEFzc2lnbnMgaGFuZGxlcnMgdG8gZXZlbnRzIG9uIHRoZSBwZWVyIGNvbm5lY3Rpb24gaW5zdGFuY2UuXG4gICAqXG4gICAqIEBwYXJhbSB7UlRDUGVlckNvbm5lY3Rpb259IGNvbm5lY3Rpb25cbiAgICogQHBhcmFtIHtQcm9taXNlfSBwcm9taXNlXG4gICAqICAgICAgICBUaGUgYFByb21pc2VgIHRvIHJlc29sdmUgb3IgcmVqZWN0IG9uIHN1Y2Nlc3Mgb2YgY29ubmVjdGlvbi5cbiAgICovXG4gIF9hZGRDb25uZWN0aW9uSGFuZGxlcnMgKGNvbm5lY3Rpb24sIHByb21pc2UpIHtcblxuICAgIGxldCByZWNvbm5lY3RUaW1lb3V0XG4gICAgY29uc3QgdGltZW91dExpbWl0ID0gNTAwMFxuXG4gICAgY29ubmVjdGlvbi5vbmNvbm5lY3Rpb25zdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgIGlmIChjb25uZWN0aW9uLmNvbm5lY3Rpb25TdGF0ZSA9PT0gJ2Nvbm5lY3RlZCcpIHtcbiAgICAgICAgZGVidWcoTkFNRSwgJ1twZWVyY29ubmVjdGlvbjpvcGVuXScpXG4gICAgICAgIGlmIChwcm9taXNlKSB7XG4gICAgICAgICAgcHJvbWlzZS5yZXNvbHZlKHRoaXMpXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoY29ubmVjdGlvbi5jb25uZWN0aW9uU3RhdGUgPT09ICdmYWlsZWQnIHx8XG4gICAgICAgIGNvbm5lY3Rpb24uY29ubmVjdGlvblN0YXRlID09PSAnZGlzY29ubmVjdGVkJykge1xuICAgICAgICB3YXJuKE5BTUUsICdbcGVlcmNvbm5lY3Rpb246ZXJyb3JdJylcbiAgICAgICAgaWYgKHByb21pc2UpIHtcbiAgICAgICAgICBwcm9taXNlLnJlamVjdCgpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25uZWN0aW9uLm9uaWNlY2FuZGlkYXRlID0gKGV2ZW50KSA9PiB7XG4gICAgICBkZWJ1ZyhOQU1FLCBgW3BlZXIub25pY2VjYW5kaWRhdGVdIC0gUGVlciBDYW5kaWRhdGU6ICR7ZXZlbnQuY2FuZGlkYXRlfWApXG4gICAgICBpZiAoZXZlbnQuY2FuZGlkYXRlKSB7XG4gICAgICAgIHRoaXMuX3Jlc3BvbmRlci5vbkljZUNhbmRpZGF0ZShldmVudC5jYW5kaWRhdGUpXG4gICAgICB9IGVsc2UgaWYgKGV2ZW50LmNhbmRpZGF0ZSA9PT0gbnVsbCkge1xuICAgICAgICAvLyBudWxsIG1lYW5zIHRoZXkgaGF2ZSBmaW5pc2hlZCBzZW5kaW5nIGNhbmRpZGF0ZXMgYmFjayBhbmQgZm9ydGg/XG4gICAgICAgIHRoaXMuX3Jlc3BvbmRlci5vbkljZUNhbmRpZGF0ZVRyaWNrbGVFbmQodGhpcy5fcGVuZGluZ01lZGlhU3RyZWFtKVxuICAgICAgICB0aGlzLl9wZW5kaW5nTWVkaWFTdHJlYW0gPSB1bmRlZmluZWRcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgIGNvbm5lY3Rpb24ub25hZGRzdHJlYW0gPSAoZXZlbnQpID0+IHtcbiAgICAgIGRlYnVnKE5BTUUsIGAob25hZGRzdHJlYW0pIFBlZXIgQWRkIFN0cmVhbTogJHtldmVudC5zdHJlYW19YClcbiAgICAgIGlmIChldmVudC5zdHJlYW0gJiYgdGhpcy5fcGVuZGluZ01lZGlhU3RyZWFtID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5fcGVuZGluZ01lZGlhU3RyZWFtID0gZXZlbnQuc3RyZWFtXG4gICAgICAgIHRoaXMuX3Jlc3BvbmRlci5vbkFuc3dlck1lZGlhU3RyZWFtKGV2ZW50LnN0cmVhbSlcbiAgICAgIH1cbiAgICB9XG4gICAgKi9cblxuICAgIC8vIFBpY2tlZCB1cCBieSBGaXJlZm94LCBhbGwgb3RoZXJzIHVzZSBgb25hZGRzdHJlYW1gLCBidXQgYWRhcHRlci5qcyB3aWxsIGNhbGwgYm90aCwgc28gd2UgbGltaXQuXG4gICAgY29ubmVjdGlvbi5vbnRyYWNrID0gKGV2ZW50KSA9PiB7XG4gICAgICBkZWJ1ZyhOQU1FLCBgKG9udHJhY2spIFBlZXIgQWRkIFN0cmVhbTogJHtldmVudC5zdHJlYW1zfWApXG4gICAgICBpZiAoZXZlbnQuc3RyZWFtcyAmJiBldmVudC5zdHJlYW1zLmxlbmd0aCA+IDAgJiYgdGhpcy5fcGVuZGluZ01lZGlhU3RyZWFtID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5fcGVuZGluZ01lZGlhU3RyZWFtID0gZXZlbnQuc3RyZWFtc1swXVxuICAgICAgICB0aGlzLl9yZXNwb25kZXIub25BbnN3ZXJNZWRpYVN0cmVhbShldmVudC5zdHJlYW1zWzBdKVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbm5lY3Rpb24ub25pY2Vjb25uZWN0aW9uc3RhdGVjaGFuZ2UgPSAoZXZlbnQpID0+IHtcbiAgICAgIGNvbnN0IHN0YXRlID0gY29ubmVjdGlvbi5pY2VDb25uZWN0aW9uU3RhdGVcbiAgICAgIGRlYnVnKE5BTUUsIGBbcGVlci5vbmljZWNvbm5lY3Rpb25zdGF0ZWNoYW5nZV0gLSBTdGF0ZTogJHtzdGF0ZX1gKVxuICAgICAgaWYgKHN0YXRlID09PSAnZmFpbGVkJykge1xuICAgICAgICBpZiAocmVjb25uZWN0VGltZW91dCkge1xuICAgICAgICAgIGNsZWFyVGltZW91dChyZWNvbm5lY3RUaW1lb3V0KVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3Jlc3BvbmRlci5vblBlZXJDb25uZWN0aW9uQ2xvc2UoZXZlbnQpXG4gICAgICB9XG4gICAgICBlbHNlIGlmIChzdGF0ZSA9PT0gJ2Rpc2Nvbm5lY3RlZCcpIHtcbiAgICAgICAgLy8gbWF5IHJlY2VpdmUgYSBkaXNjb25uZWN0IHRlbXBvcmFyaWx5IHRoYXQgd2lsbCB0aGVuIHJldHVybiB0byBhIGNvbm5lY3Rpb24uXG4gICAgICAgIHJlY29ubmVjdFRpbWVvdXQgPSBzZXRUaW1lb3V0KCAoKSA9PiB7XG4gICAgICAgICAgZGVidWcoTkFNRSwgYFtwZWVyLm9uaWNlY29ubmVjdGlvbnN0YXRlY2hhbmdlXSAtIFJlY29ubmVjdCB0aW1lb3V0IHJlYWNoZWQuIENsb3NpbmcgUGVlckNvbm5lY3Rpb24uYClcbiAgICAgICAgICBjbGVhclRpbWVvdXQocmVjb25uZWN0VGltZW91dClcbiAgICAgICAgICB0aGlzLl9yZXNwb25kZXIub25QZWVyQ29ubmVjdGlvbkNsb3NlKGV2ZW50KVxuICAgICAgICB9LCB0aW1lb3V0TGltaXQpXG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgaWYgKHJlY29ubmVjdFRpbWVvdXQpIHtcbiAgICAgICAgICBkZWJ1ZyhOQU1FLCBgW3BlZXIub25pY2Vjb25uZWN0aW9uc3RhdGVjaGFuZ2VdIC0gQ2xlYXJpbmcgdGltZW91dCBmb3IgcmVjb25uZWN0LmApXG4gICAgICAgICAgY2xlYXJUaW1lb3V0KHJlY29ubmVjdFRpbWVvdXQpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25uZWN0aW9uLm9uaWNlZ2F0aGVyaW5nc3RhdGVjaGFuZ2UgPSAoKSA9PiB7XG4gICAgICBjb25zdCBzdGF0ZSA9IGNvbm5lY3Rpb24uaWNlR2F0aGVyaW5nU3RhdGVcbiAgICAgIGRlYnVnKE5BTUUsIGBbcGVlci5vbmljZWdhdGhlcmluZ3N0YXRlY2hhbmdlXSAtIFN0YXRlOiAke3N0YXRlfWApXG4gICAgICBpZiAoc3RhdGUgPT09ICdjb21wbGV0ZScpIHtcbiAgICAgICAgdGhpcy5fcmVzcG9uZGVyLm9uUGVlckdhdGhlcmluZ0NvbXBsZXRlKClcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25uZWN0aW9uLm9ucmVtb3Zlc3RyZWFtID0gKCkgPT4ge1xuICAgICAgZGVidWcoTkFNRSwgYFtwZWVyLm9ucmVtb3Zlc3RyZWFtXWApXG4gICAgfVxuXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBjcmVhdGUgYW5zd2VyIG9uIFBlZXIgQ29ubmVjdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IHNkcFxuICAgKiAgICAgICAgVGhlIFNlc3Npb24gRGVzY3JpcHRpb24gdG8gc2V0IGFzIHJlbW90ZSBkZXNjcmlwdGlvbi5cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICovXG4gIGNyZWF0ZUFuc3dlciAoc2RwKSB7XG4gICAgZGVidWcoTkFNRSwgJ1tjcmVhdGVhbnN3ZXJdJylcbiAgICBjb25zdCBkZWZlcnJlZCA9IG5ldyBEZWZlcnJlZFByb21pc2UoKVxuXG4gICAgdGhpcy5fcGVlckNvbm5lY3Rpb24uc2V0UmVtb3RlRGVzY3JpcHRpb24oc2RwKVxuICAgICAgLnRoZW4odGhpcy5fcmVzcG9uZGVyLm9uU0RQU3VjY2VzcylcbiAgICAgIC5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICAgIHRoaXMuX3Jlc3BvbmRlci5vblNEUEVycm9yKGVycilcbiAgICAgIH0pXG5cbiAgICB0aGlzLl9wZWVyQ29ubmVjdGlvbi5jcmVhdGVBbnN3ZXIoKVxuICAgICAgLnRoZW4oc2Vzc2lvbkRlc2NyaXB0aW9uID0+IHtcbiAgICAgICAgdGhpcy5fcGVlckNvbm5lY3Rpb24uc2V0TG9jYWxEZXNjcmlwdGlvbihzZXNzaW9uRGVzY3JpcHRpb24pXG4gICAgICAgICAgLnRoZW4odGhpcy5fcmVzcG9uZGVyLm9uU0RQU3VjY2VzcylcbiAgICAgICAgICAuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAgICAgdGhpcy5fcmVzcG9uZGVyLm9uU0RQRXJyb3IoZXJyKVxuICAgICAgICAgIH0pXG4gICAgICAgIGRlZmVycmVkLnJlc29sdmUoc2Vzc2lvbkRlc2NyaXB0aW9uKVxuICAgICAgfSlcbiAgICAgIC5jYXRjaChkZWZlcnJlZC5yZWplY3QpXG5cbiAgICByZXR1cm4gZGVmZXJyZWQucHJvbWlzZVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gYWRkIElDRSBjYW5kaWRhdGUgdG8gUGVlciBDb25uZWN0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY2FuZGlkYXRlXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqL1xuICBhZGRJY2VDYW5kaWRhdGUgKGNhbmRpZGF0ZSkge1xuICAgIGRlYnVnKE5BTUUsICdjaGVja2luZyBpZiBlbXB0eS4uLicpXG4gICAgaWYgKGlzRW1wdHlDYW5kaWRhdGUoY2FuZGlkYXRlKSkge1xuICAgICAgZGVidWcoTkFNRSwgJ1thZGRpY2VjYW5kaWRhdGVdOjogZW1wdHknKVxuICAgIH0gZWxzZSBpZiAoY2FuZGlkYXRlICE9PSBudWxsKSB7XG4gICAgICBkZWJ1ZyhOQU1FLCAnW2FkZGljZWNhbmRpZGF0ZV0gOjogbm9uLWVtcHR5JylcbiAgICAgIGxldCBpY2VDYW5kaWRhdGUgPSBuZXcgd2VicnRjLlJUQ0ljZUNhbmRpZGF0ZSh7XG4gICAgICAgIHNkcE1MaW5lSW5kZXg6IGNhbmRpZGF0ZS5zZHBNTGluZUluZGV4LFxuICAgICAgICBjYW5kaWRhdGU6IGNhbmRpZGF0ZS5jYW5kaWRhdGVcbiAgICAgIH0pXG4gICAgICB0aGlzLl9wZWVyQ29ubmVjdGlvbi5hZGRJY2VDYW5kaWRhdGUoaWNlQ2FuZGlkYXRlKVxuICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgLy8gbmFkYVxuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgICBlcnJvcihOQU1FLCBgRXJyb3IgaW4gYWRkIG9mIElDRSBDYW5kaWRpYXRlICsgJHtlcnJ9YClcbiAgICAgICAgfSlcbiAgICB9IGVsc2Uge1xuICAgICAgZGVidWcoTkFNRSwgJ1thZGRpY2VjYW5kaWRhdGVdIDo6IG51bGwnKVxuICAgICAgdGhpcy5fcGVlckNvbm5lY3Rpb24uYWRkSWNlQ2FuZGlkYXRlKGNhbmRpZGF0ZSlcbiAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIC8vIG5hZGFcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgICAgZXJyb3IoTkFNRSwgYEVycm9yIGluIGFkZCBvZiBJQ0UgQ2FuZGlkaWF0ZSArICR7ZXJyfWApXG4gICAgICAgIH0pXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gc2V0dXAgdGhlIHByb3hpZWQgUGVlciBDb25uZWN0aW9uIGluc3RhbmNlLlxuICAgKlxuICAgKiBAcGFyYW0ge0FycmF5fSBpY2VTZXJ2ZXJzXG4gICAqICAgICAgICBMaXN0IG9mIElDRSBzZXJ2ZXJzIHRvIHVzZSBpbiB0aGUgY29ubmVjdGlvbi5cbiAgICogQHBhcmFtIHtQcm9taXNlfSBzZXRVcFByb21pc2VcbiAgICogICAgICAgIFRoZSBgUHJvbWlzZWAgdG8gcmVzb2x2ZSBvciByZWplY3Qgb24gaW4gc3VjY2VzcyBpbiBzZXR0aW5nIHVwIHRoZSBQZWVyIENvbm5lY3Rpb24uXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBydGNwTXV4UG9saWN5XG4gICAqICAgICAgICBUaGUgdHlwZSBvZiBtdXggcG9saWN5IHRvIHVzZS5cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICovXG4gIHNldFVwIChpY2VTZXJ2ZXJzLCBzZXRVcFByb21pc2UgPSB1bmRlZmluZWQsIHJ0Y3BNdXhQb2xpY3kgPSB1bmRlZmluZWQpIHtcbiAgICB0aGlzLnRlYXJEb3duKClcbiAgICBjb25zdCBwID0gc2V0VXBQcm9taXNlIHx8IG5ldyBEZWZlcnJlZFByb21pc2UoKVxuICAgIHRyeSB7XG4gICAgICBsZXQgcGVlckNvbmZpZyA9IHtcbiAgICAgICAgaWNlU2VydmVyczogaWNlU2VydmVycyxcbiAgICAgICAgaWNlQ2FuZGlkYXRlUG9vbFNpemU6IDIsXG4gICAgICAgIGJ1bmRsZVBvbGljeTogXCJtYXgtYnVuZGxlXCJcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgcnRjcE11eFBvbGljeSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcGVlckNvbmZpZy5ydGNwTXV4UG9saWN5ID0gcnRjcE11eFBvbGljeVxuICAgICAgfVxuICAgICAgZGVidWcoTkFNRSwgYFtwZWVyY29ubmVjdGlvbjpzZXR1cF06ICR7SlNPTi5zdHJpbmdpZnkocGVlckNvbmZpZywgbnVsbCwgMil9YClcbiAgICAgIGxldCBwZWVyID0gbmV3IHdlYnJ0Yy5SVENQZWVyQ29ubmVjdGlvbihwZWVyQ29uZmlnLFxuICAgICAgICB7XG4gICAgICAgICAgb3B0aW9uYWw6IFtcbiAgICAgICAgICAgIHtSdHBEYXRhQ2hhbm5lbHM6IGZhbHNlfSxcbiAgICAgICAgICAgIHtnb29nQ3B1T3ZlcnVzZURldGVjdGlvbjogdHJ1ZX1cbiAgICAgICAgICBdXG4gICAgICAgIH0pXG4gICAgICB0aGlzLl9wZWVyQ29ubmVjdGlvbiA9IHBlZXJcbiAgICAgIHRoaXMuX2FkZENvbm5lY3Rpb25IYW5kbGVycyhwZWVyKVxuICAgICAgcC5yZXNvbHZlKClcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB3YXJuKE5BTUUsIGBDb3VsZCBub3QgY3JlYXRlIGEgUlRDUGVlckNvbm5lY3Rpb24uIEVycm9yOiAke2UubWVzc2FnZX1gKVxuICAgICAgcC5yZWplY3QoZS5tZXNzYWdlKVxuICAgIH1cbiAgICByZXR1cm4gcC5oYXNPd25Qcm9wZXJ0eSgncHJvbWlzZScpID8gcC5wcm9taXNlIDogcFxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gdGVhciBkb3duIHByb3hpZWQgUGVlciBDb25uZWN0aW9uIGluc3RhbmNlLlxuICAgKi9cbiAgdGVhckRvd24gKCkge1xuICAgIGlmICh0aGlzLl9wZWVyQ29ubmVjdGlvbikge1xuICAgICAgZGVidWcoTkFNRSwgJ1t0ZWFyZG93bl0nKVxuICAgICAgdGhpcy5fcmVtb3ZlQ29ubmVjdGlvbkhhbmRsZXJzKHRoaXMuX3BlZXJDb25uZWN0aW9uKVxuICAgICAgdHJ5IHtcbiAgICAgICAgdGhpcy5fcGVlckNvbm5lY3Rpb24uY2xvc2UoKVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB3YXJuKE5BTUUsIGBbcGVlcmNvbm5lY3Rpb24uY2xvc2VdIGVycm9yOiAke2UubWVzc2FnZX1gKVxuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLl9wZW5kaW5nTWVkaWFTdHJlYW0gPSB1bmRlZmluZWRcbiAgICB0aGlzLl9wZWVyQ29ubmVjdGlvbiA9IHVuZGVmaW5lZFxuICB9XG5cbiAgLyoqXG4gICAqIEFjY2Vzc29yIGZvciB0aGUgcHJveGllZCBSVENQZWVyQ29ubmVjdGlvbiBpbnN0YW5jZS5cbiAgICpcbiAgICogQHJldHVybiB7UlRDUGVlckNvbm5lY3Rpb259XG4gICAqL1xuICBnZXQgY29ubmVjdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3BlZXJDb25uZWN0aW9uXG4gIH1cblxufVxuXG5leHBvcnQgZGVmYXVsdCBTdWJzY3JpcHRpb25QZWVySGVscGVyXG5cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9qcy9oZWxwZXIvd2VicnRjLWhlbHBlci1zdWIuanMiLCIndXNlIHN0cmljdCdcblxuaW1wb3J0IHsgbmFtZUZyb21MZXZlbCB9IGZyb20gJ2Jyb3dzZXItYnVueWFuJ1xuXG4vKipcbiAqIEN1c3RvbSBsb2dnZXIgZm9yIGJ1bnlvbi5cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5leHBvcnQgY2xhc3MgUmF3U3RyZWFtIHtcbiAgd3JpdGUgKHJlYykge1xuICAgIGNvbnNvbGUubG9nKCclcyAtIFslc10gJXM6ICVzJywgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1jb25zb2xlXG4gICAgICByZWMudGltZS50b0lTT1N0cmluZygpLFxuICAgICAgcmVjLm5hbWUsXG4gICAgICBuYW1lRnJvbUxldmVsW3JlYy5sZXZlbF0sXG4gICAgICByZWMubXNnXG4gICAgKVxuICB9XG59XG5cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9qcy9sb2cvYnVueWFuLXdyaXRlci5qcyIsIid1c2Ugc3RyaWN0J1xuXG5pbXBvcnQgSW1wbEZhY3RvcnlPcmRlciBmcm9tICcuLi91dGlsL2ltcGwtZmFjdG9yeS1vcmRlcidcbmltcG9ydCBFdmVudEVtaXR0ZXIgZnJvbSAnLi4vY29yZS9ldmVudC1lbWl0dGVyJ1xuaW1wb3J0IFJUTVBQdWJsaXNoZXIgZnJvbSAnLi9yZWQ1cHJvLXJ0bXAnXG5pbXBvcnQgUlRDUHVibGlzaGVyIGZyb20gJy4vcmVkNXByby1ydGMnXG5cbmltcG9ydCB7IERlZmVycmVkUHJvbWlzZSB9IGZyb20gJy4uL3V0aWwvcHJvbWlzZSdcbmltcG9ydCB7IFB1Ymxpc2hUeXBlcyB9IGZyb20gJy4uL2VudW0vcHVibGlzaCdcbmltcG9ydCB7IGRlYnVnLCB3YXJuIH0gZnJvbSAnLi4vbG9nJ1xuXG5jb25zdCBOQU1FID0gJ1JlZDVQcm9QdWJsaXNoZXInXG5jb25zdCBwdWJsaXNoRmFjdG9yeSA9IG5ldyBJbXBsRmFjdG9yeU9yZGVyKClcbmNvbnN0IHB1Ymxpc2hlckltcGwgPSAoZnVuY3Rpb24gKCkge1xuICBsZXQgbWFwID0gbmV3IE1hcCgpXG4gIG1hcC5zZXQoUHVibGlzaFR5cGVzLlJUQywgUlRDUHVibGlzaGVyKVxuICBtYXAuc2V0KFB1Ymxpc2hUeXBlcy5SVE1QLCBSVE1QUHVibGlzaGVyKVxuICByZXR1cm4gbWFwXG59KCkpXG5cbi8qKlxuICogTWFpbiBlbnRyeSBmb3IgZmFpbG92ZXIgc3VwcG9ydCBvZiBhbGwgcHVibGlzaGVyIGltcGxlbWVudGF0aW9ucy5cbiAqXG4gKiBAZXh0ZW5kcyBFdmVudEVtaXR0ZXJcbiAqL1xuY2xhc3MgUmVkNVByb1B1Ymxpc2hlciBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG5cbiAgY29uc3RydWN0b3IgKCkge1xuICAgIHN1cGVyKClcbiAgICB0aGlzLl9vcHRpb25zID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fb3JkZXIgPSBbXG4gICAgICBQdWJsaXNoVHlwZXMuUlRDLFxuICAgICAgUHVibGlzaFR5cGVzLlJUTVBcbiAgICBdXG4gIH1cblxuICAvKipcbiAgICogVXRpbGl6ZXMgRmFpbG92ZXIgUHVibGlzaGVyIEZhY3RvcnkgdG8gYXR0ZW1wdCBpbiBkZXRlcm1pbmluZyBicm93c2VyIHN1cHBvcnQgZm9yIFB1Ymxpc2hlciBmcm9tIGRlZmluZWQgb3JkZXIuXG4gICAqXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfZ2V0UHVibGlzaGVyRnJvbU9yZGVyIChvcmRlciwgb3B0aW9ucykge1xuICAgIHJldHVybiBwdWJsaXNoRmFjdG9yeS5jcmVhdGUob3JkZXIsIHB1Ymxpc2hlckltcGwsIG9wdGlvbnMsICdpbml0JylcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBzcGVjaWZpZWQgb3JkZXIgZm9yIGF1dG8tZmFpbG92ZXIuXG4gICAqXG4gICAqICBAcmV0dXJuIHtBcnJheX1cbiAgICogICAgICAgICAgRGVmYXVsdDogYFsncnRjJywgJ3J0bXAnXWAuXG4gICAqL1xuICBnZXRQdWJsaXNoT3JkZXIgKCkge1xuICAgIHJldHVybiB0aGlzLl9vcmRlclxuICB9XG5cbiAgLyoqXG4gICAqIERlZmluZXMgdGhlIGRlc2lyZWQgYXV0by1mYWlsb3ZlciBvcmRlci5cbiAgICpcbiAgICogIEBwYXJhbSB7QXJyYXl9IG9yZGVyXG4gICAqICAgICAgICAgIFRoZSBkZXNpcmVkIG9yZGVyLiBlLmcsIGBbJ3J0YycsICdydG1wJ11gLlxuICAgKlxuICAgKiAgQHJldHVybiB7UmVkNVByb1B1Ymxpc2hlcn1cbiAgICogICAgICAgICAgVGhpcyBpbnN0YW5jZS5cbiAgICovXG4gIHNldFB1Ymxpc2hPcmRlciAob3JkZXIpIHtcbiAgICAvLyBBbGxvdyBmb3Igc3RyaW5nIHZhbHVlIHRvIGRlZmluZSBzaW5nbGUgaXRlbSBpbiBvcmRlci5cbiAgICBvcmRlciA9IHR5cGVvZiBvcmRlciA9PT0gJ3N0cmluZycgPyBbb3JkZXJdIDogb3JkZXJcblxuICAgIC8vIEZpbHRlciBvdXQgdmFsdWVzIG5vdCBhdmFpbGFibGUgaW4gZW51bWVyYXRpb24gb2YgcGxheWJhY2sgdHlwZXMuXG4gICAgY29uc3QgdCA9IG9yZGVyLmZpbHRlcihlbnRyeSA9PiB7XG4gICAgICBsZXQga2V5XG4gICAgICBmb3IgKGtleSBpbiBQdWJsaXNoVHlwZXMpIHtcbiAgICAgICAgaWYgKFB1Ymxpc2hUeXBlc1trZXldLnRvTG93ZXJDYXNlKCkgPT09IGVudHJ5LnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gZmFsc2VcbiAgICB9KS5tYXAoZW50cnkgPT4gZW50cnkudG9Mb3dlckNhc2UoKSlcblxuICAgIC8vIERlZmluZSBuZXcgb3JkZXIuXG4gICAgdGhpcy5fb3JkZXIgPSBbLi4ubmV3IFNldCh0KV1cbiAgICBkZWJ1ZyhOQU1FLCBgW29yZGVydXBkYXRlXTogJHt0aGlzLl9vcmRlcn1gKVxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBpbml0aWFsaXplIGFuZCBkZXRlcm1pbmUgdGhlIHByb3BlciBQdWJsaXNoZXIgaW1wbGVtZW50YXRpb24gYmFzZWQgb24gY29uZmlndXJhdGlvbi5cbiAgICogVGhlIHJldHVybmVkIGBQcm9taXNlYCB3aWxsIGVpdGhlciByZXNvbHZlIHdpdGggdGhlIGRldGVybWluZWQgUHVibGlzaGVyIGluc3RhbmNlIG9yIHJlamVjdCB3aXRoIGFuIGVycm9yIFN0cmluZyBpbiBmYWlsdXJlIHRvIGRldGVybWluZSBQdWJsaXNoZXIgdHlwZS5cbiAgICpcbiAgICogIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqICAgICAgICAgIFRoZSBpbml0aWFsaXphdGlvbiBjb25maWd1cmF0aW9uIG1hcCBmb3IgZWFjaCBkZXNpcmVkIGZhaWxvdmVyIHRlY2guXG4gICAqICBAcmV0dXJuIHtQcm9taXNlfVxuICAgKi9cbiAgaW5pdCAob3B0aW9ucykge1xuICAgIGNvbnN0IGRlZmVycmVkID0gbmV3IERlZmVycmVkUHJvbWlzZSgpXG4gICAgZGVidWcoTkFNRSwgJ1twdWJsaXNoXScpXG4gICAgdGhpcy5fb3B0aW9ucyA9IG9wdGlvbnNcbiAgICB0aGlzLl9nZXRQdWJsaXNoZXJGcm9tT3JkZXIodGhpcy5fb3JkZXIsIHRoaXMuX29wdGlvbnMpXG4gICAgICAudGhlbihwdWJsaXNoZXIgPT4ge1xuICAgICAgICBkZWZlcnJlZC5yZXNvbHZlKHB1Ymxpc2hlcilcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgd2FybihOQU1FLCBgW3B1Ymxpc2hlcnJvcl06IENvdWxkIG5vdCBpbXBsZW1lbnQgYSBwdWJsaXNoZXI6ICR7ZXJyfWApXG4gICAgICAgIGRlZmVycmVkLnJlamVjdChlcnIpXG4gICAgICB9KVxuICAgIHJldHVybiBkZWZlcnJlZC5wcm9taXNlXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGVudW1lcmF0ZWQgdmFsdWUgUHVibGlzaGVyIHR5cGVzIHVzZWQgaW4gZmFpbG92ZXIgb3JkZXIuXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICBnZXQgcHVibGlzaFR5cGVzICgpIHtcbiAgICByZXR1cm4gUHVibGlzaFR5cGVzXG4gIH1cblxufVxuXG5leHBvcnQgeyBSZWQ1UHJvUHVibGlzaGVyLCBSVE1QUHVibGlzaGVyLCBSVENQdWJsaXNoZXIgfVxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2pzL3B1Ymxpc2hlci9pbmRleC5qcyIsIid1c2Ugc3RyaWN0J1xuXG5pbXBvcnQgKiBhcyBlbWJlZCBmcm9tICcuLi9lbnYvZW1iZWQnXG5pbXBvcnQgZW52aXJvbm1lbnQgZnJvbSAnLi4vZW52L2Jyb3dzZXInXG5pbXBvcnQgUlRNUFNoYXJlZE9iamVjdEhhbmRsZXIgZnJvbSAnLi4vaGVscGVyL3NoYXJlZG9iamVjdC1oZWxwZXItcnRtcCdcbmltcG9ydCB7IHRvSW50IH0gZnJvbSAnLi4vdXRpbCdcbmltcG9ydCB7IGRlZXBDb3B5IH0gZnJvbSAnLi4vdXRpbC9vYmplY3QnXG5pbXBvcnQgeyBGdXR1cmUgfSBmcm9tICcuLi91dGlsL3Byb21pc2UnXG5pbXBvcnQgeyBkZWJ1Zywgd2FybiB9IGZyb20gJy4uL2xvZydcblxuY29uc3QgTkFNRSA9ICdSNVByb1B1Ymxpc2hlclNvdXJjZUhhbmRsZXInXG5cbi8qKlxuICogRGV0ZXJtaW5lIHRoZSB2aWRlbyBkaW1lbnNpb25zIHNldHRpbmcgdmFsdWUgYmFzZWQgb24gcG9zc2libGUgZGVmaW5pdGlvbiB1c2luZyBgTWVkaWFDb25zdHJhaW50YC5cbiAqIEBwcml2YXRlXG4gKi9cbmNvbnN0IGNvbnZlcnREaW1lbnNpb25PcHRpb25zID0gKHZvKSA9PiB7XG4gIHJldHVybiB2by5leGFjdCB8fCB2by5pZGVhbCB8fCB2by5tYXggfHwgdm8ubWluIHx8IHZvXG59XG5cbi8qKlxuICogRGVmaW5lIHRoZSBhdWRpbyBhbmQgdmlkZW8gc2V0dGluZ3MgZm9yIEZsYXNoLlxuICogVGhlIGB3aWR0aGAgYW5kIGBoZWlnaHRgIGF0dHJpYnV0ZXMgcmVsYXRlIHRvIHZpZGVvLiBUaGUgYGF1ZGlvYCBhdHRyaWJ1dGUgaXMgYSBib29sZWFuIGZsYWcuXG4gKiBAcHJpdmF0ZVxuICovXG5jb25zdCBtZWRpYUNvbnN0cmFpbnRzVG9GbGFzaHZhcnMgPSAoY29uc3RyYWludHMsIGZsYXNodmFycykgPT4ge1xuICBsZXQgZnYgPSBkZWVwQ29weShmbGFzaHZhcnMpXG4gIGlmICh0eXBlb2YgY29uc3RyYWludHMudmlkZW8gPT09ICdib29sZWFuJykge1xuICAgIGZ2LnZpZGVvID0gY29uc3RyYWludHMudmlkZW9cbiAgfVxuICBlbHNlIHtcbiAgICBsZXQga2V5XG4gICAgZm9yIChrZXkgaW4gY29uc3RyYWludHMudmlkZW8pIHtcbiAgICAgIGZ2W2tleV0gPSBjb252ZXJ0RGltZW5zaW9uT3B0aW9ucyhjb25zdHJhaW50cy52aWRlb1trZXldKVxuICAgIH1cbiAgICBmdi52aWRlbyA9IHRydWVcbiAgfVxuICBmdi5hdWRpbyA9IHR5cGVvZiBjb25zdHJhaW50cy5hdWRpbyA9PT0gJ2Jvb2xlYW4nID8gY29uc3RyYWludHMuYXVkaW8gOiB0cnVlXG4gIHJldHVybiBmdlxufVxuXG4vKipcbiAqIFRoZSBpbnRlcm5hbCBQdWJsaXNoIFNvdXJjZSBIYW5kbGVyIGZvciBhbiBSVE1QUHVibGlzaGVyLlxuICogQHByaXZhdGVcbiAqL1xuY2xhc3MgUHVibGlzaGVyU291cmNlSGFuZGxlciB7XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gdmlkZW9cbiAgICogICAgICAgIFRoZSB2aWRlbyBET00gRWxlbWVudC5cbiAgICogQHBhcmFtIHtTdHJpbmd9IHR5cGVcbiAgICogICAgICAgIFRoZSBwdWJsaXNoZXIgdHlwZTogbW9zdCBsaWtlbHksIGBSVE1QYC5cbiAgICogQHBhcmFtIHtPYmplY3R9IHNvUmVzcG9uZGVyXG4gICAqICAgICAgICBPcHRpb25hbCByZXNwb25kZXIgdG8gU2hhcmVkT2JqZWN0IEFQSS4gSWYgbm90IHByb3ZpZGVkLCB3aWxsIGdlbmVyYXRlIGEgYFJUTVBTaGFyZWRPYmplY3RIYW5kbGVyYCBpbnN0YW5jZSBpbnRlcm5hbGx5LlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgY29uc3RydWN0b3IgKHZpZGVvLCB0eXBlLCBzb1Jlc3BvbmRlciA9IHVuZGVmaW5lZCkge1xuICAgIHRoaXMudmlkZW8gPSB2aWRlb1xuICAgIHRoaXMuY2xvbmUgPSB0aGlzLnZpZGVvLmNsb25lTm9kZSh0cnVlKVxuICAgIHRoaXMuaG9sZGVyID0gdGhpcy52aWRlby5wYXJlbnROb2RlXG4gICAgdGhpcy5fcHVibGlzaGVyVHlwZSA9IHR5cGVcbiAgICB0aGlzLl9zd2ZJZCA9IG51bGxcbiAgICB0aGlzLl9lbWJlZEZ1dHVyZSA9IHVuZGVmaW5lZFxuICAgIHRoaXMuX3NvUmVzcG9uZGVyID0gc29SZXNwb25kZXIgfHwgbmV3IFJUTVBTaGFyZWRPYmplY3RIYW5kbGVyKClcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0ZWQgYW5kIHVzZWQgYnkgUlRNUFB1Ymxpc2hlciBpbnN0YW5jZSBpbiByZWNvZ25pemluZyBjb21wbGV0aW9uIG9mIGVtYmVkLlxuICAgKlxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgZ2V0RW1iZWRPcGVyYXRpb24gKCkge1xuICAgIHRoaXMuX2VtYmVkRnV0dXJlID0gRnV0dXJlLmNyZWF0ZUlmTm90RXhpc3QodGhpcy5fZW1iZWRGdXR1cmUpXG4gICAgcmV0dXJuIHRoaXMuX2VtYmVkRnV0dXJlLnByb21pc2VcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhbiB1cCBvZiByZWZlcmVuY2VzIGFuZCBtb2RpZmllZCBkaXNwbGF5LlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgY2xlYW5VcCAoKSB7XG4gICAgLy8gUmV0dXJuIHRvIHByaW9yIERPTSBtYW5pcHVsYXRpb24uXG4gICAgdGhpcy52aWRlby5yZW1vdmUoKVxuICAgIHRoaXMudmlkZW8gPSB0aGlzLmNsb25lLmNsb25lTm9kZSh0cnVlKVxuICAgIHRoaXMuaG9sZGVyLmFwcGVuZENoaWxkKHRoaXMudmlkZW8pXG4gICAgdGhpcy5fZW1iZWRGdXR1cmUgPSB1bmRlZmluZWRcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIGRlZmluZSB0aGUgZW1iZWRkaW5nIG9wdGlvbnMgZm9yIGEgUlRNUFB1Ymxpc2hlci5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IHN3ZklkXG4gICAqICAgICAgICBUaGUgdW5pcXVlIGlkIHRvIHVzZSBpbiBlbWJlZGRpbmcgZWxlbWVudC5cbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICogICAgICAgIFRoZSBpbml0aWFsaXphdGlvbiBjb25maWd1cmF0aW9uIHRvIGRldGVybWluZSBmbGFzaHZhcnMgZnJvbS5cbiAgICogQHBhcmFtIHtTdHJpbmd9IHN3ZlVybFxuICAgKiAgICAgICAgT3B0aW9uYWwgbG9jYXRpb24gb2YgdGhlIFNXRiBmaWxlIHRvIGVtYmVkLiBEZWZhdWx0IGlzIHJlbGF0aXZlIHBhdGggdG8gYHJlZDVwcm8tc3Vic2NyaWJlci5zd2ZgLlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWluRmxhc2hWZXJzaW9uXG4gICAqICAgICAgICBPcHRpb25hbCBzZW12ZXIgb2YgbWluaW11bSBGbGFzaCB2ZXJzaW9uIHRvIGRldGVybWluZSBzdXBwb3J0LiBEZWZhdWx0IGlzIGAxMC4wLjBgLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgICAgICAgVGhlIGBQcm9taXNlYCBlaXRoZXIgcmVzb2x2ZXMgb3IgcmVqZWN0cyB0aGUgc3VjY2VzcyBvZiBlbWJlZCBvbiBwYWdlIHVzaW5nIFNXRk9iamVjdC5cbiAgICogQHByaXZhdGVcbiAgICovXG4gIGFkZFNvdXJjZSAoc3dmSWQsIG9wdGlvbnMsIHN3ZlVybCA9IG51bGwsIG1pbkZsYXNoVmVyc2lvbiA9IG51bGwpIHtcbiAgICBkZWJ1ZyhOQU1FLCAnW2FkZHNvdXJjZV0nKVxuICAgIGNvbnN0IHNlbGYgPSB0aGlzXG4gICAgdGhpcy5fc3dmSWQgPSBzd2ZJZDtcbiAgICB0aGlzLl9lbWJlZEZ1dHVyZSA9IEZ1dHVyZS5jcmVhdGVJZk5vdEV4aXN0KHRoaXMuX2VtYmVkRnV0dXJlKVxuICAgIGNvbnN0IGRlZmVycmVkID0gdGhpcy5fZW1iZWRGdXR1cmVcbiAgICBvcHRpb25zLnN3ZiA9IHN3ZlVybCB8fCBvcHRpb25zLnN3ZlxuICAgIG9wdGlvbnMubWluRmxhc2hWZXJzaW9uID0gbWluRmxhc2hWZXJzaW9uIHx8IG9wdGlvbnMubWluRmxhc2hWZXJzaW9uXG4gICAgZW1iZWQuZGVmaW5lRW1iZWRFbGVtZW50KHRoaXMudmlkZW8sIHRoaXMuaG9sZGVyKVxuICAgICAgLnRoZW4oZWxlbWVudElkID0+IHtcbiAgICAgICAgZGVidWcoTkFNRSwgJ1tlbGVtZW50OmNvbXBsZXRlXScpXG4gICAgICAgIGxldCBmbGFzaHZhcnMgPSB7XG4gICAgICAgICAgYnVmZmVyOiBvcHRpb25zLmJ1ZmZlciAhPSBudWxsID8gb3B0aW9ucy5idWZmZXIgOiAxLFxuICAgICAgICAgIHN0cmVhbU1vZGU6IG9wdGlvbnMuc3RyZWFtTW9kZSxcbiAgICAgICAgICBzdHJlYW1OYW1lOiBvcHRpb25zLnN0cmVhbU5hbWUsXG4gICAgICAgICAgYXBwTmFtZTogb3B0aW9ucy5hcHAsXG4gICAgICAgICAgaG9zdDogb3B0aW9ucy5ob3N0XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMuYmFja2dyb3VuZENvbG9yKSB7XG4gICAgICAgICAgZmxhc2h2YXJzLmJhY2tncm91bmRDb2xvciA9IG9wdGlvbnMuYmFja2dyb3VuZENvbG9yXG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMuY29udGV4dCkge1xuICAgICAgICAgIGZsYXNodmFycy5yb29tTmFtZSA9IG9wdGlvbnMuY29udGV4dFxuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLmVtYmVkV2lkdGggPT09ICcxMDAlJyB8fCBvcHRpb25zLmVtYmVkSGVpZ2h0ID09PSAnMTAwJScpIHtcbiAgICAgICAgICBmbGFzaHZhcnMuYXV0b3NpemUgPSB0cnVlXG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmNvbm5lY3Rpb25QYXJhbXMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgZmxhc2h2YXJzLmNvbm5lY3Rpb25QYXJhbXMgPSBlbmNvZGVVUklDb21wb25lbnQoSlNPTi5zdHJpbmdpZnkob3B0aW9ucy5jb25uZWN0aW9uUGFyYW1zKSlcbiAgICAgICAgfVxuICAgICAgICBmbGFzaHZhcnMgPSBtZWRpYUNvbnN0cmFpbnRzVG9GbGFzaHZhcnMob3B0aW9ucy5tZWRpYUNvbnN0cmFpbnRzLCBmbGFzaHZhcnMpXG4gICAgICAgIHJldHVybiBlbWJlZC5lbWJlZFN3Zk9iamVjdChzd2ZJZCwgb3B0aW9ucywgZmxhc2h2YXJzLCBlbnZpcm9ubWVudC5nZXRTd2ZPYmplY3QoKSwgZWxlbWVudElkKVxuICAgICAgfSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgZGVidWcoTkFNRSwgJ1tlbWJlZDpjb21wbGV0ZV0nKVxuICAgICAgICBkZWZlcnJlZC5yZXNvbHZlKHNlbGYpXG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiBkZWZlcnJlZC5yZWplY3QoZXJyKSlcbiAgICByZXR1cm4gZGVmZXJyZWQucHJvbWlzZVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gY29ubmVjdCB0byBzZXJ2ZXIgZm9yIGEgYnJvYWRjYXN0IHNlc3Npb24uXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwdWJsaXNoT3B0aW9uc1xuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgY29ubmVjdCAocHVibGlzaE9wdGlvbnMpIHtcbiAgICBkZWJ1ZyhOQU1FLCAnW2Nvbm5lY3RdJylcbiAgICBjb25zdCBlbCA9IGVudmlyb25tZW50LmdldEVtYmVkT2JqZWN0KHRoaXMuX3N3ZklkKVxuICAgIGlmIChlbCkge1xuICAgICAgZWwuY29ubmVjdChwdWJsaXNoT3B0aW9ucylcbiAgICAgIHRoaXMuX3NvUmVzcG9uZGVyLmNvbm5lY3QodGhpcy5fc3dmSWQpXG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgd2FybihOQU1FLCAnQ291bGQgbm90IGRldGVybWluZSBlbWJlZGRlZCBlbGVtZW50IHdpdGggc3dmIGlkOiAnICsgdGhpcy5fc3dmSWQgKyAnLicpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gZGlzY29ubmVjdCBmcm9tIHNlcnZlci5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIGRpc2Nvbm5lY3QgKCkge1xuICAgIGRlYnVnKE5BTUUsICdbZGlzY29ubmVjdF0nKVxuICAgIHRyeSB7XG4gICAgICBjb25zdCBlbCA9IGVudmlyb25tZW50LmdldEVtYmVkT2JqZWN0KHRoaXMuX3N3ZklkKVxuICAgICAgaWYgKGVsKSB7XG4gICAgICAgIGVsLmRpc2Nvbm5lY3QoKVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIC8vIG5hZGEuXG4gICAgfVxuICAgIHRoaXMuY2xlYW5VcCgpXG4gICAgdGhpcy5fc29SZXNwb25kZXIuZGlzY29ubmVjdCgpXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBzZW5kIGEgbWVzc2FnZSB0byBhbGwgc3Vic2NyaWJlcnMuXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2ROYW1lXG4gICAqICAgICAgICBUaGUgbWV0aG9kIG5hbWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBtZXNzYWdlIHRvIGJlIGFjY2VwdGVkIGJ5IGFsbCBzdWJzY3JpYmVycy5cbiAgICogQHBhcmFtIHtPYmplY3R9IGRhdGFcbiAgICogICAgICAgIFRoZSBkYXRhIG9iamVjdCB0byBzZW5kIGFzc29jaWF0ZWQgd2l0aCB0aGUgbWV0aG9kIG5hbWUuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBzZW5kIChtZXRob2ROYW1lLCBkYXRhKSB7XG4gICAgY29uc3QgZWwgPSBlbnZpcm9ubWVudC5nZXRFbWJlZE9iamVjdCh0aGlzLl9zd2ZJZClcbiAgICBpZiAoZWwpIHtcbiAgICAgIGVsLnNlbmQobWV0aG9kTmFtZSwgZGF0YSlcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIHJlc3BvbnNlIGhhbmRsZXIgb24gU2hhcmVkT2JqZWN0IGNoYW5uZWwgcmVzcG9uZGVyLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgYWRkU2hhcmVkT2JqZWN0UmVzcG9uc2VIYW5kbGVyIChoYW5kbGVyKSB7XG4gICAgdGhpcy5fc29SZXNwb25kZXIuYWRkUmVzcG9uc2VIYW5kbGVyKGhhbmRsZXIpXG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyBhIHJlc3BvbnNlIGhhbmRsZXIgb24gU2hhcmVkT2JqZWN0IGNoYW5uZWwgcmVzcG9uZGVyLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcmVtb3ZlU2hhcmVkT2JqZWN0UmVzcG9uc2VIYW5kbGVyIChoYW5kbGVyKSB7XG4gICAgdGhpcy5fc29SZXNwb25kZXIucmVtb3ZlUmVzcG9uc2VIYW5kbGVyKGhhbmRsZXIpXG4gIH1cblxuICAvKipcbiAgICogU2VuZHMgbWVzc2FnZSBvbiBTaGFyZWRPYmplY3QgY2hhbm5lbCByZXNwb25kZXIuXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqICAgICAgICBUaGUgU2hhcmVkT2JqZWN0IG5hbWUuXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBjYWxsTmFtZVxuICAgKiAgICAgICAgVGhlIG1ldGhvZCBuYW1lIHRvIGJlIGludm9rZWQuXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqICAgICAgICBUaGUgc3RydWN0dXJlZCB2YWx1ZSB0byBzZW5kLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgc2VuZFRvU2hhcmVkT2JqZWN0IChuYW1lLCBjYWxsTmFtZSwgbWVzc2FnZSkge1xuICAgIHRoaXMuX3NvUmVzcG9uZGVyLnNlbmRUb1NoYXJlZE9iamVjdChuYW1lLCBjYWxsTmFtZSwgbWVzc2FnZSlcbiAgfVxuXG4gIC8qKlxuICAgKiBTZW5kcyBwcm9wZXJ0eSB1cGRhdGUgb24gU2hhcmVkT2JqZWN0IGNoYW5uZWwgcmVzcG9uZGVyLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZVxuICAgKiAgICAgICAgVGhlIFNoYXJlZE9iamVjdCBuYW1lLlxuICAgKiBAcGFyYW0ge1N0cmluZ30ga2V5XG4gICAqICAgICAgICBUaGUgcHJvcGVydHkgbmFtZSBvbiB0aGUgU2hhcmVkT2JqZWN0LlxuICAgKiBAcGFyYW0ge1N0cmluZ30gdmFsdWVcbiAgICogICAgICAgIFRoZSBzdHJ1Y3R1cmVkIHByb3BlcnR5IHZhbHVlLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgc2VuZFByb3BlcnR5VG9TaGFyZWRPYmplY3QgKG5hbWUsIGtleSwgdmFsdWUpIHtcbiAgICB0aGlzLl9zb1Jlc3BvbmRlci5zZW5kUHJvcGVydHlUb1NoYXJlZE9iamVjdChuYW1lLCBrZXksIHZhbHVlKVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3RzIHRvIGdldCBTaGFyZWRPYmplY3QgaW5zdGFuY2UgZnJvbSB0aGUgU2hhcmVkT2JqZWN0IGNoYW5uZWwgcmVzcG9uZGVyLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgZ2V0UmVtb3RlU2hhcmVkT2JqZWN0IChzaGFyZWRPYmplY3ROYW1lKSB7XG4gICAgdGhpcy5fc29SZXNwb25kZXIuZ2V0UmVtb3RlU2hhcmVkT2JqZWN0KHNoYXJlZE9iamVjdE5hbWUpXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBjb25uZWN0IHRvIGEgc2hhcmVkIG9iamVjdC5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IHNoYXJlZE9iamVjdE5hbWVcbiAgICogICAgICAgIFRoZSBuYW1lIG9mIHRoZSBTaGFyZWRPYmplY3QuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBjb25uZWN0VG9TaGFyZWRPYmplY3QgKHNoYXJlZE9iamVjdE5hbWUpIHtcbiAgICB0aGlzLl9zb1Jlc3BvbmRlci5jb25uZWN0VG9TaGFyZWRPYmplY3Qoc2hhcmVkT2JqZWN0TmFtZSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIGNsb3NlIGNvbm5lY3Rpb24gdG8gYSBzaGFyZWQgb2JqZWN0LlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gc2hhcmVkT2JqZWN0TmFtZVxuICAgKiAgICAgICAgVGhlIG5hbWUgb2YgdGhlIFNoYXJlZE9iamVjdC5cbiAgICogQHByaXZhdGVcbiAgICovXG4gIGNsb3NlU2hhcmVkT2JqZWN0IChzaGFyZWRPYmplY3ROYW1lKSB7XG4gICAgdGhpcy5fc29SZXNwb25kZXIuY2xvc2VTaGFyZWRPYmplY3Qoc2hhcmVkT2JqZWN0TmFtZSlcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXByZWNhdGVkLiBSZXF1ZXN0IHRvIHVwZGF0ZSBicm9hZGNhc3QgZGltZW5zaW9ucyBiZWZvcmUgYSBicm9hZGNhc3QuXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBxdWFsaXR5XG4gICAqICAgICAgICBFeHBlY3RzIG9iamVjdCB3aXRoIGZvbGxvd2luZyBzdHJ1Y3R1cjogYHt2aWRlbzoge3dpZHRoOkludCwgaGVpZ2h0SW50fX1cbiAgICogQHByaXZhdGVcbiAgICovXG4gIHNldE1lZGlhUXVhbGl0eSAocXVhbGl0eSkge1xuICAgIGNvbnN0IGVsID0gZW52aXJvbm1lbnQuZ2V0RW1iZWRPYmplY3QodGhpcy5fc3dmSWQpXG4gICAgaWYgKGVsKSB7XG4gICAgICBpZiAocXVhbGl0eS52aWRlbyAmJiB0eXBlb2YgcXVhbGl0eS52aWRlbyAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgIGNvbnN0IHcgPSAhaXNOYU4ocXVhbGl0eS52aWRlby53aWR0aCkgPyB0b0ludChxdWFsaXR5LnZpZGVvLndpZHRoKSA6IE51bWJlci5pc05hTjtcbiAgICAgICAgY29uc3QgaCA9ICFpc05hTihxdWFsaXR5LnZpZGVvLmhlaWdodCkgPyB0b0ludChxdWFsaXR5LnZpZGVvLmhlaWdodCkgOiBOdW1iZXIuaXNOYU47XG4gICAgICAgIGVsLnVwZGF0ZVJlc29sdXRpb24odywgaClcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgdHlwZSBvZiBpbXBsZW1lbnRhdGlvbjogYFJUTVBgLlxuICAgKlxuICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBnZXRUeXBlICgpIHtcbiAgICByZXR1cm4gdGhpcy5fcHVibGlzaGVyVHlwZVxuICB9XG5cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHVibGlzaGVyU291cmNlSGFuZGxlclxuXG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvanMvcHVibGlzaGVyL3B1Yi1zb3VyY2UtaGFuZGxlci5qcyIsIid1c2Ugc3RyaWN0J1xuXG5pbXBvcnQgRXZlbnRFbWl0dGVyIGZyb20gJy4uL2NvcmUvZXZlbnQtZW1pdHRlcidcbmltcG9ydCAqIGFzIHdlYnJ0YyBmcm9tICcuLi9hZGFwdGVyL3dlYnJ0YydcbmltcG9ydCAqIGFzIHdlYnNvY2tldCBmcm9tICcuLi9hZGFwdGVyL3dlYnNvY2tldCdcbmltcG9ydCBlbnZpcm9ubWVudCBmcm9tICcuLi9lbnYvYnJvd3NlcidcbmltcG9ydCBQdWJsaXNoZXJTb2NrZXRIZWxwZXIgZnJvbSAnLi4vaGVscGVyL3NvY2tldC1oZWxwZXItcHViJ1xuaW1wb3J0IFB1Ymxpc2hlclBlZXJIZWxwZXIgZnJvbSAnLi4vaGVscGVyL3dlYnJ0Yy1oZWxwZXItcHViJ1xuaW1wb3J0IFB1Ymxpc2hWaWV3IGZyb20gJy4uL3ZpZXcvcHVibGlzaCdcbmltcG9ydCB7IFB1Ymxpc2hlckV2ZW50IH0gZnJvbSAnLi4vZXZlbnQnXG5pbXBvcnQgeyBQdWJsaXNoTW9kZVR5cGVzIH0gZnJvbSAnLi4vZW51bS9wdWJsaXNoJ1xuaW1wb3J0IHsgUHVibGlzaFR5cGVzIH0gZnJvbSAnLi4vZW51bS9wdWJsaXNoJ1xuaW1wb3J0IHsgSWNlVHJhbnNwb3J0VHlwZXMgfSBmcm9tICcuLi9lbnVtL3dlYnJ0YydcbmltcG9ydCB7IERlZmVycmVkUHJvbWlzZSwgRnV0dXJlIH0gZnJvbSAnLi4vdXRpbC9wcm9taXNlJ1xuaW1wb3J0IHsgUHVibGlzaGVyRXZlbnRUeXBlcywgUlRDUHVibGlzaGVyRXZlbnRUeXBlcyB9IGZyb20gJy4uL2V2ZW50J1xuaW1wb3J0IHsgUlRDTWVkaWFDb25zdHJhaW50IH0gZnJvbSAnLi9jb25zdHJhaW50J1xuaW1wb3J0IHsgcnRjU29ja2V0RW5kcG9pbnRGcm9tT3B0aW9ucyBhcyBlbmRwb2ludEZyb21PcHRpb25zIH0gZnJvbSAnLi4vdXRpbC91cmwtZW5kcG9pbnQnXG5pbXBvcnQgeyBkZWJ1ZyBhcyBkZWJ1Z0xvZyB9IGZyb20gJy4uL2xvZydcbmltcG9ydCB7IGVycm9yIGFzIGVycm9yTG9nIH0gZnJvbSAnLi4vbG9nJ1xuaW1wb3J0IHsgd2FybiBhcyB3YXJuTG9nIH0gZnJvbSAnLi4vbG9nJ1xuXG5jb25zdCBwdWJTdGFydFJlZ2V4ID0gLyguKikgc3RhcnRpbmcvaVxuY29uc3QgcHViU3RvcFJlZ2V4ID0gLyguKikgc3RvcHBpbmcvaVxuY29uc3QgTkFNRSA9ICdSVENQdWJsaXNoZXInXG5jb25zdCBkZWJ1ZyA9IChtZXNzYWdlKSA9PiB7XG4gIGRlYnVnTG9nKE5BTUUsIG1lc3NhZ2UpXG59XG5jb25zdCB3YXJuID0gKG1lc3NhZ2UpID0+IHtcbiAgd2FybkxvZyhOQU1FLCBtZXNzYWdlKVxufVxuY29uc3QgZXJyb3IgPSAobWVzc2FnZSkgPT4ge1xuICBlcnJvckxvZyhOQU1FLCBtZXNzYWdlKVxufVxuXG4vLyBEZWZhdWx0IHRvIHNlY3VyZSBzZXR0aW5ncy5cbmNvbnN0IGRlZmF1bHRPcHRpb25zID0ge1xuICBwcm90b2NvbDogJ3dzcycsXG4gIHBvcnQ6IDgwODMsXG4gIGFwcDogJ2xpdmUnLFxuICBzdHJlYW1Nb2RlOiBQdWJsaXNoTW9kZVR5cGVzLkxJVkUsXG4gIG1lZGlhRWxlbWVudElkOiAncmVkNXByby1wdWJsaXNoZXInLFxuICBpY2VTZXJ2ZXJzOiBbe3VybHM6ICdzdHVuOnN0dW4yLmwuZ29vZ2xlLmNvbToxOTMwMid9XSxcbiAgaWNlVHJhbnNwb3J0OiBJY2VUcmFuc3BvcnRUeXBlcy5VRFAsXG4gIGJhbmR3aWR0aDoge1xuICAgIGF1ZGlvOiA1NixcbiAgICB2aWRlbzogNTEyXG4gIH0sXG4gIG1lZGlhQ29uc3RyYWludHM6IG5ldyBSVENNZWRpYUNvbnN0cmFpbnQoKSxcbiAgb25HZXRVc2VyTWVkaWE6IHVuZGVmaW5lZFxufVxuXG4vKipcbiAqIE1haW4gZW50cnkgZm9yIFdlYlJUQy1iYXNlZCBQdWJsaXNoZXIuXG4gKlxuICogQGV4dGVuZHMgRXZlbnRFbWl0dGVyXG4gKi9cbmNsYXNzIFJUQ1B1Ymxpc2hlciBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG5cbiAgY29uc3RydWN0b3IgKCkge1xuICAgIHN1cGVyKClcbiAgICB0aGlzLl9vcHRpb25zID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fdmlldyA9IHVuZGVmaW5lZFxuICAgIHRoaXMuX3BlZXJIZWxwZXIgPSB1bmRlZmluZWRcbiAgICB0aGlzLl9zb2NrZXRIZWxwZXIgPSB1bmRlZmluZWRcbiAgICB0aGlzLl9tZWRpYVN0cmVhbSA9IHVuZGVmaW5lZFxuXG4gICAgdGhpcy5fc3RyZWFtRnV0dXJlID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fYXZhaWxhYmxlRnV0dXJlID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fcGVlckZ1dHVyZSA9IHVuZGVmaW5lZFxuICAgIHRoaXMuX29mZmVyRnV0dXJlID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fc2VuZE9mZmVyRnV0dXJlID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fdHJpY2tsZUVuZEZ1dHVyZSA9IHVuZGVmaW5lZFxuICAgIHRoaXMuX3B1Ymxpc2hGdXR1cmUgPSB1bmRlZmluZWRcbiAgICB0aGlzLl91bnB1Ymxpc2hGdXR1cmUgPSB1bmRlZmluZWRcblxuICAgIHRoaXMuX29uT3JpZW50YXRpb25DaGFuZ2UgPSB0aGlzLl9vbk9yaWVudGF0aW9uQ2hhbmdlLmJpbmQodGhpcylcbiAgfVxuXG4gIF9nZXRNZWRpYVN0cmVhbSAoKSB7XG4gICAgdGhpcy5fc3RyZWFtRnV0dXJlID0gRnV0dXJlLmNyZWF0ZUlmTm90RXhpc3QodGhpcy5fc3RyZWFtRnV0dXJlKVxuICAgIHJldHVybiB0aGlzLl9zdHJlYW1GdXR1cmUucHJvbWlzZVxuICB9XG5cbiAgX2dldFRyaWNrbGVFbmQgKCkge1xuICAgIHJldHVybiBGdXR1cmUuY3JlYXRlSWZOb3RFeGlzdCh0aGlzLl90cmlja2xlRW5kRnV0dXJlKVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgaW50ZXJuYWwgYGdldFVzZXJNZWRpYWAgbG9naWMgdG8gZGV0ZXJtaW5lIGJyb2FkY2FzdCBjb25zdHJhaW50cy5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICogICAgICAgIFRoZSBpbml0aWFsaXphdGlvbiBvcHRpb25zIHByb3ZpZGVkIGluIGBpbml0KClgLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX2d1bSAob3B0aW9ucykge1xuICAgIGlmIChvcHRpb25zLm9uR2V0VXNlck1lZGlhICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGRlYnVnKCdSZXF1ZXN0aW5nIGdVTSBmcm9tIHVzZXItZGVmaW5lZCBjb25maWd1cmF0aW9uOm9uR2V0VXNlck1lZGlhLicpXG4gICAgICBvcHRpb25zLm9uR2V0VXNlck1lZGlhKClcbiAgICAgICAgLnRoZW4obWVkaWEgPT4ge1xuICAgICAgICAgIHRoaXMuX3N0cmVhbUZ1dHVyZS5yZXNvbHZlKG1lZGlhKVxuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgICBlcnJvcihgQ291bGQgbm90IHJlc29sdmUgTWVkaWFBc3NldCBmcm9tIHByb3ZpZGVkIGdVTS4gRXJyb3IgLSAke2Vycn1gKVxuICAgICAgICAgIHRoaXMuX3N0cmVhbUZ1dHVyZS5yZWplY3QoZXJyKVxuICAgICAgICB9KVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIGRlYnVnKGBSZXF1ZXN0aW5nIGdVTSB1c2luZyBtZWRpYUNvbnN0cmFpbnRzOiAke0pTT04uc3RyaW5naWZ5KG9wdGlvbnMubWVkaWFDb25zdHJhaW50cywgbnVsbCwgMil9YClcbiAgICAgIHRoaXMuX3BlZXJIZWxwZXIuZ2V0VXNlck1lZGlhKG9wdGlvbnMubWVkaWFDb25zdHJhaW50cylcbiAgICAgICAgLnRoZW4ocmVzID0+IHtcbiAgICAgICAgICBkZWJ1ZyhgRm91bmQgdmFsaWQgY29uc3RyYWludHM6ICR7SlNPTi5zdHJpbmdpZnkocmVzLmNvbnN0cmFpbnRzLCBudWxsLCAyKX1gKVxuICAgICAgICAgIHRoaXMudHJpZ2dlcihuZXcgUHVibGlzaGVyRXZlbnQoUHVibGlzaGVyRXZlbnRUeXBlcy5ESU1FTlNJT05fQ0hBTkdFLCB0aGlzLCByZXMuY29uc3RyYWludHMpKVxuICAgICAgICAgIHRoaXMuX3N0cmVhbUZ1dHVyZS5yZXNvbHZlKHJlcy5tZWRpYSlcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKHJlaiA9PiB7XG4gICAgICAgICAgZGVidWcoYENvdWxkIG5vdCBmaW5kIHZhbGlkIGNvbnN0cmFpbnQgcmVzb2x1dGlvbnMgZnJvbTogJHtKU09OLnN0cmluZ2lmeShyZWouY29uc3RyYWludHMsIG51bGwsIDIpfWApXG4gICAgICAgICAgZXJyb3IoYENvdWxkIG5vdCByZXNvbHZlIE1lZGlhQXNzZXQgZnJvbSBwcm92aWRlZCBtZWRpYUNvbnN0cmFpbnRzLiBFcnJvciAtICR7cmVqLmVycm9yfWApXG4gICAgICAgICAgZGVidWcoYEF0dGVtcHRpbmcgdG8gZmluZCByZXNvbHV0aW9ucyBmcm9tIG9yaWdpbmFsIHByb3ZpZGVkIGNvbnN0cmFpbnRzOiAke0pTT04uc3RyaW5naWZ5KHJlai5jb25zdHJhaW50cywgbnVsbCwgMil9YClcbiAgICAgICAgICAvLyBhbGxvd2luZyB0byB0cnkgb3JpZ2luYWwgY29uc3RyYWludCByZXF1ZXN0ZWQuXG4gICAgICAgICAgb3B0aW9ucy5vbkdldFVzZXJNZWRpYSA9ICgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9wZWVySGVscGVyLmZvcmNlVXNlck1lZGlhKHJlai5jb25zdHJhaW50cylcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5fZ3VtKG9wdGlvbnMpXG4gICAgICAgIH0pXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEludm9rZWQgdXBvbiBgb25vcmllbnRhdGlvbmNoYW5nZWAgb2YgdGhlIGJyb3dzZXIuIE1vYmlsZSBicm93c2VycyBvbmx5LlxuICAgKlxuICAgKiBAcGFyYW0ge2ludH0gb3JpZW50YXRpb25cbiAgICogICAgICAgIFRoZSBvcmllbnRhdGlvbiB2YWx1ZSBvZiB0aGUgZGV2aWNlIGJyb3dzZXIuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICAgIF9vbk9yaWVudGF0aW9uQ2hhbmdlIChvcmllbnRhdGlvbikge1xuICAgICAgaWYgKHRoaXMuX3NvY2tldEhlbHBlcikge1xuICAgICAgICB0aGlzLl9zb2NrZXRIZWxwZXIucG9zdCh7XG4gICAgICAgICAgc2VuZDoge1xuICAgICAgICAgICAgbWV0aG9kOiAnb25NZXRhRGF0YScsXG4gICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgIGRldmljZU9yaWVudGF0aW9uOiBvcmllbnRhdGlvblxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgIH1cbiAgICB9XG5cbiAgLyoqXG4gICAqIEludm9rZWQgdXBvbiByZWNlaXB0IGZyb20gYF9ndW1gIHdpdGggTWVkaWFTdHJlYW0gaW5zdGFuY2UgcmV0dXJuZWQgZnJvbSBicm93c2VyLlxuICAgKlxuICAgKiBAcGFyYW0ge01lZGlhU3RyZWFtfSBtZWRpYVN0cmVhbVxuICAgKiAgICAgICAgVGhlIGBNZWRpYVN0cmVhbWAgb2JqZWN0LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX29uTWVkaWFTdHJlYW1SZWNlaXZlZCAobWVkaWFTdHJlYW0pIHtcbiAgICAvLyAgICBpZiAodGhpcy5fc29ja2V0SGVscGVyICYmICF0aGlzLl9zb2NrZXRIZWxwZXIuaXNUZXJtaW5hdGVkKSB7XG4gICAgICB0aGlzLl9tZWRpYVN0cmVhbSA9IG1lZGlhU3RyZWFtXG4gICAgICB0aGlzLnRyaWdnZXIobmV3IFB1Ymxpc2hlckV2ZW50KFJUQ1B1Ymxpc2hlckV2ZW50VHlwZXMuTUVESUFfU1RSRUFNX0FWQUlMQUJMRSwgdGhpcywgbWVkaWFTdHJlYW0pKVxuICAgICAgaWYgKHRoaXMuX3ZpZXcpIHtcbiAgICAgICAgdGhpcy5fdmlldy5wcmV2aWV3KHRoaXMuX21lZGlhU3RyZWFtKVxuICAgICAgfVxuICAgICAgLy8gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFN0aWxsIGluIHVzZSwgYnV0IGhvbGQtb3ZlciBvZiBwcmV2aW91cyAzLnggU0RLIHZlcnNpb25zIGRlc2lnbmVkIHRvIHBhaXIgdmlld3MgYW5kIHB1Ymxpc2hlcnMuIEluIDQuMC4wIGl0IGhhcyBiZWVuIGludGVybmFsaXplZC5cbiAgICogQVBJIGRlcHJlY2F0ZWQuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfc2V0Vmlld0lmTm90RXhpc3QgKGN1cnJlbnRWaWV3LCBtZWRpYUVsZW1lbnRJZCA9IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKHR5cGVvZiBjdXJyZW50VmlldyA9PT0gJ3VuZGVmaW5lZCcgJiYgbWVkaWFFbGVtZW50SWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBsZXQgdmlldyA9IG5ldyBQdWJsaXNoVmlldyhtZWRpYUVsZW1lbnRJZClcbiAgICAgICAgdmlldy5hdHRhY2hQdWJsaXNoZXIodGhpcylcbiAgICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IGF2YWlsYWJpbGl0eSBiYXNlZCBvbiB1bmlxdWUgYHN0cmVhbU5hbWVgLlxuICAgKiBUaGUgcmV0dXJuIGZyb20gdGhlIFdlYlNvY2tldCByZXF1ZXN0IHdpbGwgZWl0aGVyIGludm9rZSBgb25TdHJlYW1BdmFpbGFibGVgIG9yIGBvblN0cmVhbVVuYXZhaWxhYmxlYC5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IHN0cmVhbU5hbWVcbiAgICogICAgICAgIFRoZSB1bmlxdWUgc3RyZWFtIG5hbWUgdG8gY2hlY2sgaWYgaXQgaXMgX3VuYXZhaWxhYmxlXyAtIG1lYW5pbmcgZnJlZSB0byBwdWJsaXNoIGFnYWluc3QuXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgICAgICBUaGUgcHJvbWlzZSB3aWxsIHJlc29sdmUvcmVqZWN0IHRoZSBgX2F2YWlsYWJsZUZ1dHVyZWAuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfcmVxdWVzdEF2YWlsYWJpbGl0eSAoc3RyZWFtTmFtZSkge1xuICAgIGRlYnVnKCdbcmVxdWVzdGF2YWlsYWJpbGl0eV0nKVxuICAgIHRoaXMuX2F2YWlsYWJsZUZ1dHVyZSA9IHVuZGVmaW5lZFxuICAgIHRoaXMuX2F2YWlsYWJsZUZ1dHVyZSA9IEZ1dHVyZS5jcmVhdGVJZk5vdEV4aXN0KHRoaXMuX2F2YWlsYWJsZUZ1dHVyZSlcbiAgICB0aGlzLl9zb2NrZXRIZWxwZXIucG9zdCh7XG4gICAgICBpc0F2YWlsYWJsZTogc3RyZWFtTmFtZSxcbiAgICAgIGJ1bmRsZTogZmFsc2VcbiAgICB9KVxuICAgIHJldHVybiB0aGlzLl9hdmFpbGFibGVGdXR1cmUucHJvbWlzZVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gc2V0dXAgUlRDUGVlckNvbm5lY3Rpb24gaW5zdGFuY2UgZm9yIGV4Y2hhbmdlIG9mIFNEUCBsb2NhbGx5IGFuZCByZW1vdGVseS5cbiAgICpcbiAgICogQHBhcmFtIHtBcnJheX0gaWNlU2VydmVyc1xuICAgKiAgICAgICAgTGlzdCBvZiBJQ0Ugc2VydmVyc1xuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgICAgICAgVGhlIHByb21pc2Ugd2lsbCByZXNvbHZlL3JlamVjdCB0aGUgYF9wZWVyRnV0dXJlYC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9jcmVhdGVQZWVyQ29ubmVjdGlvbiAoaWNlU2VydmVycykge1xuICAgIGRlYnVnKCdbY3JlYXRlcGVlZXJdJylcbiAgICB0aGlzLl9wZWVyRnV0dXJlID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fcGVlckZ1dHVyZSA9IEZ1dHVyZS5jcmVhdGVJZk5vdEV4aXN0KHRoaXMuX3BlZXJGdXR1cmUpXG4gICAgdGhpcy5fcGVlckhlbHBlci5zZXRVcChpY2VTZXJ2ZXJzLCB0aGlzLl9wZWVyRnV0dXJlLCB0aGlzLl9vcHRpb25zLnJ0Y3BNdXhQb2xpY3kpXG4gICAgcmV0dXJuIHRoaXMuX3BlZXJGdXR1cmUucHJvbWlzZVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gZ2VuZXJhdGUgb2ZmZXIgb24gUGVlciBDb25uZWN0aW9uIGluc3RhbmNlLlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gYmFuZHdpZHRoXG4gICAqICAgICAgICBPcHRpb25hbCBiYW5kd2lkdGggY29uZmlndXJhdGlvbiBvYmplY3QgdG8gbXVuZ2UgU0RQLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgICAgICAgVGhlIHByb21pc2Ugd2lsbCByZXNvbHZlL3JlamVjdCBhIHN1Y2Nlc3MgaW4gY3JlYXRpb24gb2YgdGhlIG9mZmVyIHRocm91Z2ggdGhlIFBlZXIgQ29ubmVjdGlvbi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9jcmVhdGVPZmZlciAoYmFuZHdpZHRoID0gbnVsbCkge1xuICAgIGRlYnVnKCdbY3JlYXRlb2ZmZXJdJylcbiAgICB0aGlzLl9vZmZlckZ1dHVyZSA9IHVuZGVmaW5lZFxuICAgIHRoaXMuX29mZmVyRnV0dXJlID0gRnV0dXJlLmNyZWF0ZUlmTm90RXhpc3QodGhpcy5fb2ZmZXJGdXR1cmUpXG4gICAgdGhpcy5fcGVlckhlbHBlci5jcmVhdGVPZmZlcihiYW5kd2lkdGgsIHRoaXMuX29mZmVyRnV0dXJlKVxuICAgIHJldHVybiB0aGlzLl9vZmZlckZ1dHVyZS5wcm9taXNlXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBzZXQgYSByZW1vdGUgZGVzY3JpcHRpb24gb24gUGVlciBDb25uZWN0aW9uIGluc3RhbmNlLlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gc2RwXG4gICAqICAgICAgICBPYmplY3QgZGVzY3JpYmluZyB0aGUgU2Vzc2lvbiBEZXNjcmlwdGlvbi5cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICAgICAgIFRoZSBwcm9taXNlIHdpbGwgcmVzb2x2ZS9yZWplY3QgaW4gYSBzdWNjZXNzIGluIHNldHRpbmcgdGhlIHJlbW90ZSBTRFAgb24gdGhlIFBlZXIgQ29ubmVjdGlvbi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9zZXRSZW1vdGVEZXNjcmlwdGlvbiAoc2RwKSB7XG4gICAgZGVidWcoJ1tzZXRyZW1vdGVkZXNjcmlwdGlvbl0nKVxuICAgIHJldHVybiB0aGlzLl9wZWVySGVscGVyLnNldFJlbW90ZURlc2NyaXB0aW9uKHNkcClcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIHNlbmQgb2ZmZXIgb24gV2ViU29ja2V0IGluc3RhbmNlLlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gc2RwXG4gICAqICAgICAgICBPYmplY3QgZGVzY3JpYmluZyB0aGUgU2Vzc2lvbiBEZXNjcmlwdGlvbi5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmVhbU5hbWVcbiAgICogICAgICAgIFRoZSB1bmlxdWUgc3RyZWFtIG5hbWUgb2YgdGhlIGJyb2FkY2FzdC5cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICAgICAgIFRoZSBwcm9taXNlIHdpbGwgcmVzb2x2ZS9yZWplY3Qgb24gdGhlIHN1Y2Nlc3Mgb2YgZGVsaXZlcmluZyBhbiBvZmZlciBvdmVyIHRoZSBXZWJTb2NrZXQuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfc2VuZE9mZmVyIChzZHAsIHN0cmVhbU5hbWUsIHRyYW5zcG9ydCkge1xuICAgIGRlYnVnKCdbc2VuZG9mZmVyXScpXG4gICAgdGhpcy5fc2VuZE9mZmVyRnV0dXJlID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fc2VuZE9mZmVyRnV0dXJlID0gRnV0dXJlLmNyZWF0ZUlmTm90RXhpc3QodGhpcy5fc2VuZE9mZkZ1dHVyZSlcbiAgICB0aGlzLl9zb2NrZXRIZWxwZXIucG9zdCh7XG4gICAgICBoYW5kbGVPZmZlcjogc3RyZWFtTmFtZSxcbiAgICAgIHRyYW5zcG9ydDogdHJhbnNwb3J0LFxuICAgICAgZGF0YToge1xuICAgICAgICBzZHA6IHNkcFxuICAgICAgfVxuICAgIH0pXG4gICAgcmV0dXJuIHRoaXMuX3NlbmRPZmZlckZ1dHVyZS5wcm9taXNlXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBzZW5kIElDRSBjYW5kaWRhdGUgb3ZlciB0aGUgV2ViU29ja2V0LlxuICAgKiBUaGlzIGNhbiBoYXBwZW4gc2V2ZXJhbCB0aW1lcyBpbiB0aGUgSUNFIG5lZ290aWF0aW9uIHByb2Nlc3MuXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBjYW5kaWRhdGVcbiAgICogICAgICAgIFRoZSBDYW5kaWRhdGUgdG8gc2VuZC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmVhbU5hbWVcbiAgICogICAgICAgIFRoZSBhc3NvY2lhdGVkIHVuaXF1ZSBzdHJlYW0gbmFtZSBvZiB0aGUgYnJvYWRjYXN0LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX3NlbmRDYW5kaWRhdGUgKGNhbmRpZGF0ZSwgc3RyZWFtTmFtZSkge1xuICAgIGRlYnVnKCdbc2VuZGNhbmRpZGF0ZV0nKVxuICAgIHRoaXMuX3NvY2tldEhlbHBlci5wb3N0KHtcbiAgICAgIGhhbmRsZUNhbmRpZGF0ZTogc3RyZWFtTmFtZSxcbiAgICAgIGRhdGE6IHtcbiAgICAgICAgY2FuZGlkYXRlOiBjYW5kaWRhdGVcbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3Qgb24gV2ViU29ja2V0IHRvIGJlZ2luIHB1Ymxpc2hpbmcuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJlYW1OYW1lXG4gICAqICAgICAgICBUaGUgdW5pcXVlIHN0cmVhbSBuYW1lIG9mIHRoZSBicm9hZGNhc3QuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBtb2RlXG4gICAqICAgICAgICBUaGUgYnJvYWRjYXN0IG1vZGU6IGBsaXZlYCwgYHJlY29yZGAgb3IgYGFwcGVuZGAuXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgICAgICBUaGUgcHJvbWlzZSB3aWxsIHJlc29sdmUvcmVqZWN0IGluIHRoZSByZXF1ZXN0IHRvIGJlaW5nIGEgYnJvYWRjYXN0LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX3JlcXVlc3RQdWJsaXNoIChzdHJlYW1OYW1lLCBzdHJlYW1Nb2RlKSB7XG4gICAgZGVidWcoJ1tyZXF1ZXN0cHVibGlzaF0nKVxuICAgIHRoaXMuX3B1Ymxpc2hGdXR1cmUgPSB1bmRlZmluZWRcbiAgICB0aGlzLl9wdWJsaXNoRnV0dXJlID0gRnV0dXJlLmNyZWF0ZUlmTm90RXhpc3QodGhpcy5fcHVibGlzaEZ1dHVyZSlcbiAgICB0aGlzLl9zb2NrZXRIZWxwZXIucG9zdCh7XG4gICAgICBwdWJsaXNoOiBzdHJlYW1OYW1lLFxuICAgICAgbW9kZTogc3RyZWFtTW9kZVxuICAgIH0pXG4gICAgcmV0dXJuIHRoaXMuX3B1Ymxpc2hGdXR1cmUucHJvbWlzZVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gc3RvcCBhIGN1cnJlbnQgYnJvYWRjYXN0LlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyZWFtTmFtZVxuICAgKiAgICAgICAgVGhlIHVuaXF1ZSBzdHJlYW0gbmFtZSBiZWluZyBicm9hZGNhc3Qgb24uXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgICAgICBUaGUgcHJvbWlzZSB3aWxsIHJlc29sdmUvcmVqZWN0IG9uIHN1Y2Nlc3Mgb2YgcHJvcGVybHkgc3RvcHBpbmcgYSBicm9hZGNhc3QuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfcmVxdWVzdFVucHVibGlzaCAoc3RyZWFtTmFtZSkge1xuICAgIHRoaXMuX3VucHVibGlzaEZ1dHVyZSA9IHVuZGVmaW5lZFxuICAgIHRoaXMuX3VucHVibGlzaEZ1dHVyZSA9IEZ1dHVyZS5jcmVhdGVJZk5vdEV4aXN0KHRoaXMuX3VucHVibGlzaEZ1dHVyZSlcbiAgICAvLyBJZiB3ZSBnZXQgYSBmYWxzZSByZXNwb25zZSBmcm9tIHRyeWluZyB0byBzZW5kIGEgY2xvc2UgUE9TVCxcbiAgICAvLyAgaXQgbWVhbnMgdGhhdCB0aGUgc29ja2V0IGhhcyBhbHJlYWR5IGJlZW4gY2xvc2VkIGJ5IGFub3RoZXIgaW1wZXR1cyAtXG4gICAgLy8gIG1vc3QgbGlrbGV5IGxvc3Mgb2YgbmV0d29yayBvciBzZXJ2ZXIgZmFpbHVyZS5cbiAgICBpZiAoIXRoaXMuX3NvY2tldEhlbHBlci5wb3N0KHtcbiAgICAgICAgICB1bnB1Ymxpc2g6IHN0cmVhbU5hbWVcbiAgICAgICAgfSkpIHtcbiAgICAgIHRoaXMuX3VucHVibGlzaEZ1dHVyZS5yZXNvbHZlKClcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3VucHVibGlzaEZ1dHVyZS5wcm9taXNlXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBpbml0aWFsaXplIHRoZSBXZWJSVEMtYmFzZWQgUHVibGlzaGVyIGJhc2VkIG9uIGNvbmZpZ3VyYXRpb24uXG4gICAqIFRoZSByZXR1cm5lZCBgUHJvbWlzZWAgd2lsbCBlaXRoZXIgcmVzb2x2ZSB3aXRoIGEgcmVmZXJlbmNlIHRvIHRoaXMgaW5zdGFuY2Ugb3IgcmVqZWN0IHdpdGggYW4gZXJyb3IgYFN0cmluZ2AgaW4gZmFpbHVyZS5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICogICAgICAgIFRoZSBpbml0aWFsaXphdGlvbiBjb25maWd1cmF0aW9uIG1hcC5cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICovXG4gIGluaXQgKG9wdGlvbnMpIHtcbiAgICBjb25zdCBkZWZlcnJlZCA9IG5ldyBEZWZlcnJlZFByb21pc2UoKVxuICAgIGlmICghd2VicnRjLmlzU3VwcG9ydGVkKCkgfHwgIXdlYnNvY2tldC5pc1N1cHBvcnRlZCgpKSB7XG4gICAgICBkZWZlcnJlZC5yZWplY3QoJ0Nhbm5vdCBjcmVhdGUgV2ViUlRDIHBsYXliYWNrIGluc3RhbmNlLiBZb3VyIGVudmlyb25tZW50IGRvZXMgbm90IHN1cHBvcnQgV2ViUlRDIGFuZC9vciBXZWJTb2NrZXRzLicpXG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgdGhpcy5fb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oe30sIGRlZmF1bHRPcHRpb25zLCBvcHRpb25zKVxuICAgICAgdGhpcy5fcGVlckhlbHBlciA9IG5ldyBQdWJsaXNoZXJQZWVySGVscGVyKHRoaXMpXG4gICAgICB0aGlzLl9zb2NrZXRIZWxwZXIgPSBuZXcgUHVibGlzaGVyU29ja2V0SGVscGVyKHRoaXMpXG4gICAgICB0aGlzLl9nZXRNZWRpYVN0cmVhbSgpXG4gICAgICAgIC50aGVuKHRoaXMuX29uTWVkaWFTdHJlYW1SZWNlaXZlZC5iaW5kKHRoaXMpKVxuICAgICAgdGhpcy5fZ3VtKHRoaXMuX29wdGlvbnMpXG4gICAgICAvLyBhdXRvIHByZXZpZXcuXG4gICAgICB0aGlzLl9zZXRWaWV3SWZOb3RFeGlzdCh0aGlzLl92aWV3LCB0aGlzLl9vcHRpb25zLm1lZGlhRWxlbWVudElkKVxuICAgICAgZGVmZXJyZWQucmVzb2x2ZSh0aGlzKVxuICAgIH1cbiAgICByZXR1cm4gZGVmZXJyZWQucHJvbWlzZVxuICB9XG5cbiAgLyoqXG4gICAqIFN0aWxsIGluIHVzZSBmb3IgYXNzaWduaW5nIGRvY3VtZW50IGVsZW1lbnQgdmlldyBtYW5hZ2VtZW50IHRvIHRoaXMgaW5zdGFuY2UuXG4gICAqIEFQSSBkZXByZWNhdGVkIGluIDQuMC4wLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgc2V0VmlldyAodmlldykge1xuICAgIHRoaXMuX3ZpZXcgPSB2aWV3XG4gICAgaWYgKHRoaXMuX21lZGlhU3RyZWFtICYmIHRoaXMuX3ZpZXcpIHtcbiAgICAgIHRoaXMuX3ZpZXcucHJldmlldyh0aGlzLl9tZWRpYVN0cmVhbSlcbiAgICB9XG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIC8qKlxuICAgKiBTdGlsbCBpbiB1c2UgZm9yIGFzc2lnbmluZyBkb2N1bWVudCBlbGVtZW50IHZpZXcgbWFuYWdlbWVudCB0byB0aGlzIGluc3RhbmNlLlxuICAgKiBBUEkgZGVwcmVjYXRlZCBpbiA0LjAuMC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByZXZpZXcgKCkge1xuICAgIGRlYnVnKCdbcHJldmlld10nKVxuICAgIGNvbnN0IHAgPSBuZXcgUHJvbWlzZSgocmVzKSA9PiB7XG4gICAgICByZXModGhpcylcbiAgICB9KVxuICAgIHRoaXMuX3NldFZpZXdJZk5vdEV4aXN0KHRoaXMuX3ZpZXcsIHRoaXMuX29wdGlvbnMubWVkaWFFbGVtZW50SWQpXG4gICAgcmV0dXJuIHBcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIGJlZ2luIGEgYnJvYWRjYXN0IHNlc3Npb24gYWZ0ZXIgaW5pdGlsaXphdGlvbiBoYXMgb2NjdXJlZC5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IHN0cmVhbU5hbWVcbiAgICogICAgICAgIE9wdGlvbmFsIHN0cmVhbSBuYW1lIHRvIGJyb2FkY2FzdCBvbiwgb3RoZXJ3aXNlIGRlZmF1bHRpbmcgdG8gdGhlIGBzdHJlYW1OYW1lYCBwcm92aWRlZCBpbiBgaW5pdCgpYCBjb25maWd1cmF0aW9uLlxuICAgKiBAcGFyYW0ge1Byb21pc2V9IHByb21pc2VcbiAgICogICAgICAgIE9wdGlvbmFsIGBQcm9taXNlYCBvYmplY3QgdG8gcmVzb2x2ZS9yZWplY3Qgb24gYmFzZWQgb24gc2VxdWVuY2Ugb2YgZXZlbnRzIGluIGVzdGFibGlzaGluZyBhIGJyb2FkY2FzdCwgb3RoZXJ3aXNlIGRlZmF1bHRpbmcgdG8gYFByb21pc2VgIGNyZWF0ZWQgaW50ZXJuYWxseSBhbmQgcmV0dXJuZWQuXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgICAgICBUaGUgcmV0dXJuZWQgYFByb21pc2VgIHdpbGwgcmVzb2x2ZSBvciByZWplY3Qgb24gc3VjY2Vzc2Z1bCBzdGFydCBvZiBhIGJyb2FkY2FzdC48YnI+XG4gICAqICAgICAgICBUaGVyZSBhcmUgc2V2ZXJhbCBwcm9jZXNzZXMgdGhhdCBvY2N1ciBpbiBvcmRlciB0byBlc3RhYmxpc2ggYSBXZWJSVEMgYnJvYWRjYXN0IHRoYXQgaW52b2x2ZSAtIGJ1dCBhcmUgbm90IGxpbWl0ZWQgdG8gLSBJQ0UgY29tbXVuaWNhdGlvbiBhbmQgYXNzaWduaW5nIG9mIGxvY2FsIGFuZCByZW1vdGUgU0RQcyBvbiBwZWVyIGNvbm5lY3Rpb25zLlxuICAgKi9cbiAgcHVibGlzaCAoc3RyZWFtTmFtZSA9IG51bGwsIHByb21pc2UgPSBudWxsKSB7XG4gICAgZGVidWcoJ1twdWJsaXNoXScpXG4gICAgdGhpcy5fb3B0aW9ucy5zdHJlYW1OYW1lID0gc3RyZWFtTmFtZSB8fCB0aGlzLl9vcHRpb25zLnN0cmVhbU5hbWVcbiAgICBjb25zdCBwID0gcHJvbWlzZSB8fCBuZXcgRGVmZXJyZWRQcm9taXNlKClcbiAgICBjb25zdCBzb2NrZXRQcm9taXNlID0gbmV3IERlZmVycmVkUHJvbWlzZSgpXG4gICAgY29uc3Qgc29ja2V0dXJsID0gZW5kcG9pbnRGcm9tT3B0aW9ucyh0aGlzLl9vcHRpb25zLCB7XG4gICAgICBpZDogdGhpcy5fb3B0aW9ucy5zdHJlYW1OYW1lXG4gICAgfSlcbiAgICB0aGlzLl90cmlja2xlRW5kRnV0dXJlID0gdGhpcy5fZ2V0VHJpY2tsZUVuZCgpXG4gICAgdGhpcy5fc29ja2V0SGVscGVyLmNsZWFyUmV0cnkoKVxuICAgIHRoaXMuX3NvY2tldEhlbHBlci5zZXRVcChzb2NrZXR1cmwsIHNvY2tldFByb21pc2UpXG5cbi8vIDAuIEVzdGFibGlzaCBzb2NrZXQgY29ubmVjdGlvbi5cbiAgICBzb2NrZXRQcm9taXNlLnByb21pc2Vcbi8vIDEuIFdhaXQgZm9yIHN0cmVhbSBhdHRhY2hcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHRoaXMudHJpZ2dlcihuZXcgUHVibGlzaGVyRXZlbnQoUHVibGlzaGVyRXZlbnRUeXBlcy5DT05ORUNUX1NVQ0NFU1MsIHRoaXMpKVxuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0TWVkaWFTdHJlYW0oKVxuICAgICAgfSlcbi8vIDIuIFJlcXVlc3QgYXZhaWxhYmxlIHN0cmVhbSB0byBwdWJsaXNoIG9uXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9yZXF1ZXN0QXZhaWxhYmlsaXR5KHRoaXMuX29wdGlvbnMuc3RyZWFtTmFtZSwgdGhpcy5fb3B0aW9ucy5zdHJlYW1UeXBlKVxuICAgICAgfSlcbi8vIDMuIENyZWF0ZSBQZWVyIENvbm5lY3Rpb25cbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NyZWF0ZVBlZXJDb25uZWN0aW9uKHRoaXMuX29wdGlvbnMuaWNlU2VydmVycylcbiAgICAgIH0pXG4vLyA0LiBNYWtlIE9mZmVyIG9uIFBlZXIgQ29ubmVjdGlvblxuICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgIGNvbm5lY3Rpb24uYWRkU3RyZWFtKHRoaXMuX21lZGlhU3RyZWFtKVxuICAgICAgICB0aGlzLnRyaWdnZXIobmV3IFB1Ymxpc2hlckV2ZW50KFJUQ1B1Ymxpc2hlckV2ZW50VHlwZXMuUEVFUl9DT05ORUNUSU9OX0FWQUlMQUJMRSwgdGhpcywgY29ubmVjdGlvbikpXG4gICAgICAgIHJldHVybiB0aGlzLl9jcmVhdGVPZmZlcih0aGlzLl9vcHRpb25zLmJhbmR3aWR0aClcbiAgICAgIH0pXG4vLyA1LiBTZW5kIE9mZmVyXG4gICAgICAudGhlbihzZXNzaW9uRGVzY3JpcHRpb24gPT4ge1xuICAgICAgICB0aGlzLnRyaWdnZXIobmV3IFB1Ymxpc2hlckV2ZW50KFJUQ1B1Ymxpc2hlckV2ZW50VHlwZXMuT0ZGRVJfU1RBUlQsIHRoaXMsIHNlc3Npb25EZXNjcmlwdGlvbikpXG4gICAgICAgIHJldHVybiB0aGlzLl9zZW5kT2ZmZXIoc2Vzc2lvbkRlc2NyaXB0aW9uLCB0aGlzLl9vcHRpb25zLnN0cmVhbU5hbWUsIHRoaXMuX29wdGlvbnMuaWNlVHJhbnNwb3J0KVxuICAgICAgfSlcbi8vIDYuIFNldCB0aGUgc2Vzc2lvbiBkZXNjcmlwdGlvbiByZW1vdGVseVxuICAgICAgLnRoZW4oc2RwID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NldFJlbW90ZURlc2NyaXB0aW9uKHNkcC5zZHApXG4gICAgICB9KVxuLy8gNy4gV2FpdCB1bnRpbCBpY2UgdHJpY2tsZSBlbmRcbiAgICAgIC50aGVuKHNkcCA9PiB7XG4gICAgICAgIHRoaXMudHJpZ2dlcihuZXcgUHVibGlzaGVyRXZlbnQoUlRDUHVibGlzaGVyRXZlbnRUeXBlcy5PRkZFUl9FTkQsIHRoaXMsIHNkcCkpXG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRUcmlja2xlRW5kKCkucHJvbWlzZVxuICAgICAgfSlcbi8vIDguIFJlcXVlc3QgdG8gcHVibGlzaCBzdHJlYW1cbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgdGhpcy50cmlnZ2VyKG5ldyBQdWJsaXNoZXJFdmVudChSVENQdWJsaXNoZXJFdmVudFR5cGVzLklDRV9UUklDS0xFX0NPTVBMRVRFLCB0aGlzKSlcbiAgICAgICAgcmV0dXJuIHRoaXMuX3JlcXVlc3RQdWJsaXNoKHRoaXMuX29wdGlvbnMuc3RyZWFtTmFtZSwgdGhpcy5fb3B0aW9ucy5zdHJlYW1Nb2RlKVxuICAgICAgfSlcbi8vIDkuIFJlc3VsdHMgaW4gc29ja2V0IG1lc3NhZ2Ugb2YgcHVibGlzaCAoc2VlIDpvblB1Ymxpc2hTdGF0dXMpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGVudmlyb25tZW50LmFkZE9yaWVudGF0aW9uQ2hhbmdlSGFuZGxlcih0aGlzLl9vbk9yaWVudGF0aW9uQ2hhbmdlKVxuICAgICAgICBwLnJlc29sdmUodGhpcylcbiAgICAgICAgdGhpcy50cmlnZ2VyKG5ldyBQdWJsaXNoZXJFdmVudChQdWJsaXNoZXJFdmVudFR5cGVzLlBVQkxJU0hfU1RBUlQsIHRoaXMpKVxuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgZW52aXJvbm1lbnQucmVtb3ZlT3JpZW50YXRpb25DaGFuZ2VIYW5kbGVyKHRoaXMuX29uT3JpZW50YXRpb25DaGFuZ2UpXG4gICAgICAgIHAucmVqZWN0KGVycm9yKVxuICAgICAgICB0aGlzLnRyaWdnZXIobmV3IFB1Ymxpc2hlckV2ZW50KFB1Ymxpc2hlckV2ZW50VHlwZXMuQ09OTkVDVF9GQUlMVVJFLCB0aGlzLCBlcnJvcikpXG4gICAgICB9KVxuICAgIHJldHVybiBwLmhhc093blByb3BlcnR5KCdwcm9taXNlJykgPyBwLnByb21pc2UgOiBwXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBzdG9wIGEgYnJvYWRjYXN0LlxuICAgKiBUaGUgcmV0dXJuZWQgYFByb21pc2VgIHdpbGwgZWl0aGVyIHJlc29sdmUgb3IgcmVqZWN0IG9uIHN1Y2Nlc3NmdWwgc3RvcCBvZiBicm9hZGNhc3QuXG4gICAqXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqL1xuICB1bnB1Ymxpc2ggKCkge1xuICAgIGRlYnVnKE5BTUUsICdbdW5wdWJsaXNoXScpXG4gICAgY29uc3QgY2xlYXJIZWxwZXJzID0gKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuX3NvY2tldEhlbHBlcikge1xuICAgICAgICBkZWJ1ZyhOQU1FLCAnW3VucHVibGlzaDp0ZWFyZG93bl0nKVxuICAgICAgICB0aGlzLl9zb2NrZXRIZWxwZXIudGVhckRvd24oKVxuICAgICAgfVxuICAgICAgaWYgKHRoaXMuX3BlZXJIZWxwZXIpIHtcbiAgICAgICAgdGhpcy5fcGVlckhlbHBlci50ZWFyRG93bigpXG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMuX2F2YWlsYWJsZUZ1dHVyZSA9IHVuZGVmaW5lZFxuICAgIHRoaXMuX3BlZXJGdXR1cmUgPSB1bmRlZmluZWRcbiAgICB0aGlzLl9vZmZlckZ1dHVyZSA9IHVuZGVmaW5lZFxuICAgIHRoaXMuX3NlbmRPZmZlckZ1dHVyZSA9IHVuZGVmaW5lZFxuICAgIHRoaXMuX3RyaWNrbGVFbmRGdXR1cmUgPSB1bmRlZmluZWRcbiAgICB0aGlzLl9wdWJsaXNoRnV0dXJlID0gdW5kZWZpbmVkXG4gICAgY29uc3QgZiA9IHRoaXMuX3JlcXVlc3RVbnB1Ymxpc2godGhpcy5fb3B0aW9ucy5zdHJlYW1OYW1lKVxuICAgIGYudGhlbigoKSA9PiB7XG4gICAgICB0aGlzLl91bnB1Ymxpc2hGdXR1cmUgPSB1bmRlZmluZWRcbiAgICAgIC8vICAgICAgdGhpcy5fbWVkaWFTdHJlYW0gPSB1bmRlZmluZWRcbiAgICAgIGNsZWFySGVscGVycygpXG4gICAgICB0aGlzLnRyaWdnZXIobmV3IFB1Ymxpc2hlckV2ZW50KFB1Ymxpc2hlckV2ZW50VHlwZXMuVU5QVUJMSVNIX1NVQ0NFU1MsIHRoaXMpKVxuICAgIH0pXG4gICAgIGVudmlyb25tZW50LnJlbW92ZU9yaWVudGF0aW9uQ2hhbmdlSGFuZGxlcih0aGlzLl9vbk9yaWVudGF0aW9uQ2hhbmdlKVxuICAgIHJldHVybiBmXG4gIH1cblxuICAvKipcbiAgICogRGVwcmVjYXRlZC4gVXNlIGBtdXRlQXVkaW9gLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgbXV0ZSAoKSB7XG4gICAgLy8gYmFja3dhcmQgY29tYXRpYmlsaXR5IC0gdG8gYmUgZGVwcmVjYXRlZC5cbiAgICB0aGlzLm11dGVBdWRpbygpXG4gIH1cblxuICAvKipcbiAgICogRGVwcmVjYXRlZC4gVXNlIGB1bm11dGVBdWRpb2AuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICB1bm11dGUgKCkge1xuICAgIC8vIGJhY2t3YXJkIGNvbWF0aWJpbGl0eSAtIHRvIGJlIGRlcHJlY2F0ZWQuXG4gICAgdGhpcy51bm11dGVBdWRpbygpXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBtdXRlIHRoZSBhdWRpbyBvZiB0aGUgYnJvYWRjYXN0LlxuICAgKiBDYW4gb25seSBiZSBjYWxsZWQgb25jZSB0aGUgYnJvYWRjYXN0IGhhcyBiZWd1bi5cbiAgICovXG4gIG11dGVBdWRpbyAoKSB7XG4gICAgdGhpcy5fc29ja2V0SGVscGVyLnBvc3Qoe1xuICAgICAgbXV0ZToge1xuICAgICAgICBtdXRlQXVkaW86IHRydWVcbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gdW5tdXRlIHRoZSBhdWRpbyBvZiBhIGJyb2FkY2FzdCB0aGF0IGhhcyBiZWVuIHByZXZpb3VzbHkgbXV0ZWQuXG4gICAqL1xuICB1bm11dGVBdWRpbyAoKSB7XG4gICAgdGhpcy5fc29ja2V0SGVscGVyLnBvc3Qoe1xuICAgICAgbXV0ZToge1xuICAgICAgICBtdXRlQXVkaW86IGZhbHNlXG4gICAgICB9XG4gICAgfSlcbiAgfVxuXG4gIC8qKiBSZXF1ZXN0IHRvIG11dGUgKG5vdCBzZW5kKSB0aGUgdmlkZW8gb2YgdGhlIGJyb2FkY2FzdC5cbiAgICogQ2FuIG9ubHkgYmUgY2FsbGVkIG9uY2UgdGhlIGJyb2FkY2FzdCBoYXMgYmVndW4uXG4gICAqL1xuICBtdXRlVmlkZW8gKCkge1xuICAgIHRoaXMuX3NvY2tldEhlbHBlci5wb3N0KHtcbiAgICAgIG11dGU6IHtcbiAgICAgICAgbXV0ZVZpZGVvOiB0cnVlXG4gICAgICB9XG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIHVubXV0ZSAocmVzdW1lIHNlbmRpbmcpIHRoZSB2aWRlbyBvZiBhIHByZXZpb3VzbHkgdmlkZW8tbXV0ZWQgYnJvYWRjYXN0LlxuICAgKi9cbiAgdW5tdXRlVmlkZW8gKCkge1xuICAgIHRoaXMuX3NvY2tldEhlbHBlci5wb3N0KHtcbiAgICAgIG11dGU6IHtcbiAgICAgICAgbXV0ZVZpZGVvOiBmYWxzZVxuICAgICAgfVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBzZW5kIGEgbWVzc2FnZSB0byBhbGwgc3Vic2NyaWJlcnMuXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2ROYW1lXG4gICAqICAgICAgICBUaGUgbWV0aG9kIG5hbWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBtZXNzYWdlIHRvIGJlIGFjY2VwdGVkIGJ5IGFsbCBzdWJzY3JpYmVycy5cbiAgICogQHBhcmFtIHtPYmplY3R9IGRhdGFcbiAgICogICAgICAgIFRoZSBkYXRhIG9iamVjdCB0byBzZW5kIGFzc29jaWF0ZWQgd2l0aCB0aGUgbWV0aG9kIG5hbWUuXG4gICAqL1xuICBzZW5kIChtZXRob2ROYW1lLCBkYXRhKSB7XG4gICAgdGhpcy5fc29ja2V0SGVscGVyLnBvc3Qoe1xuICAgICAgc2VuZDoge1xuICAgICAgICBtZXRob2Q6IG1ldGhvZE5hbWUsXG4gICAgICAgIGRhdGE6ICh0eXBlb2YgZGF0YSA9PT0gJ3N0cmluZycpID8gSlNPTi5wYXJzZShkYXRhKSA6IGRhdGFcbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gaW52b2tlIGEgbWV0aG9kIG9uIHRoZSBBcHBsaWNhdGlvbiBBZGFwdGVyIHJlbGF0ZWQgdG8gdGhlIGBhcHBgIGNvbmZpZyBzZXR0aW5nLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWV0aG9kTmFtZVxuICAgKiAgICAgICAgVGhlIG5hbWUgb2YgdGhlIG1ldGhvZCB0byBpbnZva2Ugb24gdGh3IEFwcGxpY2F0aW9uIEFkYXB0ZXJcbiAgICogQHBhcmFtIHtBcnJheX0gYXJnc1xuICAgKiAgICAgICAgVGhlIG9yZGVyZWQgbGlzdCBvZiBhcmd1bWVudHMgdG8gaW52b2tlIG9uIHRoZSBtZXRob2QuIERvIG5vdCBwcm92aWRlIGFueXRoaW5nIGlmIHRoZSBtZXRob2QgdGFrZXMgbm8gYXJndW1lbnRzLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKi9cbiAgY2FsbFNlcnZlciAobWV0aG9kTmFtZSwgYXJncykge1xuICAgIHJldHVybiB0aGlzLl9zb2NrZXRIZWxwZXIucG9zdEFzeW5jKHtcbiAgICAgIGNhbGxBZGFwdGVyOiB7XG4gICAgICAgIG1ldGhvZDogbWV0aG9kTmFtZSxcbiAgICAgICAgYXJndW1lbnRzOiBhcmdzXG4gICAgICB9XG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBFdmVudCBoYW5kbGVyIGZvciBhdmFpbGFiaWxpdHkgb2Ygc3RyZWFtIG9uIHJlcXVlc3Qgb3ZlciB0aGUgc29ja2V0LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgb25TdHJlYW1BdmFpbGFibGUgKHJlY2VpcHQpIHtcbiAgICBkZWJ1ZygnW29uc3RyZWFtYXZhaWxhYmxlXTogJyArIEpTT04uc3RyaW5naWZ5KHJlY2VpcHQsIG51bGwsIDIpKVxuICAgIHRoaXMuX2F2YWlsYWJsZUZ1dHVyZSA9IEZ1dHVyZS5jcmVhdGVJZk5vdEV4aXN0KHRoaXMuX2F2YWlsYWJsZUZ1dHVyZSlcbiAgICB0aGlzLl9hdmFpbGFibGVGdXR1cmUucmVqZWN0KGBTdHJlYW0gd2l0aCBuYW1lICR7dGhpcy5fb3B0aW9ucy5zdHJlYW1OYW1lfSBhbHJlYWR5IGhhcyBhIGJyb2FkY2FzdCBzZXNzaW9uLmApXG4gICAgdGhpcy50cmlnZ2VyKG5ldyBQdWJsaXNoZXJFdmVudChQdWJsaXNoZXJFdmVudFR5cGVzLlBVQkxJU0hfSU5WQUxJRF9OQU1FLCB0aGlzKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBFdmVudCBoYW5kbGVyIGZvciB1bmF2YWlsYWJpbGl0eSBvZiBzdHJlYW0gb24gcmVxdWVzdCBvdmVyIHRoZSBzb2NrZXQuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBvblN0cmVhbVVuYXZhaWxhYmxlIChyZWNlaXB0KSB7XG4gICAgLy8gQmVpbmcgdW5hdmFpbGFibGUsIGlzIGEgZ29vZCB0aGluZyBmb3IgYWxsb3dpbmcgdG8gcHVibGlzaCB1c2luZyBgb3B0aW9ucy5zdHJlYW1OYW1lYFxuICAgIGRlYnVnKGBTdHJlYW0gJHt0aGlzLl9vcHRpb25zLnN0cmVhbU5hbWV9IGRvZXMgbm90IGV4aXN0LmApXG4gICAgZGVidWcoJ1tvbnN0cmVhbXVuYXZhaWxhYmxlXTogJyArIEpTT04uc3RyaW5naWZ5KHJlY2VpcHQsIG51bGwsIDIpKVxuICAgIHRoaXMuX2F2YWlsYWJsZUZ1dHVyZSA9IEZ1dHVyZS5jcmVhdGVJZk5vdEV4aXN0KHRoaXMuX2F2YWlsYWJsZUZ1dHVyZSlcbiAgICB0aGlzLl9hdmFpbGFibGVGdXR1cmUucmVzb2x2ZSh0cnVlKVxuICB9XG5cbiAgLyoqXG4gICAqIEV2ZW50IGhhbmRsZXIgZm9yIFdlYlNvY2tldCBlcnJvcnMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBvblNvY2tldE1lc3NhZ2VFcnJvciAobWVzc2FnZSwgZGV0YWlsID0gbnVsbCkge1xuICAgIGVycm9yKGBFcnJvciBpbiBzdHJlYW0gcHVibGlzaDogJHttZXNzYWdlfS5cXG5bT3B0aW9uYWwgZGV0YWlsXTogJHtkZXRhaWx9YClcbiAgICBpZiAodGhpcy5fcHVibGlzaEZ1dHVyZSkge1xuICAgICAgdGhpcy50cmlnZ2VyKG5ldyBQdWJsaXNoZXJFdmVudChQdWJsaXNoZXJFdmVudFR5cGVzLlBVQkxJU0hfRkFJTCwgdGhpcykpXG4gICAgICB0aGlzLl9wdWJsaXNoRnV0dXJlLnJlamVjdChtZXNzYWdlKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBFdmVudCBoYW5kbGVyIGZvciBjbG9zZSBvZiBXZWJTb2NrZXQuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBvblNvY2tldENsb3NlIChjbG9zZUV2ZW50KSB7XG4gICAgZGVidWcoTkFNRSwgJ1tvbnNvY2tldGNsb3NlXScpXG4gICAgaWYgKHRoaXMuX3BlZXJIZWxwZXIpIHtcbiAgICAgIHRoaXMuX3BlZXJIZWxwZXIudGVhckRvd24oKVxuICAgIH1cbiAgICB0aGlzLnRyaWdnZXIobmV3IFB1Ymxpc2hlckV2ZW50KFB1Ymxpc2hlckV2ZW50VHlwZXMuQ09OTkVDVElPTl9DTE9TRUQsIHRoaXMsIGNsb3NlRXZlbnQpKVxuICB9XG5cbiAgLyoqXG4gICAqIEV2ZW50IGhhbmRsZXIgZm9yIGNsb3NlIG9mIFBlZXIgQ29ubmVjdGlvbi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIG9uUGVlckNvbm5lY3Rpb25DbG9zZSAoZXZlbnQpIHtcbiAgICBkZWJ1ZyhOQU1FLCAnW29ucGVlcmNvbm5lY3Rpb25jbG9zZV0nKVxuICAgIGlmICh0aGlzLl9zb2NrZXRIZWxwZXIpIHtcbiAgICAgIGRlYnVnKE5BTUUsICdbb25wZWVyY29ubmVjdGlvbmNsb3NlOnRlYXJkb3duXScpXG4gICAgICB0aGlzLl9zb2NrZXRIZWxwZXIudGVhckRvd24oKVxuICAgIH1cbiAgICB0aGlzLm9uU29ja2V0Q2xvc2UoZXZlbnQpXG4gIH1cblxuICAvKipcbiAgICogRXZlbnQgaGFuZGxlciBmb3Igc3VjY2VzcyBvZiBTRFAgb2ZmZXIgb3ZlciBXZWJTb2NrZXQuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBvblNEUFN1Y2Nlc3MgKHJlY2VpcHQpIHtcbiAgICBsZXQgaW5mbyA9IHJlY2VpcHQgPyAnOiAnICsgSlNPTi5zdHJpbmdpZnkocmVjZWlwdCwgbnVsbCwgMikgOiAnJ1xuICAgIGRlYnVnKGBbb25zZHBzdWNjZXNzXSR7aW5mb31gKVxuICB9XG5cbiAgLyoqXG4gICAqIEV2ZW50IGhhbmRsZXIgZm9yIGVycm9yIGluIFNEUCBvZmZlciBvdmVyIFdlYlNvY2tldC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIG9uU0RQRXJyb3IgKHJlY2VpcHQpIHtcbiAgICB0aGlzLnRyaWdnZXIobmV3IFB1Ymxpc2hlckV2ZW50KFB1Ymxpc2hlckV2ZW50VHlwZXMuUFVCTElTSF9GQUlMLCB0aGlzKSlcbiAgICBsZXQgZXJyb3IgPSByZWNlaXB0ID8gJzogJyArIEpTT04uc3RyaW5naWZ5KHJlY2VpcHQsIG51bGwsIDIpIDogJydcbiAgICBlcnJvcihgW29uc2RwZXJyb3JdJHtlcnJvcn1gKVxuICB9XG5cbiAgLyoqXG4gICAqIEV2ZW50IGhhbmRsZXIgZm9yIHN1Y2Nlc3MgaW4gU0RQIGFuc3dlciBvdmVyIFdlYlNvY2tldC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIG9uU0RQQW5zd2VyIChzZHApIHtcbiAgICBkZWJ1ZygnW3NkcGFuc3dlcl06OiAnICsgSlNPTi5zdHJpbmdpZnkoc2RwLCBudWxsLCAyKSlcbiAgICB0aGlzLl9zZW5kT2ZmZXJGdXR1cmUgPSBGdXR1cmUuY3JlYXRlSWZOb3RFeGlzdCh0aGlzLl9zZW5kT2ZmZXJGdXR1cmUpXG4gICAgdGhpcy5fc2VuZE9mZmVyRnV0dXJlLnJlc29sdmUoc2RwKVxuICB9XG5cbiAgLyoqXG4gICAqIEV2ZW50IGhhbmRsZXIgZm9yIHJlcXVlc3QgdG8gYWRkIElDRSBjYW5kaWRhdGUgb24gUGVlciBDb25uZWN0aW9uIGluc3RhbmNlLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgb25BZGRJY2VDYW5kaWRhdGUgKGNhbmRpZGF0ZSkge1xuICAgIGRlYnVnKCdbYWRkaWNlY2FuZGlkYXRlXScpXG4gICAgdGhpcy5fcGVlckhlbHBlci5hZGRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICBkZWJ1ZygnW2FkZGljZWNhbmRpZGF0ZTpzdWNjZXNzXScpXG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgIHdhcm4oYFthZGRpY2VjYW5kaWRhdGU6ZXJyb3JdIC0gJHtlcnJ9YClcbiAgICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogRXZlbnQgaGFuZGxlciBmb3IgcmVjZWlwdCBhbmQgcmVxdWVzdCB0byBzZW5kIElDRSBjYW5kaWRhdGUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBvbkljZUNhbmRpZGF0ZSAoY2FuZGlkYXRlKSB7XG4gICAgZGVidWcoJ1tpY2VjYW5kaWRhdGV0cmlja2xlXScpXG4gICAgdGhpcy5fc2VuZENhbmRpZGF0ZShjYW5kaWRhdGUsIHRoaXMuX29wdGlvbnMuc3RyZWFtTmFtZSlcbiAgfVxuXG4gIC8qKlxuICAgKiBFdmVudCBoYW5kbGVyIGZvciBlbmQgb2YgSUNFIHRyaWNrbGUgbmVnb3RpYXRpb24uXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBvbkljZUNhbmRpZGF0ZVRyaWNrbGVFbmQgKCkge1xuICAgIGRlYnVnKCdbaWNlY2FuZGlkYXRldHJpY2tsZTplbmRdJylcbiAgfVxuXG4gIC8qKlxuICAgKiBFdmVudCBoYW5kbGVyIGZvciByZWNlaXB0IG9mIGVtcHR5IGNhbmRpZGF0ZSBkdXJpbmcgSUNFIG5lZ290aWF0aW9uLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgb25FbXB0eUNhbmRpZGF0ZSAoKSB7XG4gICAgZGVidWcoJ1tpY2VjYW5kaWRhdGV0cmlja2xlOmVtcHR5XScpXG4gICAgdGhpcy50cmlnZ2VyKG5ldyBQdWJsaXNoZXJFdmVudChSVENQdWJsaXNoZXJFdmVudFR5cGVzLlBFRVJfQ0FORElEQVRFX0VORCkpXG4gIH1cblxuICAvKipcbiAgICogRXZlbnQgaGFuZGxlciBmb3IgY29tcGxldGlvbiBvZiBwZWVyIGljZSBjYW5kaWRhdGUgZ2F0aGVyaW5nLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgb25QZWVyR2F0aGVyaW5nQ29tcGxldGUgKCkge1xuICAgIGRlYnVnKCdbaWNlY2FuZGlkYXRlZ2F0aGVyaW5nOmVuZF0nKVxuICAgIGlmICh0aGlzLl9zb2NrZXRIZWxwZXIpIHtcbiAgICAgIHRoaXMuX3NvY2tldEhlbHBlci5wb3N0RW5kT2ZDYW5kaWRhdGVzKHRoaXMuX29wdGlvbnMuc3RyZWFtTmFtZSlcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRXZlbnQgaGFuZGxlciBmb3IgZW5kIG9mIElDRSBjYW5kaWRhdGUgbm90aWZpY2F0aW9uIG92ZXIgV2ViU29ja2V0LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgb25Tb2NrZXRJY2VDYW5kaWRhdGVFbmQgKCkge1xuICAgIGRlYnVnKCdbc29ja2V0aWNlY2FuZGlkYXRlOmVuZF0nKVxuICAgIHRoaXMuX2dldFRyaWNrbGVFbmQoKS5yZXNvbHZlKClcbiAgICAvLyB0aGlzLl90cmlja2xlRW5kRnV0dXJlID0gdW5kZWZpbmVkXG4gIH1cblxuICAvKipcbiAgICogUHVibGlzaGVyIHN0YXR1cyBldmVudCBoYW5kbGVyIGZvciBzdGFydCBhbmQgc3RvcCBvZiB0aGlzIFB1Ymxpc2hlciBpbnN0YW5jZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIG9uUHVibGlzaGVyU3RhdHVzIChzdGF0dXMpIHtcbiAgICBkZWJ1ZygnW3B1Ymxpc2hlcnN0YXR1c10gLSAnICsgSlNPTi5zdHJpbmdpZnkoc3RhdHVzLCBudWxsLCAyKSlcbiAgICBjb25zdCBzdG9wUmVzdWx0ID0gcHViU3RvcFJlZ2V4LmV4ZWMoc3RhdHVzLm1lc3NhZ2UpXG4gICAgY29uc3Qgc3RhcnRSZXN1bHQgPSBwdWJTdGFydFJlZ2V4LmV4ZWMoc3RhdHVzLm1lc3NhZ2UpXG4gICAgaWYgKHN0b3BSZXN1bHQgJiYgc3RvcFJlc3VsdFsxXSA9PT0gdGhpcy5fb3B0aW9ucy5zdHJlYW1OYW1lKSB7XG4gICAgICB0aGlzLl91bnB1Ymxpc2hGdXR1cmUucmVzb2x2ZSgpXG4gICAgfSBlbHNlIGlmIChzdGFydFJlc3VsdCAmJiBzdGFydFJlc3VsdFsxXSA9PT0gdGhpcy5fb3B0aW9ucy5zdHJlYW1OYW1lKSB7XG4gICAgICB0aGlzLl9wdWJsaXNoRnV0dXJlLnJlc29sdmUoKVxuICAgIH0gZWxzZSB7XG4gICAgICB3YXJuKCdQdWJsaXNoZXIgc3RhdHVzIHJlY2VpdmVkLCBidXQgY291bGQgbm90IGhhbmRsZS4nKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBIZWxwZXIgbWV0aG9kIHRvIG92ZXJsYXkgb3B0aW9ucyBvdmVyIGN1cnJlbnQgY29uZmlndXJhdGlvbi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIG92ZXJsYXlPcHRpb25zIChuZXdPcHRpb25zKSB7XG4gICAgdGhpcy5fb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24odGhpcy5fb3B0aW9ucywgbmV3T3B0aW9ucyk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY3VycmVudCBXZWJTb2NrZXQgY29ubmVjdGlvbiBoZWxwZXIgaWYgZXN0YWJsaXNoZWQuXG4gICAqIFVzZWQgaW4gU2hhcmVkT2JqZWN0IGNvbW11bmljYXRpb24uXG4gICAqXG4gICAqIEByZXR1cm4ge1B1Ymxpc2hlclNvY2tldEhlbHBlcn1cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIGdldENvbm5lY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLl9zb2NrZXRIZWxwZXJcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IFJUQ1BlZXJDb25uZWN0aW9uIGhlbHBlciBpZiBlc3RhYmxpc2hlZC5cbiAgICpcbiAgICogQHJldHVybiB7UlRDUGVlckNvbm5lY3Rpb259XG4gICAqL1xuICBnZXRQZWVyQ29ubmVjdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3BlZXJIZWxwZXIgPyB0aGlzLl9wZWVySGVscGVyLmNvbm5lY3Rpb24gOiB1bmRlZmluZWRcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBgTWVkaWFTdHJlYW1gIGluc3RhbmNlIGlmIGdlbmVyYXRlZCB0aHJvdWdoIGBnZXRVc2VyTWVkaWFgIGFuZCBleGlzdHMgZm9yIGJyb2FkY2FzdC5cbiAgICpcbiAgICogQHJldHVybiB7TWVkaWFTdHJlYW19XG4gICAqL1xuICBnZXRNZWRpYVN0cmVhbSAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX21lZGlhU3RyZWFtXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgaW5pdGlhbGl6YXRpb24gY29uZmlndXJhdGlvbiB1c2VkIGluIGBpbml0KClgLlxuICAgKlxuICAgKiBAcmV0dXJuIHtPYmplY3R9XG4gICAqL1xuICBnZXRPcHRpb25zICgpIHtcbiAgICByZXR1cm4gdGhpcy5fb3B0aW9uc1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHR5cGUgb2YgaW1wbGVtZW50YXRpb246IGBSVENgLlxuICAgKlxuICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAqL1xuICBnZXRUeXBlICgpIHtcbiAgICByZXR1cm4gUHVibGlzaFR5cGVzLlJUQy50b1VwcGVyQ2FzZSgpXG4gIH1cblxufVxuXG5leHBvcnQgZGVmYXVsdCBSVENQdWJsaXNoZXJcblxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2pzL3B1Ymxpc2hlci9yZWQ1cHJvLXJ0Yy5qcyIsIid1c2Ugc3RyaWN0J1xuXG5pbXBvcnQgRXZlbnRFbWl0dGVyIGZyb20gJy4uL2NvcmUvZXZlbnQtZW1pdHRlcidcbmltcG9ydCBlbnZpcm9ubWVudCBmcm9tICcuLi9lbnYvYnJvd3NlcidcbmltcG9ydCBQdWJsaXNoZXJTb3VyY2VIYW5kbGVyIGZyb20gJy4vcHViLXNvdXJjZS1oYW5kbGVyJ1xuaW1wb3J0IFB1Ymxpc2hWaWV3IGZyb20gJy4uL3ZpZXcvcHVibGlzaCdcbmltcG9ydCB7IFB1Ymxpc2hlckV2ZW50IH0gZnJvbSAnLi4vZXZlbnQnXG5pbXBvcnQgeyBEZWZlcnJlZFByb21pc2UgfSBmcm9tICcuLi91dGlsL3Byb21pc2UnXG5pbXBvcnQgeyBQdWJsaXNoVHlwZXMgfSBmcm9tICcuLi9lbnVtL3B1Ymxpc2gnXG5pbXBvcnQgeyBQdWJsaXNoZXJFdmVudFR5cGVzLCBSVE1QUHVibGlzaGVyRXZlbnRUeXBlcyB9IGZyb20gJy4uL2V2ZW50J1xuaW1wb3J0IHsgUlRNUE1lZGlhQ29uc3RyYWludCB9IGZyb20gJy4vY29uc3RyYWludCdcbmltcG9ydCB7IGRlYnVnLCBlcnJvciB9IGZyb20gJy4uL2xvZydcblxuY29uc3QgTkFNRSA9ICdSVE1QUHVibGlzaGVyJ1xuY29uc3QgZGVmYXVsdE9wdGlvbnMgPSB7XG4gIHByb3RvY29sOiAncnRtcCcsXG4gIHBvcnQ6IDE5MzUsXG4gIHN0cmVhbU1vZGU6ICdsaXZlJyxcbiAgbWVkaWFFbGVtZW50SWQ6ICdyZWQ1cHJvLXB1Ymxpc2hlcicsXG4gIGVtYmVkV2lkdGg6ICcxMDAlJywgLy8gRE9NIGRpc3BsYXkgc3R5bGVcbiAgZW1iZWRIZWlnaHQ6ICcxMDAlJywgLy8gRE9NIGRpc3BsYXkgc3R5bGVcbiAgbWluRmxhc2hWZXJzaW9uOiAnMTAuMC4wJyxcbiAgc3dmOiAnbGliL3JlZDVwcm8vcmVkNXByby1wdWJsaXNoZXIuc3dmJyxcbiAgc3dmb2JqZWN0VVJMOiAnbGliL3N3Zm9iamVjdC9zd2ZvYmplY3QuanMnLFxuICBwcm9kdWN0SW5zdGFsbFVSTDogJ2xpYi9zd2ZvYmplY3QvcGxheWVyUHJvZHVjdEluc3RhbGwuc3dmJyxcbiAgbWVkaWFDb25zdHJhaW50czogbmV3IFJUTVBNZWRpYUNvbnN0cmFpbnQoKVxufVxuXG4vKipcbiAqIE1haW4gZW50cnkgZm9yIEZsYXNoLWJhc2VkIFB1Ymxpc2hlci5cbiAqXG4gKiBAZXh0ZW5kcyBFdmVudEVtaXR0ZXJcbiAqL1xuY2xhc3MgUlRNUFB1Ymxpc2hlciBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG5cbiAgY29uc3RydWN0b3IgKCkge1xuICAgIHN1cGVyKClcbiAgICB0aGlzLl9vcHRpb25zID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fdmlldyA9IHVuZGVmaW5lZFxuICAgIHRoaXMuX3NvdXJjZUhhbmRsZXIgPSB1bmRlZmluZWRcbiAgICB0aGlzLl9lbGVtZW50SWQgPSB1bmRlZmluZWRcbiAgICB0aGlzLl9jb25uZWN0RnV0dXJlID0gdW5kZWZpbmVkXG4gIH1cblxuICAvKipcbiAgICogU3RpbGwgaW4gdXNlIGZvciBhc3NpZ25pbmcgZG9jdW1lbnQgZWxlbWVudCB2aWV3IG1hbmFnZW1lbnQgdG8gdGhpcyBpbnN0YW5jZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9zZXRWaWV3SWZOb3RFeGlzdCAoY3VycmVudFZpZXcsIG1lZGlhRWxlbWVudElkID0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAodHlwZW9mIGN1cnJlbnRWaWV3ID09PSAndW5kZWZpbmVkJyAmJiBtZWRpYUVsZW1lbnRJZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGxldCB2aWV3ID0gbmV3IFB1Ymxpc2hWaWV3KG1lZGlhRWxlbWVudElkKVxuICAgICAgICB2aWV3LmF0dGFjaFB1Ymxpc2hlcih0aGlzKVxuICAgICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFN0aWxsIGluIHVzZSBmb3IgYXNzaWduaW5nIGRvY3VtZW50IGVsZW1lbnQgdmlldyBtYW5hZ2VtZW50IHRvIHRoaXMgaW5zdGFuY2UuXG4gICAqIEFQSSBkZXByZWNhdGVkIGluIDQuMC4wLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgc2V0VmlldyAodmlldywgZWxlbWVudElkKSB7XG4gICAgdGhpcy5fdmlldyA9IHZpZXdcbiAgICB0aGlzLl9lbGVtZW50SWQgPSBlbGVtZW50SWRcbiAgICBpZiAodGhpcy5fc291cmNlSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLl9zb3VyY2VIYW5kbGVyLmRpc2Nvbm5lY3QoKVxuICAgICAgdGhpcy5fc291cmNlSGFuZGxlciA9IHVuZGVmaW5lZFxuICAgIH1cbiAgICBpZiAodGhpcy5fdmlldykge1xuICAgICAgdGhpcy5fc291cmNlSGFuZGxlciA9IG5ldyBQdWJsaXNoZXJTb3VyY2VIYW5kbGVyKHRoaXMuX3ZpZXcudmlldywgdGhpcy5nZXRUeXBlKCkpXG4gICAgfVxuICAgIGlmICh0aGlzLl9vcHRpb25zICYmIHRoaXMuX3NvdXJjZUhhbmRsZXIpIHtcbiAgICAgIHRoaXMuX3NvdXJjZUhhbmRsZXIuYWRkU291cmNlKHRoaXMuX2VsZW1lbnRJZCwgdGhpcy5fb3B0aW9ucylcbiAgICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgICAgZXJyb3IoTkFNRSwgYENvdWxkIG5vdCBlc3RhYmxpc2ggcHJvcGVyIFJUTVAgcHVibGlzaGVyOiAke2Vycn1gKVxuICAgICAgICAgIHRoaXMudHJpZ2dlcihuZXcgUHVibGlzaGVyRXZlbnQoUlRNUFB1Ymxpc2hlckV2ZW50VHlwZXMuRU1CRURfRkFJTFVSRSwgdGhpcykpXG4gICAgICAgIH0pXG4gICAgfVxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICAvKipcbiAgICogRGVmaW5lIGEgd2luZG93IGdsb2JhbCBjYWxsYmFjayB1c2VkIGJ5IEZsYXNoIHB1Ymxpc2hlciB0byByZWNvZ25pemUgZW1iZWQgY29tcGxldGUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfc2V0VXBDb25uZWN0Q2FsbGJhY2sgKHByb21pc2UpIHtcbiAgICB3aW5kb3cuc2V0QWN0aXZlSWQgPSAoc3VjY2Vzc0lkKSA9PiB7XG4gICAgICAvLyBzdWNjZXNzSWQgPT09IF9vcHRpb25zLnN0cmVhbU5hbWVcbiAgICAgIGRlYnVnKE5BTUUsIGBFbWJlZCBhbmQgY29ubmVjdCgpIGNvbXBsZXRlIGZvciBwdWJsaXNoZXIgc3dmLiBzdWNjZXNzSWQoJHtzdWNjZXNzSWR9KS5gKVxuICAgICAgcHJvbWlzZS5yZXNvbHZlKHRoaXMpXG4gICAgICB0aGlzLnRyaWdnZXIobmV3IFB1Ymxpc2hlckV2ZW50KFJUTVBQdWJsaXNoZXJFdmVudFR5cGVzLkVNQkVEX1NVQ0NFU1MsIHRoaXMpKVxuICAgICAgdGhpcy5fdGVhckRvd25Db25uZWN0Q2FsbGJhY2soKVxuICAgIH1cbiAgICAvLyBUT0RPOiBTZXR1cCB0aW1lb3V0IHRvIHJlamVjdD9cbiAgfVxuXG4gIC8qKlxuICAgKiBUZWFyIGRvd24gZ2xvYmFsIGNhbGxiYWNrIHVzZWQgaW4gRmxhc2ggcHVibGlzaGVyIHJlY29nbml6ZSBvZiBlbWJlZC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF90ZWFyRG93bkNvbm5lY3RDYWxsYmFjayAoKSB7XG4gICAgd2luZG93LnNldEFjdGl2ZUlkID0gdW5kZWZpbmVkXG4gIH1cblxuICAvKipcbiAgICogRGVmaW5lIGdsb2JhbCBmdW5jdGlvbiBoYW5kbGVycyBmb3IgRXh0ZXJuYWxJbnRlcmZhY2UgdG8gaW52b2tlIGZvciBBUEkgY29tbXVuaWNhdGlvbi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9lc3RhYmxpc2hFeHRJbnRIYW5kbGVycyAoKSB7XG4gICAgY29uc3QgaWQgPSB0aGlzLl9vcHRpb25zLnN0cmVhbU5hbWVcbiAgICBjb25zdCBpbnZva2VGbiA9IChsYWJlbCkgPT4ge1xuICAgICAgcmV0dXJuIFsncHVibGlzaGVyJywgbGFiZWwsIGlkLnNwbGl0KCctJykuam9pbignXycpXS5qb2luKCdfJylcbiAgICB9XG4gICAgd2luZG93W2ludm9rZUZuKCdyNXByb0Nvbm5lY3RDbG9zZWQnKV0gPSAoKSA9PiB7XG4gICAgICB0aGlzLnRyaWdnZXIobmV3IFB1Ymxpc2hlckV2ZW50KFB1Ymxpc2hlckV2ZW50VHlwZXMuQ09OTkVDVElPTl9DTE9TRUQsIHRoaXMpKVxuICAgIH1cbiAgICB3aW5kb3dbaW52b2tlRm4oJ3I1cHJvQ29ubmVjdFN1Y2Nlc3MnKV0gPSAoKSA9PiB0aGlzLnRyaWdnZXIobmV3IFB1Ymxpc2hlckV2ZW50KFB1Ymxpc2hlckV2ZW50VHlwZXMuQ09OTkVDVF9TVUNDRVNTLCB0aGlzKSlcbiAgICB3aW5kb3dbaW52b2tlRm4oJ3I1cHJvVW5wdWJsaXNoU3VjY2VzcycpXSA9ICgpID0+IHRoaXMudHJpZ2dlcihuZXcgUHVibGlzaGVyRXZlbnQoUHVibGlzaGVyRXZlbnRUeXBlcy5VTlBVQkxJU0hfU1VDQ0VTUywgdGhpcykpXG4gICAgd2luZG93W2ludm9rZUZuKCdyNXByb1B1Ymxpc2hTdGFydCcpXSA9ICgpID0+IHtcbiAgICAgIHRoaXMuX2Nvbm5lY3RGdXR1cmUucmVzb2x2ZSh0aGlzKVxuICAgICAgdGhpcy50cmlnZ2VyKG5ldyBQdWJsaXNoZXJFdmVudChQdWJsaXNoZXJFdmVudFR5cGVzLlBVQkxJU0hfU1RBUlQsIHRoaXMpKVxuICAgIH1cbiAgICB3aW5kb3dbaW52b2tlRm4oJ3I1cHJvUHVibGlzaE1ldGFkYXRhJyldID0gKG1ldGFkYXRhKSA9PiB0aGlzLnRyaWdnZXIobmV3IFB1Ymxpc2hlckV2ZW50KFB1Ymxpc2hlckV2ZW50VHlwZXMuUFVCTElTSF9NRVRBREFUQSwgdGhpcywgbWV0YWRhdGEpKVxuICAgIHdpbmRvd1tpbnZva2VGbigncjVwcm9Db25uZWN0RmFpbHVyZScpXSA9ICgpID0+IHtcbiAgICAgIHRoaXMuX2Nvbm5lY3RGdXR1cmUucmVqZWN0KFB1Ymxpc2hlckV2ZW50VHlwZXMuQ09OTkVDVF9GQUlMVVJFKVxuICAgICAgdGhpcy50cmlnZ2VyKG5ldyBQdWJsaXNoZXJFdmVudChQdWJsaXNoZXJFdmVudFR5cGVzLkNPTk5FQ1RfRkFJTFVSRSwgdGhpcykpXG4gICAgfVxuICAgIHdpbmRvd1tpbnZva2VGbigncjVwcm9QdWJsaXNoRmFpbCcpXSA9ICgpID0+IHtcbiAgICAgIHRoaXMuX2Nvbm5lY3RGdXR1cmUucmVqZWN0KFB1Ymxpc2hlckV2ZW50VHlwZXMuUFVCTElTSF9GQUlMKVxuICAgICAgdGhpcy50cmlnZ2VyKG5ldyBQdWJsaXNoZXJFdmVudChQdWJsaXNoZXJFdmVudFR5cGVzLlBVQkxJU0hfRkFJTCwgdGhpcykpXG4gICAgfVxuICAgIHdpbmRvd1tpbnZva2VGbigncjVwcm9QdWJsaXNoSW52YWxpZE5hbWUnKV0gPSgpID0+IHtcbiAgICAgIHRoaXMuX2Nvbm5lY3RGdXR1cmUucmVqZWN0KFB1Ymxpc2hlckV2ZW50VHlwZXMuUFVCTElTSF9JTlZBTElEX05BTUUpXG4gICAgICB0aGlzLnRyaWdnZXIobmV3IFB1Ymxpc2hlckV2ZW50KFB1Ymxpc2hlckV2ZW50VHlwZXMuUFVCTElTSF9JTlZBTElEX05BTUUsIHRoaXMpKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIGluaXRpYWxpemUgdGhlIEZsYXNoLWJhc2VkIFB1Ymxpc2hlciBiYXNlZCBvbiBjb25maWd1cmF0aW9uLlxuICAgKiBUaGUgcmV0dXJuZWQgYFByb21pc2VgIHdpbGwgZWl0aGVyIHJlc29sdmUgd2l0aCBhIHJlZmVyZW5jZSB0byB0aGlzIGluc3RhbmNlIG9yIHJlamVjdCB3aXRoIGFuIGVycm9yIGBTdHJpbmdgIGluIGZhaWx1cmUuXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqICAgICAgICBUaGUgaW5pdGlhbGl6YXRpb24gY29uZmlndXJhdGlvbiBtYXAuXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqL1xuICBpbml0IChvcHRpb25zKSB7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXNcbiAgICBjb25zdCBkZWZlcnJlZCA9IG5ldyBEZWZlcnJlZFByb21pc2UoKVxuICAgIGNvbnN0IHZlcnNpb24gPSBvcHRpb25zLm1pbkZsYXNoVmVyc2lvbiB8fCBkZWZhdWx0T3B0aW9ucy5taW5GbGFzaFZlcnNpb25cbiAgICBpZiAoIWVudmlyb25tZW50LnN1cHBvcnRzRmxhc2hWZXJzaW9uKHZlcnNpb24pKSB7XG4gICAgICBkZWZlcnJlZC5yZWplY3QoYENvdWxkIG5vdCByZXNvbHZlIFJUTVBQdWJsaXNoZXIgaW5zdGFuY2UuIFJlcXVpcmVzIG1pbmltdW0gRmxhc2ggUGxheWVyIGluc3RhbGwgb2YgJHt2ZXJzaW9ufWApXG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgdGhpcy5fb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oe30sIGRlZmF1bHRPcHRpb25zLCBvcHRpb25zKVxuICAgICAgdHJ5IHtcbiAgICAgICAgZW52aXJvbm1lbnQuaW5qZWN0U2NyaXB0KHRoaXMuX29wdGlvbnMuc3dmb2JqZWN0VVJMKVxuICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgIGRlYnVnKE5BTUUsICdTV0ZPYmplY3QgZW1iZWRkZWQuJylcbiAgICAgICAgICAgIGlmIChzZWxmLl9zb3VyY2VIYW5kbGVyKSB7XG4gICAgICAgICAgICAgIGRlYnVnKE5BTUUsICdQdWJsaXNoIGhhbmRsZXIgZXN0YWJsaXNoZWQuJylcbiAgICAgICAgICAgICAgcmV0dXJuIHNlbGYuX3NvdXJjZUhhbmRsZXIuYWRkU291cmNlKHNlbGYuX2VsZW1lbnRJZCwgc2VsZi5fb3B0aW9ucylcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGRlYnVnKE5BTUUsICdQdWJsaXNoIGhhbmRsZXIgbm90IGVzdGFibGlzaGVkLicpXG4gICAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSlcbiAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICBzZWxmLl9zZXRWaWV3SWZOb3RFeGlzdChzZWxmLl92aWV3LCBzZWxmLl9vcHRpb25zLm1lZGlhRWxlbWVudElkKVxuICAgICAgICAgICAgZGVmZXJyZWQucmVzb2x2ZShzZWxmKVxuICAgICAgICAgIH0pXG4gICAgICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgICAgICBlcnJvcihOQU1FLCBgQ291bGQgbm90IGVtYmVkIEZsYXNoLWJhc2VkIFJUTVAgUHVibGlzaGVyLiBSZWFzb246ICR7ZXJyfWApXG4gICAgICAgICAgICBpZiAoc2VsZi5fc291cmNlSGFuZGxlcikge1xuICAgICAgICAgICAgICBzZWxmLl9zb3VyY2VIYW5kbGVyLmRpc2Nvbm5lY3QoKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVmZXJyZWQucmVqZWN0KGVycilcbiAgICAgICAgICAgIHNlbGYudHJpZ2dlcihuZXcgUHVibGlzaGVyRXZlbnQoUlRNUFB1Ymxpc2hlckV2ZW50VHlwZXMuRU1CRURfRkFJTFVSRSwgc2VsZikpXG4gICAgICAgICAgfSlcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgZGVmZXJyZWQucmVqZWN0KGBDb3VsZCBub3QgaW5qZWN0IEZsYXNoLWJhc2VkIFB1Ymxpc2hlciBpbnRvIHRoZSBwYWdlLiBSZWFzb246ICR7ZS5tZXNzYWdlfWApXG4gICAgICAgIHNlbGYudHJpZ2dlcihuZXcgUHVibGlzaGVyRXZlbnQoUlRNUFB1Ymxpc2hlckV2ZW50VHlwZXMuRU1CRURfRkFJTFVSRSwgc2VsZikpXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBkZWZlcnJlZC5wcm9taXNlXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBiZWluZyBhIGJyb2FkY2FzdCBzZXNzaW9uIGFmdGVyIGluaXRpbGl6YXRpb24gaGFzIG9jY3VyZWQuXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzdHJlYW1OYW1lXG4gICAqICAgICAgICBPcHRpb25hbCBzdHJlYW0gbmFtZSB0byBicm9hZGNhc3Qgb24sIG90aGVyd2lzZSBkZWZhdWx0aW5nIHRvIHRoZSBgc3RyZWFtTmFtZWAgcHJvdmlkZWQgaW4gYGluaXQoKWAgY29uZmlndXJhdGlvbi5cbiAgICogQHBhcmFtIHtQcm9taXNlfSBwcm9taXNlXG4gICAqICAgICAgICBPcHRpb25hbCBgUHJvbWlzZWAgb2JqZWN0IHRvIHJlc29sdmUvcmVqZWN0IG9uIGJhc2VkIG9uIHNlcXVlbmNlIG9mIGV2ZW50cyBpbiBlc3RhYmxpc2hpbmcgYSBicm9hZGNhc3QsIG90aGVyd2lzZSBkZWZhdWx0aW5nIHRvIGBQcm9taXNlYCBjcmVhdGVkIGludGVybmFsbHkgYW5kIHJldHVybmVkLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgICAgICAgVGhlIHJldHVybmVkIGBQcm9taXNlYCB3aWxsIHJlc29sdmUgb3IgcmVqZWN0IG9uIHN1Y2Nlc3NmdWwgc3RhcnQgb2YgYSBicm9hZGNhc3QuPGJyPlxuICAgKiAgICAgICAgVGhlcmUgYXJlIHNldmVyYWwgcHJvY2Vzc2VzIHRoYXQgb2NjdXIgaW4gb3JkZXIgdG8gZXN0YWJsaXNoIGEgRmxhc2gtYmFzZWQgYnJvYWRjYXN0IHRoYXQgaW52b2x2ZSAtIGJ1dCBhcmUgbm90IGxpbWl0ZWQgdG8gLSBwcm9wZXIgZW1iZWQgb2YgRmxhc2ggb2JqZWN0IG9uIHBhZ2Ugd2l0aCBmbGFzaHZhcnMgdXNlZCBpbiBlc3RhYmxpc2hpbmcgUlRNUC1iYXNlZCBOZXRDb25uZWN0aW9uLlxuICAgKi9cbiAgcHVibGlzaCAoc3RyZWFtTmFtZSA9IHVuZGVmaW5lZCwgcHJvbWlzZSA9IHVuZGVmaW5lZCkgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gICAgY29uc3QgZGZkID0gcHJvbWlzZSB8fCBuZXcgRGVmZXJyZWRQcm9taXNlKClcbiAgICB0aGlzLl9zZXRVcENvbm5lY3RDYWxsYmFjayhkZmQpXG4gICAgdGhpcy5fb3B0aW9ucy5zdHJlYW1OYW1lID0gc3RyZWFtTmFtZSB8fCB0aGlzLl9vcHRpb25zLnN0cmVhbU5hbWVcbiAgICBjb25zdCBwdWJsaXNoT3B0aW9ucyA9IHRoaXMuX29wdGlvbnNcbiAgICB0cnkge1xuICAgICAgbGV0IHNyY0hhbmRsZXIgPSB0aGlzLl9zb3VyY2VIYW5kbGVyXG4gICAgICB0aGlzLl9zb3VyY2VIYW5kbGVyLmdldEVtYmVkT3BlcmF0aW9uKClcbiAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIGRlYnVnKE5BTUUsICdbaGFuZGxlcjplbWJlZDpjb21wbGV0ZV0nKVxuICAgICAgICAgIGNvbnN0IGVsID0gZW52aXJvbm1lbnQuZ2V0RW1iZWRPYmplY3QodGhpcy5fZWxlbWVudElkKVxuICAgICAgICAgIGlmIChlbCkge1xuICAgICAgICAgICAgdGhpcy5fZXN0YWJsaXNoRXh0SW50SGFuZGxlcnMoKVxuICAgICAgICAgIH1cbiAgICAgICAgICBsZXQgY291bnQgPSAwXG4gICAgICAgICAgY29uc3QgbGltaXQgPSAxMDBcbiAgICAgICAgICBsZXQgdHJ5Q29ubmVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGxldCB0aW1lb3V0XG4gICAgICAgICAgICB0aW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpXG4gICAgICAgICAgICAgICAgc3JjSGFuZGxlci5jb25uZWN0KEpTT04uc3RyaW5naWZ5KHB1Ymxpc2hPcHRpb25zKSlcbiAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGlmIChjb3VudCsrID4gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgIHRocm93IGVcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgdHJ5Q29ubmVjdCgpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LCAzMDApXG4gICAgICAgICAgfVxuICAgICAgICAgIHRyeUNvbm5lY3QoKVxuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgICBkZmQucmVqZWN0KGVycilcbiAgICAgICAgICB0aGlzLnRyaWdnZXIobmV3IFB1Ymxpc2hlckV2ZW50KFB1Ymxpc2hlckV2ZW50VHlwZXMuQ09OTkVDVF9GQUlMVVJFLCB0aGlzKSlcbiAgICAgICAgfSlcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBlcnJvcihOQU1FLCAnW2hhbmRsZXI6ZW1iZWQ6ZXJyb3JdJylcbiAgICAgIGRmZC5yZWplY3QoYENvdWxkIG5vdCBpbml0aWF0ZSBjb25uZWN0aW9uIHNlcXVlbmNlLiBSZWFzb246ICR7ZS5tZXNzYWdlfWApXG4gICAgICB0aGlzLnRyaWdnZXIobmV3IFB1Ymxpc2hlckV2ZW50KFB1Ymxpc2hlckV2ZW50VHlwZXMuQ09OTkVDVF9GQUlMVVJFLCB0aGlzKSlcbiAgICAgIHRoaXMuX3RlYXJEb3duQ29ubmVjdENhbGxiYWNrKClcbiAgICB9XG4gICAgdGhpcy5fY29ubmVjdEZ1dHVyZSA9IGRmZFxuICAgIHJldHVybiBkZmQucHJvbWlzZVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gc3RvcCBhIGJyb2FkY2FzdC5cbiAgICogVGhlIHJldHVybmVkIGBQcm9taXNlYCB3aWxsIGVpdGhlciByZXNvbHZlIG9yIHJlamVjdCBvbiBzdWNjZXNzZnVsIHN0b3Agb2YgYnJvYWRjYXN0LlxuICAgKlxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKi9cbiAgdW5wdWJsaXNoICgpIHtcbiAgICBjb25zdCBkZWZlcnJlZCA9IG5ldyBEZWZlcnJlZFByb21pc2UoKVxuICAgIHRyeSB7XG4gICAgICBlbnZpcm9ubWVudC5nZXRFbWJlZE9iamVjdCh0aGlzLl9lbGVtZW50SWQpLnVucHVibGlzaCgpXG4gICAgICBkZWZlcnJlZC5yZXNvbHZlKClcbiAgICB9XG4gICAgY2F0Y2ggKGUpIHtcbiAgICAgIGVycm9yKE5BTUUsIGBDb3VsZCBub3QgaW5pdGlhdGUgcHVibGlzaCBzZXF1ZW5jZS4gUmVhc29uOiAke2UubWVzc2FnZX1gKVxuICAgICAgZGVmZXJyZWQucmVqZWN0KGUubWVzc2FnZSlcbiAgICB9XG4gICAgdGhpcy5fY29ubmVjdEZ1dHVyZSA9IHVuZGVmaW5lZFxuICAgIHJldHVybiBkZWZlcnJlZC5wcm9taXNlXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBzZW5kIGEgbWVzc2FnZSB0byBhbGwgc3Vic2NyaWJlcnMuXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2ROYW1lXG4gICAqICAgICAgICBUaGUgbWV0aG9kIG5hbWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBtZXNzYWdlIHRvIGJlIGFjY2VwdGVkIGJ5IGFsbCBzdWJzY3JpYmVycy5cbiAgICogQHBhcmFtIHtPYmplY3R9IGRhdGFcbiAgICogICAgICAgIFRoZSBkYXRhIG9iamVjdCB0byBzZW5kIGFzc29jaWF0ZWQgd2l0aCB0aGUgbWV0aG9kIG5hbWUuXG4gICAqL1xuICBzZW5kIChtZXRob2ROYW1lLCBkYXRhKSB7XG4gICAgdGhpcy5fc291cmNlSGFuZGxlci5zZW5kKG1ldGhvZE5hbWUsIHR5cGVvZiBkYXRhID09PSAnc3RyaW5nJyA/IGRhdGEgOiBKU09OLnN0cmluZ2lmeShkYXRhKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXByZWNhdGVkLiBSZXF1ZXN0IHRvIHVwZGF0ZSBicm9hZGNhc3QgZGltZW5zaW9ucyBiZWZvcmUgYSBicm9hZGNhc3QuXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBxdWFsaXR5XG4gICAqICAgICAgICBFeHBlY3RzIG9iamVjdCB3aXRoIGZvbGxvd2luZyBzdHJ1Y3R1cjogYHt2aWRlbzoge3dpZHRoOkludCwgaGVpZ2h0SW50fX1cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHNldE1lZGlhUXVhbGl0eSAocXVhbGl0eSkge1xuICAgIGlmICh0aGlzLl9zb3VyY2VIYW5kbGVyKSB7XG4gICAgICB0aGlzLl9zb3VyY2VIYW5kbGVyLnNldE1lZGlhUXVhbGl0eShxdWFsaXR5KVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBIZWxwZXIgbWV0aG9kIHRvIG92ZXJsYXkgb3B0aW9ucyBvdmVyIGN1cnJlbnQgY29uZmlndXJhdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IG5ld09wdGlvbnNcbiAgICogICAgICAgIFRoZSBvcHRpb25zIHRvIG92ZXJsYXkuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBvdmVybGF5T3B0aW9ucyAobmV3T3B0aW9ucykge1xuICAgIHRoaXMuX29wdGlvbnMgPSBPYmplY3QuYXNzaWduKHRoaXMuX29wdGlvbnMsIG5ld09wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGN1cnJlbnQgRmxhc2gvUlRNUCBjb25uZWN0aW9uIGhlbHBlciBpZiBlc3RhYmxpc2hlZC5cbiAgICogVXNlZCBpbiBTaGFyZWRPYmplY3QgY29tbXVuaWNhdGlvbi5cbiAgICpcbiAgICogQHJldHVybiB7UHVibGlzaGVyU291cmNlSGFuZGxlcn1cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIGdldENvbm5lY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLl9zb3VyY2VIYW5kbGVyXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgaW5pdGlhbGl6YXRpb24gY29uZmlndXJhdGlvbiB1c2VkIGluIGBpbml0KClgLlxuICAgKlxuICAgKiBAcmV0dXJuIHtPYmplY3R9XG4gICAqL1xuICBnZXRPcHRpb25zICgpIHtcbiAgICByZXR1cm4gdGhpcy5fb3B0aW9uc1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHR5cGUgb2YgaW1wbGVtZW50YXRpb246IGBSVE1QYC5cbiAgICpcbiAgICogQHJldHVybiB7U3RyaW5nfVxuICAgKi9cbiAgZ2V0VHlwZSAoKSB7XG4gICAgcmV0dXJuIFB1Ymxpc2hUeXBlcy5SVE1QLnRvVXBwZXJDYXNlKClcbiAgfVxuXG59XG5cbmV4cG9ydCBkZWZhdWx0IFJUTVBQdWJsaXNoZXJcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9qcy9wdWJsaXNoZXIvcmVkNXByby1ydG1wLmpzIiwiJ3VzZSBzdHJpY3QnXG5cbmltcG9ydCBFdmVudEVtaXR0ZXIgZnJvbSAnLi4vY29yZS9ldmVudC1lbWl0dGVyJ1xuaW1wb3J0IGVudmlyb25tZW50IGZyb20gJy4uL2Vudi9icm93c2VyJ1xuaW1wb3J0IHsgU2hhcmVkT2JqZWN0RXZlbnQgfSBmcm9tICcuLi9ldmVudC9pbmRleCdcbmltcG9ydCB7IFNoYXJlZE9iamVjdEV2ZW50VHlwZXMgfSBmcm9tICcuLi9ldmVudC9zaGFyZWRvYmplY3QtZXZlbnQnXG5cbmltcG9ydCB7IGRlYnVnIGFzIGRlYnVnTG9nIH0gZnJvbSAnLi4vbG9nJ1xuaW1wb3J0IHsgd2FybiBhcyB3YXJuTG9nIH0gZnJvbSAnLi4vbG9nJ1xuaW1wb3J0IHsgZXJyb3IgYXMgZXJyb3JMb2cgfSBmcm9tICcuLi9sb2cnXG5cbmNvbnN0IE5BTUUgPSAnUmVkNVByb1NoYXJlZE9iamVjdCdcbmNvbnN0IFNPX1NVQlRZUEVfUFJPUEVSVFkgPSA0XG5jb25zdCBTT19TVUJUWVBFX01FVEhPRCA9IDZcblxuY29uc3QgZGVidWcgPSAoc29OYW1lLCBtZXNzYWdlKSA9PiB7XG4gIGRlYnVnTG9nKFtOQU1FLCBzb05hbWVdLmpvaW4oJzonKSwgbWVzc2FnZSlcbn1cbmNvbnN0IHdhcm4gPSAoc29OYW1lLCBtZXNzYWdlKSA9PiB7XG4gIHdhcm5Mb2coW05BTUUsIHNvTmFtZV0uam9pbignOicpLCBtZXNzYWdlKVxufVxuY29uc3QgZXJyb3IgPSAoc29OYW1lLCBtZXNzYWdlKSA9PiB7XG4gIGVycm9yTG9nKFtOQU1FLCBzb05hbWVdLmpvaW4oJzonKSwgbWVzc2FnZSlcbn1cblxuY29uc3QgZGVjb2RlTWVzc2FnZUlmSlNPTlN0cmluZyA9IChtZXNzYWdlKSA9PiB7XG4gIHJldHVybiB0eXBlb2YgbWVzc2FnZSA9PT0gJ3N0cmluZycgPyBKU09OLnBhcnNlKG1lc3NhZ2UpIDogbWVzc2FnZVxufVxuXG4vKipcbiAqIERlZmluZXMgdGhlIHN0cnVjdHVyZSBvZiBhIFByb3BlcnR5IERhdGEgbm90aWZpY2F0aW9uIG9iamVjdC5cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5jbGFzcyBQcm9wZXJ0eURhdGEge1xuXG4gIGNvbnN0cnVjdG9yIChrZXksIHZhbHVlKSB7XG4gICAgdGhpcy5rZXkgPSBrZXlcbiAgICB0aGlzLnZhbHVlID0gdmFsdWVcbiAgfVxuXG4gIHRvT2JqZWN0ICgpIHtcbiAgICBsZXQgb2JqID0gIHt9XG4gICAgb2JqW3RoaXMua2V5XSA9IHRoaXMudmFsdWVcbiAgICByZXR1cm4gb2JqXG4gIH1cblxufVxuXG4vKipcbiAqIERlZmluZXMgdGhlIHN0cnVjdHVyZSBvZiBhIE1ldGhvZCBEYXRhIG5vdGlmaWNhdGlvbiBvYmplY3QuXG4gKlxuICogQHByaXZhdGVcbiAqL1xuY2xhc3MgTWV0aG9kRGF0YSB7XG5cbiAgY29uc3RydWN0b3IgKG1ldGhvZE5hbWUsIG1lc3NhZ2UpIHtcbiAgICB0aGlzLm1ldGhvZE5hbWUgPSBtZXRob2ROYW1lXG4gICAgbGV0IG1lc3NhZ2VMaXN0XG4gICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChtZXNzYWdlKSA9PT0gJ1tvYmplY3QgQXJyYXldJykge1xuICAgICAgbGV0IGlcbiAgICAgIGxldCBtc2dcbiAgICAgIGxldCBsZW5ndGggPSBtZXNzYWdlLmxlbmd0aFxuICAgICAgbWVzc2FnZUxpc3QgPSBbXVxuICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgIG1zZyA9IGRlY29kZU1lc3NhZ2VJZkpTT05TdHJpbmcobWVzc2FnZVtpXSlcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChtZXNzYWdlKSA9PT0gJ1tvYmplY3QgQXJyYXldJykge1xuICAgICAgICAgIG1lc3NhZ2VMaXN0ID0gbWVzc2FnZUxpc3QuY29uY2F0KG1zZylcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBtZXNzYWdlTGlzdC5wdXNoKG1zZylcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIG1lc3NhZ2VMaXN0ID0gW2RlY29kZU1lc3NhZ2VJZkpTT05TdHJpbmcobWVzc2FnZSldXG4gICAgfVxuICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2VMaXN0Lmxlbmd0aCA9PT0gMSA/IG1lc3NhZ2VMaXN0WzBdIDogbWVzc2FnZUxpc3RcbiAgfVxuXG4gIHRvT2JqZWN0ICgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbWV0aG9kTmFtZTogdGhpcy5tZXRob2ROYW1lLFxuICAgICAgbWVzc2FnZTogdGhpcy5tZXNzYWdlXG4gICAgfVxuICB9XG5cbn1cblxuLyoqXG4gKiBNYWluIGVudHJ5IGZvciBTaGFyZWQgT2JqZWN0IGFzc29jaWF0ZWQgd2l0aCBQdWJsaXNoZXJzIGFuZCBTdWJzY3JpYmVycy5cbiAqXG4gKiBAZXh0ZW5kcyBFdmVudEVtaXR0ZXJcbiAqL1xuY2xhc3MgUmVkNVByb1NoYXJlZE9iamVjdCBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG5cbiAgLyoqXG4gICAqIFRoZSBBUEkgb24gdGhpcyBvYmplY3QgaXMgbGltaXRlZCBhcyBpdCBjb21tdW5pY2F0ZXMgYWxvbmcgd2l0aCBtZXNzYWdlIGNoYW5uZWwgY29ubmVjdGlvbiBvZiBhIHByZXZpb3VzbHkgZXN0YWJsaXNoZWQgUHVibGlzaGVyIG9yIFN1YnNjcmliZXIsIG9mIHdoaWNoIHlvdSBwcm92aWRlIGluIHRoZSBjb25zdHVjdG9yLlxuICAgKlxuICAgKiBFdmVudCBoYW5kbGVycyBzaG91bGQgYmUgYXNzaWduZWQgdG8gbmV3IGBSZWQ1UHJvU2hhcmVkT2JqZWN0YCBpbnN0YW5jZXMgaW4gb3JkZXIgdG8gaGFuZGxlIG5vdGlmaWNhdGlvbnMgb3ZlciB0aGUgY29tbXVuaWNhdGlvbiBjaGFubmVsLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZVxuICAgKiAgICAgICAgVGhlIG5hbWUgb2YgdGhlIFNoYXJlZCBPYmplY3QgdG8gY29ubmVjdCB0by5cbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbm5lY3Rpb25cbiAgICogICAgICAgIFRoZSBjb25uZWN0aW9uIGRlbGVnYXRlIHRvIHNlbmQgYW5kIHJlY2VpdmUgU2hhcmVkIE9iamVjdCBub3RpZmljYXRpb25zIG9uLlxuICAgKiAgICAgICAgVGhpcyB3aWxsIGVpdGhlciBiZSBhIHByZXZpb3VzbHkgZXN0YWJsaXNoZWQgUHVibGlzaGVyIG9yIFN1YnNjcmliZXIgaW5zdGFuY2UuXG4gICAqL1xuICBjb25zdHJ1Y3RvciAobmFtZSwgY29ubmVjdGlvbikge1xuICAgIHN1cGVyKClcbiAgICB0aGlzLl9uYW1lID0gbmFtZVxuICAgIHRoaXMuX3NvY2tldCA9IGNvbm5lY3Rpb24uZ2V0Q29ubmVjdGlvbigpXG4gICAgdGhpcy5fc29ja2V0LmFkZFNoYXJlZE9iamVjdFJlc3BvbnNlSGFuZGxlcih0aGlzKVxuICAgIHRoaXMuX29uY2xvc2UgPSB0aGlzLmNsb3NlLmJpbmQodGhpcylcbiAgICB0cnkge1xuICAgICAgZGVidWcodGhpcy5fbmFtZSwgJ1tzaGFyZWRvYmplY3Q6Y29ubmVjdDphdHRlbXB0XScpXG4gICAgICAvLyBJbW1lZGlhdGVseSBpbnZva2UgcmVxdWVzdCBvbiBzaGFyZWQgb2JqZWN0IHRocm91Z2ggdGhlIGBnZXRDb25uZWN0aW9uKClgXG4gICAgICAvLyAgaW5zdGFuY2Ugb2YgYSBQdWJsaXNoZXIgb3IgU3Vic2NyaWJlciAod2hvbWV2ZXIgaW52b2tlZCB0aGlzIGNvbnN0cnVjdG9yKS5cbiAgICAgIHRoaXMuX3NvY2tldC5nZXRSZW1vdGVTaGFyZWRPYmplY3QodGhpcy5fbmFtZSlcbiAgICAgIGVudmlyb25tZW50LmFkZENsb3NlSGFuZGxlcih0aGlzLl9vbmNsb3NlLCAwKVxuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgZXJyb3IodGhpcy5fbmFtZSwgJ1tzaGFyZWRvYmplY3Q6Y29ubmVjdDplcnJvcl06ICcgKyBlLm1lc3NhZ2UpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEF0dGVtcHQgdG8gcGFyc2UgbWVzc2FnZSBpbnRvIGEgT2JqZWN0LlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gbWVzc2FnZVxuICAgKiAgICAgICAgRWl0aGVyIGEgSlNPTiBzdHJpbmcgb3Igb2JqZWN0LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX2dldEpzb25Gcm9tU29ja2V0TWVzc2FnZSAobWVzc2FnZSkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gdHlwZW9mIG1lc3NhZ2UuZGF0YSA9PT0gJ3N0cmluZycgPyBKU09OLnBhcnNlKG1lc3NhZ2UuZGF0YSkgOiBtZXNzYWdlLmRhdGFcbiAgICB9XG4gICAgY2F0Y2ggKGUpIHtcbiAgICAgIHdhcm4odGhpcy5fbmFtZSwgJ0NvdWxkIG5vdCBwYXJzZSBtZXNzYWdlIGFzIEpTT04uIE1lc3NhZ2U9ICcgKyBtZXNzYWdlLmRhdGEgKyAnLiBFcnJvcj0gJyArIGUubWVzc2FnZSlcbiAgICB9XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIC8qKlxuICAgKiBEaXNwYXRjaCBvZiBQUk9QRVJUWV9VUERBVEUgd2l0aCBpbmZvcm1hdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IHZhbHVlT2JqZWN0XG4gICAqICAgICAgICBPcHRpb25hbCB2YWx1ZSBvYmplY3QgdG8gc2VuZCBpbiBub3RpZmljYXRpb24uXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfbm90aWZ5T2ZQcm9wZXJ0eVZhbHVlcyAodmFsdWVPYmplY3QpIHtcbiAgICBpZiAoT2JqZWN0LmtleXModmFsdWVPYmplY3QpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB0aGlzLnRyaWdnZXIobmV3IFNoYXJlZE9iamVjdEV2ZW50KFNoYXJlZE9iamVjdEV2ZW50VHlwZXMuUFJPUEVSVFlfVVBEQVRFLCB0aGlzLl9uYW1lLCB7fSkpXG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgbGV0IGtleVxuICAgICAgZm9yIChrZXkgaW4gdmFsdWVPYmplY3QpIHtcbiAgICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTaGFyZWRPYmplY3RFdmVudChTaGFyZWRPYmplY3RFdmVudFR5cGVzLlBST1BFUlRZX1VQREFURSwgdGhpcy5fbmFtZSwgbmV3IFByb3BlcnR5RGF0YShrZXksIHZhbHVlT2JqZWN0W2tleV0pLnRvT2JqZWN0KCkpKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEaXNwYXRjaCBvZiBQUk9QRVJUWV9VUERBVEUgb3IgTUVUSE9EX1VQREFURSBiYXNlZCBvbiBldmVudChzKS5cbiAgICpcbiAgICogQHBhcmFtIHtBcnJheX0gZXZlbnRzXG4gICAqICAgICAgICBBIGxpc3Qgb2YgZXZlbnRzIHRvIGl0ZXJhdGUgdGhyb3VnaCBhbmQgZGlzcGF0Y2ggbm90aWZpY2F0aW9ucyBmcm9tLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX25vdGlmeU9mRXZlbnRzIChldmVudHMpIHtcbiAgICBsZXQgaSwgZXZlbnRcbiAgICBsZXQgaGFuZGxlZCA9IGZhbHNlXG4gICAgY29uc3QgbGVuZ3RoID0gZXZlbnRzLmxlbmd0aFxuICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgZXZlbnQgPSBldmVudHNbaV1cbiAgICAgIHN3aXRjaCAoZXZlbnQuc3VidHlwZSkge1xuICAgICAgICBjYXNlIFNPX1NVQlRZUEVfUFJPUEVSVFk6XG4gICAgICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTaGFyZWRPYmplY3RFdmVudChTaGFyZWRPYmplY3RFdmVudFR5cGVzLlBST1BFUlRZX1VQREFURSwgdGhpcy5fbmFtZSwgbmV3IFByb3BlcnR5RGF0YShldmVudC5hdHRyaWJ1dGUsIGV2ZW50LnZhbHVlKS50b09iamVjdCgpKSlcbiAgICAgICAgICBoYW5kbGVkID0gdHJ1ZVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGNhc2UgU09fU1VCVFlQRV9NRVRIT0Q6XG4gICAgICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTaGFyZWRPYmplY3RFdmVudChTaGFyZWRPYmplY3RFdmVudFR5cGVzLk1FVEhPRF9VUERBVEUsIHRoaXMuX25hbWUsIG5ldyBNZXRob2REYXRhKGV2ZW50Lm1ldGhvZCwgZXZlbnQudmFsdWUpLnRvT2JqZWN0KCkpKVxuICAgICAgICAgIGhhbmRsZWQgPSB0cnVlXG4gICAgICAgICAgYnJlYWtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGhhbmRsZWRcbiAgfVxuXG4gIC8qKlxuICAgKiBJbnZva2VkIGJ5IGNvbm5lY3Rpb24gY2hhbm5lbCB0byBoYW5kbGUgbWVzc2FnZSBhbmQgZGlzcGF0Y2ggYXBwcm9wcmlhdGUgbm90aWZpY2F0aW9ucy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHJlc3BvbmQgKG1lc3NhZ2UpIHtcbiAgICBpZiAobWVzc2FnZS5kYXRhKSB7XG4gICAgICBsZXQganNvbiA9IHRoaXMuX2dldEpzb25Gcm9tU29ja2V0TWVzc2FnZShtZXNzYWdlKVxuICAgICAgaWYgKGpzb24gPT09IG51bGwpIHtcbiAgICAgICAgd2Fybih0aGlzLl9uYW1lLCAnRGV0ZXJtaW5lZCB3ZWJzb2NrZXQgcmVzcG9uc2Ugbm90IGluIGNvcnJlY3QgZm9ybWF0LiBBYm9ydGluZyBtZXNzYWdlIGhhbmRsZS4nKVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGlmIChqc29uLmRhdGEgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZiAoanNvbi5kYXRhLm5hbWUgPT09IHRoaXMuX25hbWUpIHtcbiAgICAgICAgICBkZWJ1Zyh0aGlzLl9uYW1lLCAnW3NoYXJlZG9iamVjdC1yZXNwb25zZV06ICcgKyBKU09OLnN0cmluZ2lmeShqc29uLCBudWxsLCAyKSlcbiAgICAgICAgICBpZiAoanNvbi5kYXRhLnN0YXR1cyA9PT0gJ1NoYXJlZE9iamVjdC5TdGF0dXMuR2V0UmVtb3RlJyAmJlxuICAgICAgICAgICAgICBqc29uLmRhdGEubWVzc2FnZSA9PT0gJ1N1Y2Nlc3MnKSB7XG4gICAgICAgICAgICB0aGlzLl9zb2NrZXQuY29ubmVjdFRvU2hhcmVkT2JqZWN0KHRoaXMuX25hbWUpXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIGlmIChqc29uLmRhdGEuc3RhdHVzID09PSAnU2hhcmVkT2JqZWN0LlN0YXR1cy5HZXRSZW1vdGUnICYmXG4gICAgICAgICAgICAgIGpzb24uZGF0YS5tZXNzYWdlID09PSAnRmFpbCcpIHtcbiAgICAgICAgICAgIHRoaXMudHJpZ2dlcihuZXcgU2hhcmVkT2JqZWN0RXZlbnQoU2hhcmVkT2JqZWN0RXZlbnRUeXBlcy5DT05ORUNUX0ZBSUxVUkUsIHRoaXMuX25hbWUpKVxuICAgICAgICAgICAgcmV0dXJuIHRydWVcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSBpZiAoanNvbi5kYXRhLnN0YXR1cyA9PT0gJ1NoYXJlZE9iamVjdC5TdGF0dXMuQ29ubmVjdCcgJiZcbiAgICAgICAgICAgICAganNvbi5kYXRhLm1lc3NhZ2UgPT09ICdTdWNjZXNzJykge1xuICAgICAgICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTaGFyZWRPYmplY3RFdmVudChTaGFyZWRPYmplY3RFdmVudFR5cGVzLkNPTk5FQ1RfU1VDQ0VTUywgdGhpcy5fbmFtZSkpXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIGlmIChqc29uLmRhdGEuc3RhdHVzID09PSAnU2hhcmVkT2JqZWN0LlN0YXR1cy5Db25uZWN0JyAmJlxuICAgICAgICAgICAgICBqc29uLmRhdGEubWVzc2FnZSA9PT0gJ0ZhaWwnKSB7XG4gICAgICAgICAgICB0aGlzLnRyaWdnZXIobmV3IFNoYXJlZE9iamVjdEV2ZW50KFNoYXJlZE9iamVjdEV2ZW50VHlwZXMuQ09OTkVDVF9GQUlMVVJFLCB0aGlzLl9uYW1lKSlcbiAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgICAgfVxuICAgICAgICAgIGVsc2UgaWYgKGpzb24uZGF0YS50eXBlID09PSAnc2hhcmVkb2JqZWN0Jykge1xuICAgICAgICAgICAgaWYgKGpzb24uZGF0YS5oYXNPd25Qcm9wZXJ0eSgnZXZlbnRzJykpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX25vdGlmeU9mRXZlbnRzKGpzb24uZGF0YS5ldmVudHMpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChqc29uLmRhdGEuaGFzT3duUHJvcGVydHkoJ3ZhbHVlJykpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX25vdGlmeU9mUHJvcGVydHlWYWx1ZXMoanNvbi5kYXRhLnZhbHVlKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBkZWJ1ZygnVW5oYW5kbGVkIFNvY2tldCBleGNoYW5nZTogJyArIEpTT04uc3RyaW5naWZ5KGpzb24sIG51bGwsIDIpKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuXG4gIHNlbmQgKG1lc3NhZ2VOYW1lLCBkYXRhKSB7XG4gICAgdGhpcy5fc29ja2V0LnNlbmRUb1NoYXJlZE9iamVjdCh0aGlzLl9uYW1lLCBtZXNzYWdlTmFtZSwgZGF0YSlcbiAgfVxuXG4gIHNldFByb3BlcnR5IChrZXksIHZhbHVlKSB7XG4gICAgdGhpcy5fc29ja2V0LnNlbmRQcm9wZXJ0eVRvU2hhcmVkT2JqZWN0KHRoaXMuX25hbWUsIGtleSwgdmFsdWUpXG4gIH1cblxuICBjbG9zZSAoKSB7XG4gICAgaWYgKHRoaXMuX3NvY2tldCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB3YXJuKCdTb2NrZXQgbm8gbG9uZ2VyIGV4aXN0IHRvIGNsb3NlIHNoYXJlZCBvYmplY3QgcHJvcGVybHkuJylcbiAgICB9XG4gICAgdGhpcy5fc29ja2V0LmNsb3NlU2hhcmVkT2JqZWN0KHRoaXMuX25hbWUpXG4gICAgaWYgKHRoaXMuX3NvY2tldCkge1xuICAgICAgdGhpcy5fc29ja2V0LnJlbW92ZVNoYXJlZE9iamVjdFJlc3BvbnNlSGFuZGxlcih0aGlzKVxuICAgIH1cbiAgICB0aGlzLl9zb2NrZXQgPSB1bmRlZmluZWRcbiAgICB0aGlzLl9uYW1lID0gdW5kZWZpbmVkXG4gICAgZW52aXJvbm1lbnQucmVtb3ZlQ2xvc2VIYW5kbGVyKHRoaXMuX29uY2xvc2UpXG4gIH1cblxuICBnZXROYW1lICgpIHtcbiAgICByZXR1cm4gdGhpcy5fbmFtZVxuICB9XG5cbn1cblxuZXhwb3J0IHsgUmVkNVByb1NoYXJlZE9iamVjdCB9XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvanMvc2hhcmVkb2JqZWN0L2luZGV4LmpzIiwiJ3VzZSBzdHJpY3QnXG5cbmltcG9ydCBFdmVudEVtaXR0ZXIgZnJvbSAnLi4vLi4vY29yZS9ldmVudC1lbWl0dGVyJ1xuaW1wb3J0IGVudmlyb25tZW50IGZyb20gJy4uLy4uL2Vudi9icm93c2VyJ1xuaW1wb3J0IHsgU2xpZGVyRXZlbnQsIFNsaWRlckV2ZW50VHlwZXMgfSBmcm9tICcuL2V2ZW50J1xuaW1wb3J0IHsgZGVidWcgfSBmcm9tICcuLi8uLi9sb2cnXG5cbmxldCBOQU1FID0gJ0NvbnRyb2xTbGlkZXInXG5cbi8qKlxuICogQ3VzdG9tIHNsaWRlciBjb250cm9sIGZvciBQbGF5YmFjayBDb250cm9scy5cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5jbGFzcyBDb250cm9sU2xpZGVyIGV4dGVuZHMgRXZlbnRFbWl0dGVyIHtcblxuICBjb25zdHJ1Y3RvciAodHlwZSkge1xuICAgIHN1cGVyKClcbiAgICBOQU1FID0gW05BTUUsIHR5cGVdLmpvaW4oJzo6JylcbiAgICBkZWJ1ZyhOQU1FLCAnW2luaXRdJylcbiAgICB0aGlzLl9jb250YWluZXIgPSBlbnZpcm9ubWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKVxuICAgIHRoaXMuX2J1dHRvbiA9IHRoaXMuY3JlYXRlQnV0dG9uKClcbiAgICB0aGlzLl90cmFjayA9IHRoaXMuY3JlYXRlVHJhY2soKVxuICAgIHRoaXMuX3Byb2dyZXNzQmFyID0gdGhpcy5jcmVhdGVQcm9ncmVzc0JhcigpXG4gICAgdGhpcy5fY29udGFpbmVyLmFwcGVuZENoaWxkKHRoaXMuX3RyYWNrKVxuICAgIHRoaXMuX2NvbnRhaW5lci5hcHBlbmRDaGlsZCh0aGlzLl9wcm9ncmVzc0JhcilcbiAgICB0aGlzLl9jb250YWluZXIuYXBwZW5kQ2hpbGQodGhpcy5fYnV0dG9uKVxuICAgIHRoaXMuX3ZhbHVlID0gMCAvLyAwIC0gMVxuICAgIHRoaXMuX2Rpc2FibGVkID0gZmFsc2VcbiAgICB0aGlzLl9ldmVudFN0YXJ0UG9zaXRpb24gPSAwXG4gICAgdGhpcy5fbGF5b3V0KClcbiAgICB0aGlzLl9tb3VzZXVwSGFuZGxlciA9IHRoaXMuX21vdXNldXAuYmluZCh0aGlzKVxuICAgIHRoaXMuX21vdXNlZG93bkhhbmRsZXIgPSB0aGlzLl9tb3VzZWRvd24uYmluZCh0aGlzKVxuICAgIHRoaXMuX21vdXNlbW92ZUhhbmRsZXIgPSB0aGlzLl9tb3VzZW1vdmUuYmluZCh0aGlzKVxuICAgIHRoaXMuX3RvdWNodXBIYW5kbGVyID0gdGhpcy5fdG91Y2hwcm94eS5iaW5kKHRoaXMpXG4gICAgdGhpcy5fdG91Y2hkb3duSGFuZGxlciA9IHRoaXMuX3RvdWNocHJveHkuYmluZCh0aGlzKVxuICAgIHRoaXMuX3RvdWNobW92ZUhhbmRsZXIgPSB0aGlzLl90b3VjaHByb3h5LmJpbmQodGhpcylcbiAgICB0aGlzLl91cGRhdGVIYW5kbGVycyh0aGlzLl9kaXNhYmxlZClcbiAgfVxuXG4gIC8qKlxuICAgKiBUb3VjaCBldmVudCBwcm94eSB0byBidWJibGUgb3V0IG1vdXNlIGV2ZW50cyBmb3IgaGFuZGxpbmcgaW50ZXJhY3Rpb24uXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfdG91Y2hwcm94eSAoZXZlbnQpIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpXG4gICAgaWYgKGV2ZW50LnRvdWNoZXMubGVuZ3RoID4gMSB8fCAoZXZlbnQudHlwZSA9PSBcInRvdWNoZW5kXCIgJiYgZXZlbnQudG91Y2hlcy5sZW5ndGggPiAwKSkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIGxldCBldnQgPSBlbnZpcm9ubWVudC5jcmVhdGVFdmVudCgnTW91c2VFdmVudCcpXG4gICAgbGV0IHR5cGUsIHRvdWNoXG4gICAgY29uc3QgdCA9IGV2ZW50Lm9yaWdpbmFsVGFyZ2V0IHx8IGV2ZW50LnRhcmdldFxuICAgIHN3aXRjaCAoZXZlbnQudHlwZSkge1xuICAgICAgY2FzZSAndG91Y2hzdGFydCc6XG4gICAgICAgIHR5cGUgPSAnbW91c2Vkb3duJ1xuICAgICAgICB0b3VjaCA9IGV2ZW50LmNoYW5nZWRUb3VjaGVzWzBdXG4gICAgICAgIGJyZWFrXG4gICAgICBjYXNlICd0b3VjaG1vdmUnOlxuICAgICAgICB0eXBlID0gJ21vdXNlbW92ZSdcbiAgICAgICAgdG91Y2ggPSBldmVudC5jaGFuZ2VkVG91Y2hlc1swXVxuICAgICAgICBicmVha1xuICAgICAgY2FzZSAndG91Y2hlbmQnOlxuICAgICAgICB0eXBlID0gJ21vdXNldXAnXG4gICAgICAgIHRvdWNoID0gZXZlbnQuY2hhbmdlZFRvdWNoZXNbMF1cbiAgICAgICAgYnJlYWtcbiAgICB9XG5cbiAgICBldnQuaW5pdE1vdXNlRXZlbnQodHlwZSwgdHJ1ZSwgdHJ1ZSwgdC5vd25lckRvY3VtZW50LmRlZmF1bHRWaWV3LCAwLFxuICAgICAgdG91Y2guc2NyZWVuWCwgdG91Y2guc2NyZWVuWSwgdG91Y2guY2xpZW50WCwgdG91Y2guY2xpZW50WSxcbiAgICAgIGV2ZW50LmN0cmxLZXksIGV2ZW50LmFsdEtleSwgZXZlbnQuc2hpZnRLZXksIGV2ZW50Lm1ldGFLZXksIDAsIG51bGwpXG4gICAgdC5kaXNwYXRjaEV2ZW50KGV2dClcbiAgfVxuXG4gIC8qKlxuICAgKiBFdmVudCBoYW5kbGVyIGZvciBtb3VzZSB1cC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9tb3VzZXVwICgpIHtcbiAgICB0aGlzLl9ldmVudFN0YXJ0UG9zaXRpb24gPSAwXG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdGhpcy5fbW91c2Vtb3ZlSGFuZGxlcilcbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fbW91c2V1cEhhbmRsZXIpXG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdGhpcy5fdG91Y2htb3ZlSGFuZGxlcilcbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaHVwJywgdGhpcy5fdG91Y2h1cEhhbmRsZXIpXG4gICAgdGhpcy50cmlnZ2VyKG5ldyBTbGlkZXJFdmVudChTbGlkZXJFdmVudFR5cGVzLkNIQU5HRV9DT01QTEVURSwgdGhpcykpXG4gIH1cblxuICAvKipcbiAgICogRXZlbnQgaGFuZGxlciBmb3IgbW91c2UgbW92ZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9tb3VzZW1vdmUgKGV2ZW50KSB7XG4gICAgICBjb25zdCBwb3NpdGlvbk9mZnNldCA9IChlbnZpcm9ubWVudC5nZXRNb3VzZVhGcm9tRXZlbnQoZXZlbnQpIC0gdGhpcy5fZXZlbnRTdGFydFBvc2l0aW9uKVxuICAgICAgY29uc3QgcmVjdCA9IHRoaXMuX2J1dHRvbi5wYXJlbnROb2RlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpXG4gICAgICBsZXQgcG9zaXRpb24gPSAodGhpcy5fZXZlbnRTdGFydFBvc2l0aW9uICsgcG9zaXRpb25PZmZzZXQpIC0gcmVjdC5sZWZ0IC8vIC0gZW52aXJvbm1lbnQuZ2V0U2Nyb2xsWCgpXG4gICAgICBwb3NpdGlvbiA9IE1hdGgubWF4KDAsIHBvc2l0aW9uKVxuICAgICAgcG9zaXRpb24gPSBNYXRoLm1pbihwb3NpdGlvbiwgcmVjdC53aWR0aClcbiAgICAgIGxldCBwZXJjZW50YWdlID0gcG9zaXRpb24gLyByZWN0LndpZHRoXG4gICAgICB0aGlzLnRyaWdnZXIobmV3IFNsaWRlckV2ZW50KFNsaWRlckV2ZW50VHlwZXMuQ0hBTkdFLCB0aGlzLCBwZXJjZW50YWdlKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBFdmVudCBoYW5kbGVyIGZvciBtb3VzZSBkb3duLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX21vdXNlZG93biAoZXZlbnQpIHtcbiAgICAgIHRoaXMuX2V2ZW50U3RhcnRQb3NpdGlvbiA9IGVudmlyb25tZW50LmdldE1vdXNlWEZyb21FdmVudChldmVudClcbiAgICAgIHRoaXMudHJpZ2dlcihuZXcgU2xpZGVyRXZlbnQoU2xpZGVyRXZlbnRUeXBlcy5DSEFOR0VfU1RBUlQsIHRoaXMpKVxuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdGhpcy5fbW91c2Vtb3ZlSGFuZGxlcilcbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLl9tb3VzZXVwSGFuZGxlcilcbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRoaXMuX3RvdWNobW92ZUhhbmRsZXIpXG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHVwJywgdGhpcy5fdG91Y2h1cEhhbmRsZXIpXG4gIH1cblxuICAvKipcbiAgICogQWRkcyBvciByZW1vdmVzIGNvbnRyb2wgaGFubGRlcnMgYmFzZWQgb24gZmxhZyBvZiBvdmVyYWxsIGNvbnRyb2wgYmVpbmcgZGlzYWJsZWQuXG4gICAqXG4gICAqIEBwYXJhbSB7Qm9vbGVhbn0gaXNEaXNhYmxlZFxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX3VwZGF0ZUhhbmRsZXJzIChpc0Rpc2FibGVkKSB7XG4gICAgdGhpcy5fZXZlbnRTdGFydFBvc2l0aW9uID0gMFxuICAgIGlmIChpc0Rpc2FibGVkKSB7XG4gICAgICB0aGlzLl90cmFjay5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX21vdXNlbW92ZUhhbmRsZXIpXG4gICAgICB0aGlzLl9wcm9ncmVzc0Jhci5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX21vdXNlbW92ZUhhbmRsZXIpXG4gICAgICB0aGlzLl9idXR0b24ucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5fbW91c2Vkb3duSGFuZGxlcilcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX21vdXNlbW92ZUhhbmRsZXIpXG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fbW91c2V1cEhhbmRsZXIpXG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCB0aGlzLl90b3VjaG1vdmVIYW5kbGVyKVxuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2h1cCcsIHRoaXMuX3RvdWNodXBIYW5kbGVyKVxuICAgICAgdGhpcy5fdHJhY2suY2xhc3NMaXN0LmFkZCgncmVkNXByby1tZWRpYS1zbGlkZXItZGlzYWJsZWQnKVxuICAgICAgdGhpcy5fcHJvZ3Jlc3NCYXIuY2xhc3NMaXN0LmFkZCgncmVkNXByby1tZWRpYS1zbGlkZXItZGlzYWJsZWQnKVxuICAgICAgdGhpcy5fYnV0dG9uLmNsYXNzTGlzdC5hZGQoJ3JlZDVwcm8tbWVkaWEtc2xpZGVyLWRpc2FibGVkJylcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICB0aGlzLl90cmFjay5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX21vdXNlbW92ZUhhbmRsZXIpXG4gICAgICB0aGlzLl9wcm9ncmVzc0Jhci5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX21vdXNlbW92ZUhhbmRsZXIpXG4gICAgICB0aGlzLl9idXR0b24uYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5fbW91c2Vkb3duSGFuZGxlcilcbiAgICAgIHRoaXMuX2J1dHRvbi5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgdGhpcy5fdG91Y2hkb3duSGFuZGxlcilcbiAgICAgIHRoaXMuX3RyYWNrLmNsYXNzTGlzdC5yZW1vdmUoJ3JlZDVwcm8tbWVkaWEtc2xpZGVyLWRpc2FibGVkJylcbiAgICAgIHRoaXMuX3Byb2dyZXNzQmFyLmNsYXNzTGlzdC5yZW1vdmUoJ3JlZDVwcm8tbWVkaWEtc2xpZGVyLWRpc2FibGVkJylcbiAgICAgIHRoaXMuX2J1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKCdyZWQ1cHJvLW1lZGlhLXNsaWRlci1kaXNhYmxlZCcpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlLWxheW91dCBzdWIgY29udHJvbHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfbGF5b3V0ICgpIHtcbiAgICBsZXQgcG9zaXRpb24gPSB0aGlzLl9wcm9ncmVzc0Jhci5wYXJlbnROb2RlLmNsaWVudFdpZHRoICogdGhpcy5fdmFsdWVcbiAgICB0aGlzLl9wcm9ncmVzc0Jhci5zdHlsZS53aWR0aCA9IHBvc2l0aW9uICsgJ3B4J1xuICAgIHRoaXMuX2J1dHRvbi5zdHlsZS5sZWZ0ID0gKHBvc2l0aW9uIC0gKHRoaXMuX2J1dHRvbi5jbGllbnRXaWR0aCAqIDAuNSkpICsgJ3B4J1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgdGhlIGJ1dHRvbiBlbGVtZW50LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgY3JlYXRlQnV0dG9uICgpIHtcbiAgICBsZXQgc3BhbiA9IGVudmlyb25tZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKVxuICAgIHNwYW4uY2xhc3NMaXN0LmFkZCgncmVkNXByby1tZWRpYS1zbGlkZXItYnV0dG9uJylcbiAgICByZXR1cm4gc3BhblxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgdGhlIHByb2dyZXNzIGJhciBlbGVtZW50LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgY3JlYXRlUHJvZ3Jlc3NCYXIgKCkge1xuICAgIGxldCBzcGFuID0gZW52aXJvbm1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpXG4gICAgc3Bhbi5jbGFzc0xpc3QuYWRkKCdyZWQ1cHJvLW1lZGlhLXNsaWRlci1wcm9ncmVzcycpXG4gICAgcmV0dXJuIHNwYW5cbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIHRoZSB0cmFjayBlbGVtZW50LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgY3JlYXRlVHJhY2sgKCkge1xuICAgIGxldCBzcGFuID0gZW52aXJvbm1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpXG4gICAgc3Bhbi5jbGFzc0xpc3QuYWRkKCdyZWQ1cHJvLW1lZGlhLXNsaWRlci10cmFjaycpXG4gICAgcmV0dXJuIHNwYW5cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHZhbHVlLlxuICAgKlxuICAgKiBAcmV0dXJuIHtOdW1iZXJ9XG4gICAqL1xuICBnZXQgdmFsdWUgKCkge1xuICAgIHJldHVybiB0aGlzLl92YWx1ZVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIGN1cnJlbnQgdmFsdWUuXG4gICAqXG4gICAqIEBwYXJhbSB7TnVtYmVyfSAwLi4xXG4gICAqL1xuICBzZXQgdmFsdWUgKHBlcmNlbnRWYWx1ZSAvKiAwIC0gMSAqLykge1xuICAgIHRoaXMuX3ZhbHVlID0gcGVyY2VudFZhbHVlXG4gICAgdGhpcy5fbGF5b3V0KClcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGRpc2FibGVkIGZsYWcuXG4gICAqXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBnZXQgZGlzYWJsZWQgKCkge1xuICAgIHJldHVybiB0aGlzLl9kaXNhYmxlZFxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIGRpc2FibGVkIGZsYWcuXG4gICAqXG4gICAqIEBwYXJhbSB7Qm9vbGVhbn0gYm9vbFxuICAgKi9cbiAgc2V0IGRpc2FibGVkIChib29sKSB7XG4gICAgdGhpcy5fZGlzYWJsZWQgPSBib29sXG4gICAgdGhpcy5fdXBkYXRlSGFuZGxlcnMoYm9vbClcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSB0YXJnZXQgY29udGFpbmVyIHRoaXMgY29udHJvbCBpcyBhc3NpZ25lZCB0byBpbiB0aGUgRE9NLlxuICAgKlxuICAgKiBAcmV0dXJuIHtFbGVtZW50fVxuICAgKi9cbiAgZ2V0IHZpZXcoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2NvbnRhaW5lclxuICB9XG5cbn1cblxuZXhwb3J0IGRlZmF1bHQgQ29udHJvbFNsaWRlclxuXG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvanMvc3Vic2NyaWJlci9jb250cm9scy9zbGlkZXIuanMiLCIndXNlIHN0cmljdCdcblxuaW1wb3J0IEltcGxGYWN0b3J5T3JkZXIgZnJvbSAnLi4vdXRpbC9pbXBsLWZhY3Rvcnktb3JkZXInXG5pbXBvcnQgRXZlbnRFbWl0dGVyIGZyb20gJy4uL2NvcmUvZXZlbnQtZW1pdHRlcidcbmltcG9ydCBSVENTdWJzY3JpYmVyIGZyb20gJy4vcmVkNXByby1ydGMnXG5pbXBvcnQgUlRNUFN1YnNjcmliZXIgZnJvbSAnLi9yZWQ1cHJvLXJ0bXAnXG5pbXBvcnQgSExTU3Vic2NyaWJlciBmcm9tICcuL3JlZDVwcm8taGxzJ1xuXG5pbXBvcnQgeyBEZWZlcnJlZFByb21pc2UgfSBmcm9tICcuLi91dGlsL3Byb21pc2UnXG5pbXBvcnQgeyBQbGF5YmFja1R5cGVzIH0gZnJvbSAnLi4vZW51bS9wbGF5YmFjaydcbmltcG9ydCB7IGRlYnVnLCB3YXJuIH0gZnJvbSAnLi4vbG9nJ1xuXG5jb25zdCBOQU1FID0gJ1JlZDVQcm9TdWJzY3JpYmVyJ1xuXG5jb25zdCBwbGF5YmFja0ZhY3RvcnkgPSBuZXcgSW1wbEZhY3RvcnlPcmRlcigpXG5jb25zdCBwbGF5YmFja0ltcGwgPSAoZnVuY3Rpb24gKCkge1xuICBsZXQgbWFwID0gbmV3IE1hcCgpXG4gIG1hcC5zZXQoUGxheWJhY2tUeXBlcy5SVEMsIFJUQ1N1YnNjcmliZXIpXG4gIG1hcC5zZXQoUGxheWJhY2tUeXBlcy5SVE1QLCBSVE1QU3Vic2NyaWJlcilcbiAgbWFwLnNldChQbGF5YmFja1R5cGVzLkhMUywgSExTU3Vic2NyaWJlcilcbiAgcmV0dXJuIG1hcFxufSgpKVxuXG4vKipcbiAqIE1haW4gZW50cnkgZm9yIGZhaWxvdmVyIHN1cHBvcnQgb2YgYWxsIHN1YnNjcmliZXIgaW1wbGVtZW50YXRpb25zLlxuICpcbiAqIEBleHRlbmRzIEV2ZW50RW1pdHRlclxuICovXG5jbGFzcyBSZWQ1UHJvU3Vic2NyaWJlciBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG5cbiAgY29uc3RydWN0b3IgKCkge1xuICAgIHN1cGVyKClcbiAgICB0aGlzLl9vcHRpb25zID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fb3JkZXIgPSBbXG4gICAgICBQbGF5YmFja1R5cGVzLlJUQyxcbiAgICAgIFBsYXliYWNrVHlwZXMuUlRNUCxcbiAgICAgIFBsYXliYWNrVHlwZXMuSExTXG4gICAgXVxuICB9XG5cbiAgLyoqXG4gICAqIFV0aWxpemVzIEZhaWxvdmVyIFB1Ymxpc2hlciBGYWN0b3J5IHRvIGF0dGVtcHQgaW4gZGV0ZXJtaW5pbmcgYnJvd3NlciBzdXBwb3J0IGZvciBQdWJsaXNoZXIgZnJvbSBkZWZpbmVkIG9yZGVyLlxuICAgKlxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX2dldFBsYXliYWNrRnJvbU9yZGVyIChvcmRlciwgb3B0aW9ucykge1xuICAgIHJldHVybiBwbGF5YmFja0ZhY3RvcnkuY3JlYXRlKG9yZGVyLCBwbGF5YmFja0ltcGwsIG9wdGlvbnMsICdpbml0JylcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBzcGVjaWZpZWQgb3JkZXIgZm9yIGF1dG8tZmFpbG92ZXIuXG4gICAqXG4gICAqICBAcmV0dXJuIHtBcnJheX1cbiAgICogICAgICAgICAgRGVmYXVsdDogYFsncnRjJywgJ3J0bXAnLCAnaGxzJ11gLlxuICAgKi9cbiAgZ2V0UGxheWJhY2tPcmRlciAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX29yZGVyXG4gIH1cblxuICAvKipcbiAgICogRGVmaW5lcyB0aGUgZGVzaXJlZCBhdXRvLWZhaWxvdmVyIG9yZGVyLlxuICAgKlxuICAgKiAgQHBhcmFtIHtBcnJheX0gb3JkZXJcbiAgICogICAgICAgICAgVGhlIGRlc2lyZWQgb3JkZXIuIGUuZywgYFsncnRjJywgJ3J0bXAnLCAnaGxzJ11gLlxuICAgKi9cbiAgc2V0UGxheWJhY2tPcmRlciAob3JkZXIpIHtcbiAgICAvLyBBbGxvdyBmb3Igc3RyaW5nIHZhbHVlIHRvIGRlZmluZSBzaW5nbGUgaXRlbSBpbiBvcmRlci5cbiAgICBvcmRlciA9IHR5cGVvZiBvcmRlciA9PT0gJ3N0cmluZycgPyBbb3JkZXJdIDogb3JkZXJcblxuICAgIC8vIEZpbHRlciBvdXQgdmFsdWVzIG5vdCBhdmFpbGFibGUgaW4gZW51bWVyYXRpb24gb2YgcGxheWJhY2sgdHlwZXMuXG4gICAgY29uc3QgdCA9IG9yZGVyLmZpbHRlcihlbnRyeSA9PiB7XG4gICAgICBsZXQga2V5XG4gICAgICBmb3IgKGtleSBpbiBQbGF5YmFja1R5cGVzKSB7XG4gICAgICAgIGlmIChQbGF5YmFja1R5cGVzW2tleV0udG9Mb3dlckNhc2UoKSA9PT0gZW50cnkudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH0pLm1hcChlbnRyeSA9PiBlbnRyeS50b0xvd2VyQ2FzZSgpKVxuXG4gICAgLy8gRGVmaW5lIG5ldyBvcmRlci5cbiAgICB0aGlzLl9vcmRlciA9IFsuLi5uZXcgU2V0KHQpXVxuICAgIGRlYnVnKE5BTUUsIGBbb3JkZXJ1cGRhdGVdOiAke3RoaXMuX29yZGVyfWApXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIGluaXRpYWxpemUgYW5kIGRldGVybWluZSB0aGUgcHJvcGVyIFN1YnNjcmliZXIgaW1wbGVtZW50YXRpb24gYmFzZWQgb24gY29uZmlndXJhdGlvbi5cbiAgICpcbiAgICogVGhlIHJldHVybmVkIGBQcm9taXNlYCB3aWxsIGVpdGhlciByZXNvbHZlIHdpdGggdGhlIGRldGVybWluZWQgU3Vic2NyaWJlciBpbnN0YW5jZSBvciByZWplY3Qgd2l0aCBhbiBlcnJvciBTdHJpbmcgaW4gZmFpbHVyZSB0byBkZXRlcm1pbmUgU3Vic2NyaWJlciB0eXBlLlxuICAgKlxuICAgKiAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICogICAgICAgICAgVGhlIGluaXRpYWxpemF0aW9uIGNvbmZpZ3VyYXRpb24gbWFwIGZvciBlYWNoIGRlc2lyZWQgZmFpbG92ZXIgdGVjaC5cbiAgICogIEByZXR1cm4ge1Byb21pc2V9XG4gICAqL1xuICBpbml0IChvcHRpb25zKSB7XG4gICAgdGhpcy5fb3B0aW9ucyA9IG9wdGlvbnNcbiAgICBjb25zdCBkZWZlcnJlZCA9IG5ldyBEZWZlcnJlZFByb21pc2UoKVxuICAgIGRlYnVnKE5BTUUsICdbaW5pdF0nKVxuICAgIHRoaXMuX2dldFBsYXliYWNrRnJvbU9yZGVyKHRoaXMuX29yZGVyLCB0aGlzLl9vcHRpb25zKVxuICAgICAgLnRoZW4oc3Vic2NyaWJlciA9PiB7XG4gICAgICAgIGRlYnVnKE5BTUUsIGBbaW5pdDpzdWNjZXNzXTogc3Vic2NyaWJlciBmb3VuZCAke3N1YnNjcmliZXIuZ2V0VHlwZSgpfWApXG4gICAgICAgIGRlZmVycmVkLnJlc29sdmUoc3Vic2NyaWJlcilcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgd2FybihOQU1FLCBgW3BsYXllcnJvcl06IENvdWxkIG5vdCBpbXBsZW1lbnQgYSBzdWJzY3JpYmVyOiAke2Vycn1gKVxuICAgICAgICBkZWZlcnJlZC5yZWplY3QoZXJyKVxuICAgICAgfSlcbiAgICByZXR1cm4gZGVmZXJyZWQucHJvbWlzZVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiBlbnVtZXJhdGVkIHZhbHVlIFN1YnNjcmliZXIgdHlwZXMgdXNlZCBpbiBmYWlsb3ZlciBvcmRlci5cbiAgICogQHR5cGUge09iamVjdH1cbiAgICovXG4gIGdldCBwbGF5YmFja1R5cGVzICgpIHtcbiAgICByZXR1cm4gUGxheWJhY2tUeXBlc1xuICB9XG5cbn1cblxuZXhwb3J0IHsgUmVkNVByb1N1YnNjcmliZXIsIFJUQ1N1YnNjcmliZXIsIEhMU1N1YnNjcmliZXIsIFJUTVBTdWJzY3JpYmVyIH1cblxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2pzL3N1YnNjcmliZXIvaW5kZXguanMiLCIndXNlIHN0cmljdCdcblxuaW1wb3J0IGVudmlyb25tZW50IGZyb20gJy4uL2Vudi9icm93c2VyJ1xuaW1wb3J0ICogYXMgd2Vic29ja2V0IGZyb20gJy4uL2FkYXB0ZXIvd2Vic29ja2V0J1xuaW1wb3J0IFNvY2tldEhlbHBlciBmcm9tICcuLi9oZWxwZXIvc29ja2V0LWhlbHBlcidcbmltcG9ydCBITFNTb3VyY2VIYW5kbGVyIGZyb20gJy4vcmVkNXByby1zb3VyY2UtaGFuZGxlci1obHMnXG5pbXBvcnQgUGxheWJhY2tWaWV3IGZyb20gJy4uL3ZpZXcvcGxheWJhY2snXG5pbXBvcnQgeyBQbGF5YmFja0NvbnRyb2xsZXIgfSBmcm9tICcuL2NvbnRyb2xzL2luZGV4J1xuaW1wb3J0IHsgU3Vic2NyaWJlckV2ZW50IH0gZnJvbSAnLi4vZXZlbnQnXG5pbXBvcnQgeyBTdWJzY3JpYmVyRXZlbnRUeXBlcyB9IGZyb20gJy4uL2V2ZW50J1xuaW1wb3J0IHsgUGxheWJhY2tUeXBlcyB9IGZyb20gJy4uL2VudW0vcGxheWJhY2snXG5pbXBvcnQgeyBEZWZlcnJlZFByb21pc2UgfSBmcm9tICcuLi91dGlsL3Byb21pc2UnXG5pbXBvcnQgeyBkZWJ1Zywgd2FybiwgZXJyb3IgfSBmcm9tICcuLi9sb2cnXG5pbXBvcnQgeyBobHNTb2NrZXRFbmRwb2ludEZyb21PcHRpb25zIGFzIGVuZHBvaW50RnJvbU9wdGlvbnMgfSBmcm9tICcuLi91dGlsL3VybC1lbmRwb2ludCdcblxuY29uc3QgTkFNRSA9ICdITFNTdWJzY3JpYmVyJ1xuXG4vKipcbiAqIFNpbXBsZSBnZW5lcmF0aW9uIG9nIHVuaXF1ZSBzdWJzY3JpYmVyIGlkLlxuICpcbiAqIEByZXR1cm4ge1N0cmluZ31cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5jb25zdCBnZW5lcmF0ZVN1YnNjcmlwdGlvbklkID0gKCkgPT4ge1xuICBjb25zdCBpZCA9IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIDB4MTAwMDApLnRvU3RyaW5nKDE2KVxuICByZXR1cm4gYHN1YnNjcmliZXItJHtpZH1gXG59XG5cbi8vIERlZmF1bHQgdG8gc2VjdXJlIHNldHRpbmdzLlxuY29uc3QgZGVmYXVsdE9wdGlvbnMgPSB7XG4gIHByb3RvY29sOiAnaHR0cHMnLFxuICBwb3J0OiA0NDMsXG4gIGFwcDogJ2xpdmUnLFxuICBtaW1lVHlwZTogJ2FwcGxpY2F0aW9uL3gtbXBlZ1VSTCcsXG4gIG1lZGlhRWxlbWVudElkOiAncmVkNXByby1zdWJzY3JpYmVyJyxcbiAgYXV0b0xheW91dE9yaWVudGF0aW9uOiB0cnVlLFxuICBzdWJzY3JpcHRpb25JZDogZ2VuZXJhdGVTdWJzY3JpcHRpb25JZCgpXG59XG5cbi8qKlxuICogVXRpbCB0byByZXR1cm4gdGhlIGVuZHBvaW50IGZvciBhbiBITFMgdmlkZW8gZmlsZS5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICogICAgICAgIFRoZSBpbml0aWFsaXphdGlvbiBvYmplY3QuXG4gKiBAcmV0dXJuIHtTdHJpbmd9XG4gKlxuICogQHByaXZhdGVcbiAqL1xuY29uc3Qgb3B0aW9uc1RvSGxzVVJMID0gKG9wdGlvbnMpID0+IHtcbiAgY29uc3QgcHJvdG9jb2wgPSBvcHRpb25zLmhsc3Byb3RvY29sID8gb3B0aW9ucy5obHNwcm90b2NvbCA6IG9wdGlvbnMucHJvdG9jb2xcbiAgY29uc3QgcG9ydCA9IG9wdGlvbnMuaGxzcG9ydCA/IG9wdGlvbnMuaGxzcG9ydCA6IG9wdGlvbnMucG9ydFxuICBjb25zdCBhcHBFbmRwb2ludCA9IG9wdGlvbnMuY29udGV4dCA/IFtvcHRpb25zLmFwcCwgb3B0aW9ucy5jb250ZXh0XS5qb2luKCcvJykgOiBvcHRpb25zLmFwcFxuICByZXR1cm4gYCR7cHJvdG9jb2x9Oi8vJHtvcHRpb25zLmhvc3R9OiR7cG9ydH0vJHthcHBFbmRwb2ludH0vJHtvcHRpb25zLnN0cmVhbU5hbWV9Lm0zdThgXG59XG5cbi8qKlxuICogTWFpbiBlbnRyeSBmb3IgSExTLWJhc2VkIFN1YnNjcmliZXIuXG4gKlxuICogQGV4dGVuZHMgRXZlbnRFbWl0dGVyXG4gKiBAZXh0ZW5kcyBTdWJzY3JpYmVyUGxheWJhY2tDb250cm9sbGVyXG4gKi9cbmNsYXNzIEhMU1N1YnNjcmliZXIgZXh0ZW5kcyBQbGF5YmFja0NvbnRyb2xsZXIge1xuXG4gIGNvbnN0cnVjdG9yICgpIHtcbiAgICBzdXBlcigpXG4gICAgdGhpcy5fb3B0aW9ucyA9IHVuZGVmaW5lZFxuICAgIHRoaXMuX3ZpZXcgPSB1bmRlZmluZWRcbiAgICB0aGlzLl9zb3VyY2VIYW5kbGVyID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fc29ja2V0SGVscGVyID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fdmlld1Jlc29sdmVyID0gbmV3IERlZmVycmVkUHJvbWlzZSgpXG4gICAgdGhpcy5fc3Vic2NyaXB0aW9uUmVzb2x2ZXIgPSBuZXcgRGVmZXJyZWRQcm9taXNlKClcbiAgICB0aGlzLl9ib3VuZEJ1YmJsZVN1YnNjcmliZXJFdmVudHMgPSB0aGlzLmJ1YmJsZVN1YnNjcmliZXJFdmVudHMuYmluZCh0aGlzKVxuICB9XG5cbiAgX2dldFZpZXdSZXNvbHZlclByb21pc2UgKCkge1xuICAgIHJldHVybiB0aGlzLl92aWV3UmVzb2x2ZXIucHJvbWlzZVxuICB9XG5cbiAgX2dldFN1YnNjcmlwdGlvblJlc29sdmVyUHJvbWlzZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fc3Vic2NyaXB0aW9uUmVzb2x2ZXIucHJvbWlzZVxuICB9XG5cbiAgLyoqXG4gICAqIFByb3h5IGV2ZW50IGJ1YmJsZXIgdGhyb3VnaCBoYW5kbGVyIGluc3RhbmNlLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgYnViYmxlU3Vic2NyaWJlckV2ZW50cyAoZXZlbnQpIHtcbiAgICBpZiAoZXZlbnQudHlwZSA9PT0gU3Vic2NyaWJlckV2ZW50VHlwZXMuU1VCU0NSSUJFX1NUQVJUKSB7XG4gICAgICB0aGlzLl9zdWJzY3JpcHRpb25SZXNvbHZlci5yZXNvbHZlKHRoaXMpXG4gICAgfVxuICAgIHRoaXMudHJpZ2dlcihuZXcgU3Vic2NyaWJlckV2ZW50KGV2ZW50LnR5cGUsIHRoaXMsIGV2ZW50LmRhdGEpKVxuICB9XG5cbiAgLyoqXG4gICAqIEdsb21zIHRoZSBQbGF5YmFjayBDb250cm9scyBBUEkgb250byB0aGlzIGluc3RhbmNlIHRvIHByb3ZpZGUgZWFzZSBpbiB1c2UuXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBoYW5kbGVyXG4gICAqICAgICAgICBUaGUgbWV0aG9kIHJlcXVlc3QgaGFuZGxlciB0byBiaW5kIGFuZCBmb3J3YXJkIGNhbGxzIG9uLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX2dsb21Tb3VyY2VIYW5kbGVyQVBJIChoYW5kbGVyKSB7XG4gICAgdGhpcy5wbGF5ID0gaGFuZGxlci5wbGF5LmJpbmQoaGFuZGxlcilcbiAgICB0aGlzLnBhdXNlID0gaGFuZGxlci5wYXVzZS5iaW5kKGhhbmRsZXIpXG4gICAgdGhpcy5yZXN1bWUgPSBoYW5kbGVyLnJlc3VtZS5iaW5kKGhhbmRsZXIpXG4gICAgdGhpcy5zdG9wID0gaGFuZGxlci5zdG9wLmJpbmQoaGFuZGxlcilcbiAgICB0aGlzLm11dGUgPSBoYW5kbGVyLm11dGUuYmluZChoYW5kbGVyKVxuICAgIHRoaXMudW5tdXRlID0gaGFuZGxlci51bm11dGUuYmluZChoYW5kbGVyKVxuICAgIHRoaXMuc2V0Vm9sdW1lID0gaGFuZGxlci5zZXRWb2x1bWUuYmluZChoYW5kbGVyKVxuICAgIHRoaXMuc2Vla1RvID0gaGFuZGxlci5zZWVrVG8uYmluZChoYW5kbGVyKVxuICAgIHRoaXMudG9nZ2xlRnVsbFNjcmVlbiA9IGhhbmRsZXIudG9nZ2xlRnVsbFNjcmVlbi5iaW5kKGhhbmRsZXIpXG4gICAgaGFuZGxlci5vbignKicsIChldmVudCkgPT4ge1xuICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoZXZlbnQudHlwZSwgdGhpcywgZXZlbnQuZGF0YSkpXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBTdGlsbCBpbiB1c2UsIGJ1dCBob2xkLW92ZXIgb2YgcHJldmlvdXMgMy54IFNESyB2ZXJzaW9ucyBkZXNpZ25lZCB0byBwYWlyIHZpZXdzIGFuZCBzdWJzY3JpYmVycy4gSW4gNC4wLjAgaXQgaGFzIGJlZW4gaW50ZXJuYWxpemVkLlxuICAgKiBBUEkgZGVwcmVjYXRlZC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9zZXRWaWV3SWZOb3RFeGlzdCAoY3VycmVudFZpZXcsIG1lZGlhRWxlbWVudElkID0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAodHlwZW9mIGN1cnJlbnRWaWV3ID09PSAndW5kZWZpbmVkJyAmJiBtZWRpYUVsZW1lbnRJZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGxldCB2aWV3ID0gbmV3IFBsYXliYWNrVmlldyhtZWRpYUVsZW1lbnRJZClcbiAgICAgICAgdmlldy5hdHRhY2hTdWJzY3JpYmVyKHRoaXMpXG4gICAgICB9XG4gIH1cblxuICAvKipcbiAgICogQXR0ZW1wdCB0byBpbml0aWFsaXplIHRoZSBzdWJzY3JpcHRpb24gaGFuZGxlciBmb3IgSExTLlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICAgKiAgICAgICAgVGhlIGluaXRpYWxpemF0aW9uIGNvbmZpZ3VyYXRpb24uXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBoYW5kbGVyXG4gICAqICAgICAgICBUaGUgaGFuZGxlciBpbnN0YW5jZSB0aGF0IHdpbGwgbWFuYWdlIHZpZXcgaW50ZXJhY3Rpb24gYW5kIGV2ZW50cy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9pbml0SGFuZGxlciAob3B0aW9ucykge1xuICAgIGNvbnN0IHVybFJlZ2V4ID0gL15odHRwKHxzKS4qXFwubTN1OC9nXG4gICAgbGV0IHVybCA9IHRoaXMuX29wdGlvbnMuc3RyZWFtTmFtZS5tYXRjaCh1cmxSZWdleCkgPyB0aGlzLl9vcHRpb25zLnN0cmVhbU5hbWUgOiBvcHRpb25zVG9IbHNVUkwodGhpcy5fb3B0aW9ucylcbiAgICB0aGlzLl9zb3VyY2VIYW5kbGVyLm9uKCcqJywgdGhpcy5fYm91bmRCdWJibGVTdWJzY3JpYmVyRXZlbnRzKVxuICAgIHRoaXMuX3NvdXJjZUhhbmRsZXIuYWRkU291cmNlKHVybCwgb3B0aW9ucy5taW1lVHlwZSwgb3B0aW9ucylcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoU3Vic2NyaWJlckV2ZW50VHlwZXMuQ09OTkVDVF9TVUNDRVNTKSlcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgZXJyb3IoTkFNRSwgJ0NvdWxkIG5vdCBlc3RhYmxpc2ggYW4gSExTIFN1YnNjcmliZXI6ICcgKyBlcnIpXG4gICAgICAgIHRoaXMudHJpZ2dlcihuZXcgU3Vic2NyaWJlckV2ZW50KFN1YnNjcmliZXJFdmVudFR5cGVzLkNPTk5FQ1RfRkFJTFVSRSkpXG4gICAgICB9KVxuICB9XG5cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBpbml0aWFsaXplIHRoZSBITFMtYmFzZWQgU3Vic2NyaWJlciBiYXNlZCBvbiBjb25maWd1cmF0aW9uLlxuICAgKiBUaGUgcmV0dXJuZWQgYFByb21pc2VgIHdpbGwgZWl0aGVyIHJlc29sdmUgd2l0aCBhIHJlZmVyZW5jZSB0byB0aGlzIGluc3RhbmNlIG9yIHJlamVjdCB3aXRoIGFuIGVycm9yIGBTdHJpbmdgIGluIGZhaWx1cmUuXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqICAgICAgICBUaGUgaW5pdGlhbGl6YXRpb24gY29uZmlndXJhdGlvbiBtYXAuXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqL1xuICBpbml0IChvcHRpb25zKSB7XG4gICAgY29uc3QgZGVmZXJyZWQgPSBuZXcgRGVmZXJyZWRQcm9taXNlKClcbiAgICBpZiAoIWVudmlyb25tZW50LnN1cHBvcnRzSExTKCkpIHtcbiAgICAgIHdhcm4oTkFNRSwgYENvdWxkIG5vdCByZXNvbHZlIEhMU1N1YnNjcmliZXIgaW5zdGFuY2UuYClcbiAgICAgIGRlZmVycmVkLnJlamVjdChgQ291bGQgbm90IHJlc29sdmUgSExTU3Vic2NyaWJlciBpbnN0YW5jZS5gKVxuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5jb25uZWN0aW9uUGFyYW1zICYmICF3ZWJzb2NrZXQuaXNTdXBwb3J0ZWQoKSkge1xuICAgICAgLy8gSWYgYGNvbm5lY3Rpb25QYXJhbXNgIGFyZSBwcm92aWRlZCBpbiB0aGUgaW5pdCBjb25maWcsXG4gICAgICAvLyAgdGhlbiBhIHN1YnNlcXVlbnQgdmFsaWRhdGlvbiBjYWxsIGlzIG1hZGUgb24gYSBXZWJTb2NrZXQgdG8gXG4gICAgICAvLyAgZW5zdXJlIHRoYXQgdGhpcyBjbGllbnQgaXMgYWxsb3dlZCBhY2Nlc3MuXG4gICAgICB3YXJuKE5BTUUsIGBDb3VsZCBub3QgcmVzb2x2ZSBITFNTdWJzY3JpYmVyIGluc3RhbmNlIHdpdGggY29ubmVjdGlvbiBwYXJhbXMuIFdlYlNvY2tldCBzdXBwb3J0IGlzIHJlcXVpcmVkLmApXG4gICAgICBkZWZlcnJlZC5yZWplY3QoTkFNRSwgYENvdWxkIG5vdCByZXNvbHZlIEhMU1N1YnNjcmliZXIgaW5zdGFuY2Ugd2l0aCBjb25uZWN0aW9uIHBhcmFtcy4gV2ViU29ja2V0IHN1cHBvcnQgaXMgcmVxdWlyZWQuYClcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oe30sIGRlZmF1bHRPcHRpb25zLCBvcHRpb25zKVxuICAgICAgY29uc3Qgc29ja2V0UHJvbWlzZSA9IG5ldyBEZWZlcnJlZFByb21pc2UoKVxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMuY29ubmVjdGlvblBhcmFtcykge1xuICAgICAgICB0aGlzLl9zb2NrZXRIZWxwZXIgPSBuZXcgU29ja2V0SGVscGVyKHRoaXMsICdITFNTdWJzY3JpcHRpb25Tb2NrZXQnKVxuICAgICAgICBjb25zdCBzb2NrZXR1cmwgPSBlbmRwb2ludEZyb21PcHRpb25zKHRoaXMuX29wdGlvbnMsIHtcbiAgICAgICAgICBpZDogdGhpcy5fb3B0aW9ucy5zdWJzY3JpcHRpb25JZFxuICAgICAgICB9KVxuICAgICAgICB0aGlzLl9zb2NrZXRIZWxwZXIuc2V0VXAoc29ja2V0dXJsLCBzb2NrZXRQcm9taXNlKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc29ja2V0UHJvbWlzZS5yZXNvbHZlKClcbiAgICAgIH1cbiAgICAgIHNvY2tldFByb21pc2UucHJvbWlzZVxuICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgLy8gVGVhciBkb3duIHNvY2tldCBoZWxwZXIgaWYgZXhpc3RzLlxuICAgICAgICAgIC8vIFdlIG9ubHkgbmVlZGVkIGl0IHRvIGRvIHZhbGlkYXRpb24gd2l0aCBvcHRpb25hbCBjb25uZWN0aW9uUGFyYW1zLlxuICAgICAgICAgIGlmICh0aGlzLl9zb2NrZXRIZWxwZXIpIHtcbiAgICAgICAgICAgIHRoaXMuX3NvY2tldEhlbHBlci50ZWFyRG93bigpXG4gICAgICAgICAgICB0aGlzLl9zb2NrZXRIZWxwZXIgPSB1bmRlZmluZWRcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5fc2V0Vmlld0lmTm90RXhpc3QodGhpcy5fdmlldywgdGhpcy5fb3B0aW9ucy5tZWRpYUVsZW1lbnRJZClcbiAgICAgICAgICB0aGlzLl9nZXRWaWV3UmVzb2x2ZXJQcm9taXNlKClcbiAgICAgICAgICAgIC50aGVuKHZpZXcgPT4ge1xuICAgICAgICAgICAgICB0aGlzLl9zb3VyY2VIYW5kbGVyID0gbmV3IEhMU1NvdXJjZUhhbmRsZXIodmlldy52aWV3LCB0aGlzLmdldFR5cGUoKSlcbiAgICAgICAgICAgICAgdGhpcy5fZ2xvbVNvdXJjZUhhbmRsZXJBUEkodGhpcy5fc291cmNlSGFuZGxlcilcbiAgICAgICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9pbml0SGFuZGxlcih0aGlzLl9vcHRpb25zKVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgIGRlZmVycmVkLnJlc29sdmUodGhpcylcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICBkZWZlcnJlZC5yZWplY3QoZXJyb3IpXG4gICAgICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoU3Vic2NyaWJlckV2ZW50VHlwZXMuQ09OTkVDVF9GQUlMVVJFLCB0aGlzLCBlcnJvcikpXG4gICAgICAgIH0pXG4gICAgfVxuICAgIHJldHVybiBkZWZlcnJlZC5wcm9taXNlXG4gIH1cblxuICAvKipcbiAgICogU3RpbGwgaW4gdXNlIGZvciBhc3NpZ25pbmcgZG9jdW1lbnQgZWxlbWVudCB2aWV3IG1hbmFnZW1lbnQgdG8gdGhpcyBpbnN0YW5jZS5cbiAgICogQVBJIGRlcHJlY2F0ZWQgaW4gNC4wLjAuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBzZXRWaWV3ICh2aWV3KSB7XG4gICAgdGhpcy5fdmlldyA9IHZpZXdcbiAgICB0aGlzLl92aWV3UmVzb2x2ZXIucmVzb2x2ZSh2aWV3KVxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBiZWdpbiBzdWJzY3JpYmluZyB0byBhIHN0cmVhbS5cbiAgICpcbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICAgICAgICAgVGhlIHJldHVybmVkIGBQcm9taXNlYCB3aWxsIHJlc29sdmUgb3IgcmVqZWN0IG9uIHN1Y2Nlc3NmdWwgc3RhcnQgb2YgcGxheWJhY2suXG4gICAqL1xuICBzdWJzY3JpYmUgKCkge1xuICAgIHJldHVybiB0aGlzLl9nZXRTdWJzY3JpcHRpb25SZXNvbHZlclByb21pc2UoKVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gc3RvcCBhIHN1YnNjcmlwdGlvbi5cbiAgICogVGhlIHJldHVybmVkIGBQcm9taXNlYCB3aWxsIGVpdGhlciByZXNvbHZlIG9yIHJlamVjdCBvbiBzdWNjZXNzZnVsIHN0b3Agb2Ygc3Vic2NyaXB0aW9uLlxuICAgKlxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKi9cbiAgdW5zdWJzY3JpYmUgKCkge1xuICAgIGRlYnVnKE5BTUUsICdbdW5zY3Vic2NyaWJlXScpXG4gICAgY29uc3QgZGVmZXJyZWQgPSBuZXcgRGVmZXJyZWRQcm9taXNlKClcbiAgICBpZiAodGhpcy5fc29ja2V0SGVscGVyKSB7XG4gICAgICB0aGlzLl9zb2NrZXRIZWxwZXIudGVhckRvd24oKVxuICAgIH1cbiAgICB0cnkge1xuICAgICAgdGhpcy5fc291cmNlSGFuZGxlci5zdG9wKClcbiAgICAgIHRoaXMuX3NvdXJjZUhhbmRsZXIuZGlzY29ubmVjdCgpXG4gICAgICBkZWZlcnJlZC5yZXNvbHZlKClcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBkZWZlcnJlZC5yZWplY3QoZS5tZXNzYWdlKVxuICAgIH1cbiAgICByZXR1cm4gZGVmZXJyZWQucHJvbWlzZVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgY29ubmVjdGlvbiBoYW5kbGVyIGZvciBwbGF5YmFjay5cbiAgICpcbiAgICogQHJldHVybiB7T2JqZWN0fVxuICAgKi9cbiAgZ2V0Q29ubmVjdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3NvdXJjZUhhbmRsZXJcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHJlZmVyZW5jZSB0byBwbGF5YmFjayBjb250cm9scyBpZiBhdmFpbGFibGUuXG4gICAqXG4gICAqIEByZXR1cm4ge1BsYXliYWNrQ29udHJvbHN9XG4gICAqL1xuICBnZXRDb250cm9scyAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3NvdXJjZUhhbmRsZXIgPyB0aGlzLl9zb3VyY2VIYW5kbGVyLmdldENvbnRyb2xzKCkgOiB1bmRlZmluZWRcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBpbml0aWFsaXphdGlvbiBjb25maWd1cmF0aW9uIHVzZWQgaW4gYGluaXQoKWAuXG4gICAqXG4gICAqIEByZXR1cm4ge09iamVjdH1cbiAgICovXG4gIGdldE9wdGlvbnMgKCkge1xuICAgIHJldHVybiB0aGlzLl9vcHRpb25zXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgdGFyZ2V0IHZpZXcgRWxlbWVudC5cbiAgICpcbiAgICogQHJldHVybiB7RWxlbWVudH1cbiAgICovXG4gIGdldFBsYXllciAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3ZpZXcudmlld1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHR5cGUgb2YgaW1wbGVtZW50YXRpb246IGBSVENgLlxuICAgKlxuICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAqL1xuICBnZXRUeXBlICgpIHtcbiAgICByZXR1cm4gUGxheWJhY2tUeXBlcy5ITFMudG9VcHBlckNhc2UoKVxuICB9XG5cbn1cblxuZXhwb3J0IGRlZmF1bHQgSExTU3Vic2NyaWJlclxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2pzL3N1YnNjcmliZXIvcmVkNXByby1obHMuanMiLCIndXNlIHN0cmljdCdcblxuaW1wb3J0IGVudmlyb25tZW50IGZyb20gJy4uL2Vudi9icm93c2VyJ1xuaW1wb3J0IHsgYXBwbHlPcmllbnRhdGlvbiB9IGZyb20gJy4uL2Vudi90cmFuc2xhdGlvbi11dGlsJ1xuaW1wb3J0ICogYXMgd2VicnRjIGZyb20gJy4uL2FkYXB0ZXIvd2VicnRjJ1xuaW1wb3J0ICogYXMgd2Vic29ja2V0IGZyb20gJy4uL2FkYXB0ZXIvd2Vic29ja2V0J1xuaW1wb3J0IFJUQ1NvdXJjZUhhbmRsZXIgZnJvbSAnLi9yZWQ1cHJvLXNvdXJjZS1oYW5kbGVyLXJ0YydcbmltcG9ydCBTdWJzY3JpcHRpb25Tb2NrZXRIZWxwZXIgZnJvbSAnLi4vaGVscGVyL3NvY2tldC1oZWxwZXItc3ViJ1xuaW1wb3J0IFN1YnNjcmlwdGlvblBlZXJIZWxwZXIgZnJvbSAnLi4vaGVscGVyL3dlYnJ0Yy1oZWxwZXItc3ViJ1xuaW1wb3J0IFBsYXliYWNrVmlldyBmcm9tICcuLi92aWV3L3BsYXliYWNrJ1xuaW1wb3J0IHsgUGxheWJhY2tDb250cm9sbGVyIH0gZnJvbSAnLi9jb250cm9scydcbmltcG9ydCB7IG1ldGFkYXRhUmVzb2x1dGlvblRvT2JqZWN0IH0gZnJvbSAnLi4vdXRpbC9vYmplY3QnXG5pbXBvcnQgeyBydGNTb2NrZXRFbmRwb2ludEZyb21PcHRpb25zIGFzIGVuZHBvaW50RnJvbU9wdGlvbnMgfSBmcm9tICcuLi91dGlsL3VybC1lbmRwb2ludCdcbmltcG9ydCB7IFN1YnNjcmliZXJFdmVudCB9IGZyb20gJy4uL2V2ZW50J1xuaW1wb3J0IHtcbiAgUGxheWJhY2tUeXBlcyxcbiAgUGxheWJhY2tBdWRpb0VuY29kZXIsXG4gIFBsYXliYWNrVmlkZW9FbmNvZGVyXG59IGZyb20gJy4uL2VudW0vcGxheWJhY2snXG5pbXBvcnQgeyBJY2VUcmFuc3BvcnRUeXBlcyB9IGZyb20gJy4uL2VudW0vd2VicnRjJ1xuaW1wb3J0IHsgRGVmZXJyZWRQcm9taXNlIH0gZnJvbSAnLi4vdXRpbC9wcm9taXNlJ1xuaW1wb3J0IHsgU3Vic2NyaWJlckV2ZW50VHlwZXMsIFJUQ1N1YnNjcmliZXJFdmVudFR5cGVzIH0gZnJvbSAnLi4vZXZlbnQnXG5pbXBvcnQgeyBkZWJ1Zywgd2FybiwgZXJyb3IgfSBmcm9tICcuLi9sb2cnXG5cbmNvbnN0IHN1YlN0YXJ0UmVnZXggPSAvKC4qKSBzdGFydGluZy9pXG5jb25zdCBOQU1FID0gJ1JUQ1N1YnNjcmliZXInXG5cbi8qKlxuICogU2ltcGxlIGdlbmVyYXRpb24gb2cgdW5pcXVlIHN1YnNjcmliZXIgaWQuXG4gKlxuICogQHJldHVybiB7U3RyaW5nfVxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmNvbnN0IGdlbmVyYXRlU3Vic2NyaXB0aW9uSWQgPSAoKSA9PiB7XG4gIGNvbnN0IGlkID0gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogMHgxMDAwMCkudG9TdHJpbmcoMTYpXG4gIHJldHVybiBgc3Vic2NyaWJlci0ke2lkfWBcbn1cblxuLy8gRGVmYXVsdCB0byBzZWN1cmUgc2V0dGluZ3MuXG5jb25zdCBkZWZhdWx0T3B0aW9ucyA9IHtcbiAgcHJvdG9jb2w6ICd3c3MnLFxuICBwb3J0OiA4MDgzLFxuICBhcHA6ICdsaXZlJyxcbiAgYXV0b0xheW91dE9yaWVudGF0aW9uOiB0cnVlLFxuICBtZWRpYUVsZW1lbnRJZDogJ3JlZDVwcm8tc3Vic2NyaWJlcicsXG4gIGljZVNlcnZlcnM6IFt7dXJsczogJ3N0dW46c3R1bjIubC5nb29nbGUuY29tOjE5MzAyJ31dLFxuICBpY2VUcmFuc3BvcnQ6IEljZVRyYW5zcG9ydFR5cGVzLlVEUCxcbiAgbWFpbnRhaW5Db25uZWN0aW9uT25TdWJzY3JpYmVFcnJvcnM6IGZhbHNlXG59XG5cblxuLyoqXG4gKiBNYWluIGVudHJ5IGZvciBXZWJSVEMtYmFzZWQgU3Vic2NyaWJlci5cbiAqXG4gKiBAZXh0ZW5kcyBFdmVudEVtaXR0ZXJcbiAqIEBleHRlbmRzIFN1YnNjcmliZXJQbGF5YmFja0NvbnRyb2xsZXJcbiAqL1xuY2xhc3MgUlRDU3Vic2NyaWJlciBleHRlbmRzIFBsYXliYWNrQ29udHJvbGxlciB7XG5cbiAgY29uc3RydWN0b3IgKCkge1xuICAgIHN1cGVyKClcbiAgICB0aGlzLl92aWV3ID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fb3B0aW9ucyA9IHVuZGVmaW5lZFxuICAgIHRoaXMuX3BlZXJIZWxwZXIgPSB1bmRlZmluZWRcbiAgICB0aGlzLl9zb2NrZXRIZWxwZXIgPSB1bmRlZmluZWRcbiAgICB0aGlzLl9jb25uZWN0aW9uQ2xvc2VkID0gdHJ1ZVxuICAgIHRoaXMuX3NvdXJjZUhhbmRsZXIgPSB1bmRlZmluZWRcbiAgICB0aGlzLl9tZWRpYVN0cmVhbSA9IHVuZGVmaW5lZFxuICAgIHRoaXMuX3ZpZXdSZXNvbHZlciA9IG5ldyBEZWZlcnJlZFByb21pc2UoKVxuICAgIHRoaXMuX2F2YWlsYWJpbGl0eVJlc29sdmVyID0gbmV3IERlZmVycmVkUHJvbWlzZSgpXG4gICAgdGhpcy5fc3Vic2NyaXB0aW9uUmVzb2x2ZXIgPSBuZXcgRGVmZXJyZWRQcm9taXNlKClcbiAgICB0aGlzLl9vcmllbnRhdGlvbiA9IDBcbiAgfVxuXG4gIF9nZXRWaWV3UmVzb2x2ZXJQcm9taXNlICgpIHtcbiAgICByZXR1cm4gdGhpcy5fdmlld1Jlc29sdmVyLnByb21pc2VcbiAgfVxuXG4gIF9nZXRBdmFpbGFiaWxpdHlSZXNvbHZlclByb21pc2UgKCkge1xuICAgIHJldHVybiB0aGlzLl9hdmFpbGFiaWxpdHlSZXNvbHZlci5wcm9taXNlXG4gIH1cblxuICBfZ2V0U3Vic2NyaXB0aW9uUmVzb2x2ZXJQcm9taXNlKCkge1xuICAgIHJldHVybiB0aGlzLl9zdWJzY3JpcHRpb25SZXNvbHZlci5wcm9taXNlXG4gIH1cblxuICAvKipcbiAgICogR2xvbXMgdGhlIFBsYXliYWNrIENvbnRyb2xzIEFQSSBvbnRvIHRoaXMgaW5zdGFuY2UgdG8gcHJvdmlkZSBlYXNlIGluIHVzZS5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGhhbmRsZXJcbiAgICogICAgICAgIFRoZSBtZXRob2QgcmVxdWVzdCBoYW5kbGVyIHRvIGJpbmQgYW5kIGZvcndhcmQgY2FsbHMgb24uXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfZ2xvbVNvdXJjZUhhbmRsZXJBUEkgKGhhbmRsZXIpIHtcbiAgICB0aGlzLnBsYXkgPSBoYW5kbGVyLnBsYXkuYmluZChoYW5kbGVyKVxuICAgIHRoaXMucGF1c2UgPSBoYW5kbGVyLnBhdXNlLmJpbmQoaGFuZGxlcilcbiAgICB0aGlzLnJlc3VtZSA9IGhhbmRsZXIucmVzdW1lLmJpbmQoaGFuZGxlcilcbiAgICB0aGlzLnN0b3AgPSBoYW5kbGVyLnN0b3AuYmluZChoYW5kbGVyKVxuICAgIHRoaXMubXV0ZSA9IGhhbmRsZXIubXV0ZS5iaW5kKGhhbmRsZXIpXG4gICAgdGhpcy51bm11dGUgPSBoYW5kbGVyLnVubXV0ZS5iaW5kKGhhbmRsZXIpXG4gICAgdGhpcy5zZXRWb2x1bWUgPSBoYW5kbGVyLnNldFZvbHVtZS5iaW5kKGhhbmRsZXIpXG4gICAgdGhpcy5zZWVrVG8gPSBoYW5kbGVyLnNlZWtUby5iaW5kKGhhbmRsZXIpXG4gICAgdGhpcy50b2dnbGVGdWxsU2NyZWVuID0gaGFuZGxlci50b2dnbGVGdWxsU2NyZWVuLmJpbmQoaGFuZGxlcilcbiAgICBoYW5kbGVyLm9uKCcqJywgKGV2ZW50KSA9PiB7XG4gICAgICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChldmVudC50eXBlLCB0aGlzLCBldmVudC5kYXRhKSlcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFN0aWxsIGluIHVzZSwgYnV0IGhvbGQtb3ZlciBvZiBwcmV2aW91cyAzLnggU0RLIHZlcnNpb25zIGRlc2lnbmVkIHRvIHBhaXIgdmlld3MgYW5kIHN1YnNjcmliZXJzLiBJbiA0LjAuMCBpdCBoYXMgYmVlbiBpbnRlcm5hbGl6ZWQuXG4gICAqIEFQSSBkZXByZWNhdGVkLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX3NldFZpZXdJZk5vdEV4aXN0IChjdXJyZW50VmlldywgbWVkaWFFbGVtZW50SWQgPSB1bmRlZmluZWQpIHtcbiAgICAgIGlmICh0eXBlb2YgY3VycmVudFZpZXcgPT09ICd1bmRlZmluZWQnICYmIG1lZGlhRWxlbWVudElkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbGV0IHZpZXcgPSBuZXcgUGxheWJhY2tWaWV3KG1lZGlhRWxlbWVudElkKVxuICAgICAgICB2aWV3LmF0dGFjaFN1YnNjcmliZXIodGhpcylcbiAgICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBdHRlbXB0IHRvIGluaXRpYWxpemUgdGhlIHN1YnNjcmlwdGlvbiBoYW5kbGVyIGZvciBXZWJSVEMuXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqICAgICAgICBUaGUgaW5pdGlhbGl6YXRpb24gY29uZmlndXJhdGlvbi5cbiAgICogQHBhcmFtIHtPYmplY3R9IGhhbmRsZXJcbiAgICogICAgICAgIFRoZSBoYW5kbGVyIGluc3RhbmNlIHRoYXQgd2lsbCBtYW5hZ2UgdmlldyBpbnRlcmFjdGlvbiBhbmQgZXZlbnRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX2luaXRIYW5kbGVyIChvcHRpb25zLCBoYW5kbGVyKSB7XG4gICAgaWYgKG9wdGlvbnMgJiYgaGFuZGxlcikge1xuICAgICAgaGFuZGxlci5vbignKicsIHRoaXMuX2JvdW5kQnViYmxlU3Vic2NyaWJlckV2ZW50cylcbiAgICAgIGhhbmRsZXIuYWRkU291cmNlKG9wdGlvbnMpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgYXZhaWxhYmxlIHN0cmVhbSBieSBuYW1lIG9uIHNlcnZlciB0aHJvdWdoIFdlYlNvY2tldCByZXF1ZXN0LlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyZWFtTmFtZVxuICAgKiAgICAgICAgVGhlIG5hbWUgb2YgdGhlIHN0cmVhbSB0byBsb29rIHVwLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX3JlcXVlc3RBdmFpbGFiaWxpdHkgKHN0cmVhbU5hbWUpIHtcbiAgICBkZWJ1ZyhOQU1FLCAnW3JlcXVlc3RhdmFpbGFiaWxpdHldJylcbiAgICAvLyBtZXNzYWdlIG9uIHNvY2tldCByZXR1cm5zIC0+IG9uU3RyZWFtKFVuKUF2YWlsYWJsZVxuICAgIHRoaXMuX3NvY2tldEhlbHBlci5wb3N0KHtcbiAgICAgIGlzQXZhaWxhYmxlOiBzdHJlYW1OYW1lXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IG9mZmVyIG92ZXIgV2ViU29ja2V0LlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyZWFtTmFtZVxuICAgKiAgICAgICAgVGhlIG5hbWUgb2YgdGhlIHN0cmVhbSB0byBzdWJzY3JpYmUgdG8uXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzdWJzY3JpcHRpb25JZFxuICAgKiAgICAgICAgVGhlIHVuaXF1ZSBpZCBvZiB0aGlzIHN1YnNjcmliZXIuXG4gICAqIEBwYXJhbSB7U3RyaW5nfSB2RW5jb2RpbmdcbiAgICogICAgICAgIE9wdGlvbmFsIGVuY29kaW5nIHR5cGUgZm9yIHZpZGVvLiBEZWZhdWx0cyB0byBzZXJ2ZXIgc2VsZWN0aW9uLlxuICAgKiBAcGFyYW0ge1N0cmluZ30gYUVuY29kaW5nXG4gICAqICAgICAgICBPcHRpb25hbCBlbmNvZGluZyB0eXBlIGZvciBhdWRpby4gRGVmYXVsdHMgdG8gc2VydmVyIHNlbGVjdGlvbi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9yZXF1ZXN0T2ZmZXIgKHN0cmVhbU5hbWUsIHN1YnNjcmlwdGlvbklkLCB0cmFuc3BvcnQsIHZFbmNvZGluZyA9IHVuZGVmaW5lZCwgYUVuY29kaW5nID0gdW5kZWZpbmVkKSB7XG4gICAgZGVidWcoTkFNRSwgJ1tyZXF1ZXN0b2ZmZXJdJylcbiAgICBsZXQgb2ZmZXIgPSB7XG4gICAgICByZXF1ZXN0T2ZmZXI6IHN0cmVhbU5hbWUsXG4gICAgICByZXF1ZXN0SWQ6IHN1YnNjcmlwdGlvbklkLFxuICAgICAgdHJhbnNwb3J0OiB0cmFuc3BvcnRcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB2RW5jb2RpbmcgIT09ICd1bmRlZmluZWQnICYmIHZFbmNvZGluZyAhPT0gUGxheWJhY2tWaWRlb0VuY29kZXIuTk9ORSkge1xuICAgICAgb2ZmZXIudmlkZW9FbmNvZGluZyA9IHZFbmNvZGluZztcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBhRW5jb2RpbmcgIT09ICd1bmRlZmluZWQnICYmIGFFbmNvZGluZyAhPT0gUGxheWJhY2tBdWRpb0VuY29kZXIuTk9ORSkge1xuICAgICAgb2ZmZXIuYXVkaW9FbmNvZGluZyA9IGFFbmNvZGluZztcbiAgICB9XG4gICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoUlRDU3Vic2NyaWJlckV2ZW50VHlwZXMuT0ZGRVJfU1RBUlQsIHRoaXMpKVxuICAgIC8vIG1lc3NhZ2Ugb24gc29ja2V0IHJldHVybnMgLT4gb25TRFBPZmZlclxuICAgIHRoaXMuX3NvY2tldEhlbHBlci5wb3N0KG9mZmVyKVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYW5kIHNlbmRzIGFuIGFuc3dlciBiYXNlZCBvbiBwcm92aWRlZCBTRFAuXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBzZHBcbiAgICogICAgICAgIFRoZSBTRFAgb2JqZWN0IHRvIHVzZSBpbiBjcmVhdGluZyBhbiBTRFAgYW5zd2VyIHRvIHNlbmQgYmFjay5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9yZXF1ZXN0QW5zd2VyIChzZHApIHtcbiAgICBkZWJ1ZyhOQU1FLCAnW3JlcXVlc3RhbnN3ZXJdJylcbiAgICAvLyBpbnZva2VzIC0+IHNlbmRBbnN3ZXJcbiAgICB0aGlzLl9wZWVySGVscGVyLmNyZWF0ZUFuc3dlcihzZHApXG4gICAgICAgIC50aGVuKHNlc3Npb25EZXNjcmlwdGlvbiA9PiB7XG4gICAgICAgICAgZGVidWcoTkFNRSwgJ1tvbmFuc3dlcmNyZWF0ZWRdJylcbiAgICAgICAgICBkZWJ1ZyhOQU1FLCAnWz4gc2VuZGFuc3dlcl0nKVxuICAgICAgICAgIHRoaXMuX3NlbmRBbnN3ZXIodGhpcy5fb3B0aW9ucy5zdHJlYW1OYW1lLCB0aGlzLl9vcHRpb25zLnN1YnNjcmlwdGlvbklkLCBzZXNzaW9uRGVzY3JpcHRpb24pXG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgdGhpcy5vblNEUEVycm9yKGVycm9yKVxuICAgICAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFBvc3RzIFNEUCBhbnN3ZXIgdG8gc2VydmVyIG92ZXIgV2ViU29ja2V0LlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyZWFtTmFtZVxuICAgKiAgICAgICAgVGhlIHRhcmdldCBzdHJlYW0gbmFtZS5cbiAgICogQHBhcmFtIHtTdHJpbmd9IHN1YnNjcmlwdGlvbklkXG4gICAqICAgICAgICBUaGUgdW5pcXVlIGlkIG9mIHRoaXMgc3Vic2NyaWJlci5cbiAgICogQHBhcmFtIHtPYmplY3R9IHNkcFxuICAgKiAgICAgICAgVGhlIFNEUCB0byBzZW5kIGFzIGFuIGFuc3dlci5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9zZW5kQW5zd2VyIChzdHJlYW1OYW1lLCBzdWJzY3JpcHRpb25JZCwgc2RwKSB7XG4gICAgZGVidWcoTkFNRSwgYFtzZW5kYW5zd2VyXTogc3RyZWFtbmFtZSgke3N0cmVhbU5hbWV9KSwgc3Vic2NyaXB0aW9uaWQoJHtzdWJzY3JpcHRpb25JZH0pYClcbiAgICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChSVENTdWJzY3JpYmVyRXZlbnRUeXBlcy5BTlNXRVJfU1RBUlQsIHRoaXMsIHNkcCkpXG4gICAgLy8gbWVzc2FnZSBvbiBzb2NrZXQgcmVzcG9uc2UgLT4gb25BZGRJY2VDYW5kaWRhdGVcbiAgICAvLyBtZXNzYWdlIG9uIHBlZXIgcmVzcG9uc2UgLT4gb25hZGRzdHJlYW1cbiAgICB0aGlzLl9zb2NrZXRIZWxwZXIucG9zdCh7XG4gICAgICBoYW5kbGVBbnN3ZXI6IHN0cmVhbU5hbWUsXG4gICAgICByZXF1ZXN0SWQ6IHN1YnNjcmlwdGlvbklkLFxuICAgICAgZGF0YToge1xuICAgICAgICBzZHA6IHNkcFxuICAgICAgfVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogU2VuZHMgYSBjYW5kaWRhdGUgdG8gdGhlIHNlcnZlciBvdmVyIFdlYlNvY2tldC5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGNhbmRpZGF0ZVxuICAgKiAgICAgICAgVGhlIHBlZXIgY2FuZGlkYXRlIGRlc2NyaXB0aW9uLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX3NlbmRDYW5kaWRhdGUgKGNhbmRpZGF0ZSkge1xuICAgIGRlYnVnKE5BTUUsICdbc2VuZGNhbmRpZGF0ZV0nKVxuICAgIHRoaXMudHJpZ2dlcihuZXcgU3Vic2NyaWJlckV2ZW50KFJUQ1N1YnNjcmliZXJFdmVudFR5cGVzLkNBTkRJREFURV9TVEFSVCwgdGhpcywgY2FuZGlkYXRlKSlcbiAgICAvLyBtZXNzYWdlIG9uIHBlZXIgcmVzcG9uc2UgLT4gb25pY2VjYW5kaWRhdGVcbiAgICB0aGlzLl9zb2NrZXRIZWxwZXIucG9zdCh7XG4gICAgICBoYW5kbGVDYW5kaWRhdGU6IHRoaXMuX29wdGlvbnMuc3RyZWFtTmFtZSxcbiAgICAgIHJlcXVlc3RJZDogdGhpcy5fb3B0aW9ucy5zdWJzY3JpcHRpb25JZCxcbiAgICAgIGRhdGE6IHtcbiAgICAgICAgY2FuZGlkYXRlOiBjYW5kaWRhdGVcbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHVwIGFuZCBjb25uZWN0IHRvIGJlZ2luIGEgc3Vic2NyaXB0aW9uLlxuICAgKiBUaGlzIGlzIGludm9rZWQgb25jZSB0aGUgYXZhaWxhYmlsaXR5IG9mIHRoZSBzdHJlYW0gaXMgcmVjb2duaXplZCBvbiB0aGUgc2VydmVyIGFuZCBub3RpZmllZCBvbiB0aGlzIGluc3RhbmNlLlxuICAgKlxuICAgKiBAcGFyYW0ge0FycmF5fSBpY2VTZXJ2ZXJzXG4gICAqICAgICAgICBUaGUgSUNFIHNlcnZlciBsaXN0IHRvIHVzZSBpbiB0cmlja2xlLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX2Nvbm5lY3QgKGljZVNlcnZlcnMpIHtcbiAgICBkZWJ1ZyhOQU1FLCAnW2Nvbm5lY3RdJylcbiAgICB0aGlzLl9vcHRpb25zLmljZVNlcnZlcnMgPSBpY2VTZXJ2ZXJzXG4gICAgY29uc3QgcCA9IHRoaXMuX3BlZXJIZWxwZXIuc2V0VXAodGhpcy5fb3B0aW9ucy5pY2VTZXJ2ZXJzLCB1bmRlZmluZWQsIHRoaXMuX29wdGlvbnMucnRjcE11eFBvbGljeSlcbiAgICBwLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChSVENTdWJzY3JpYmVyRXZlbnRUeXBlcy5QRUVSX0NPTk5FQ1RJT05fQVZBSUxBQkxFLCB0aGlzLCBjb25uZWN0aW9uKSlcbiAgICAgIHRoaXMuX3JlcXVlc3RPZmZlcih0aGlzLl9vcHRpb25zLnN0cmVhbU5hbWUsIHRoaXMuX29wdGlvbnMuc3Vic2NyaXB0aW9uSWQsIHRoaXMuX29wdGlvbnMuaWNlVHJhbnNwb3J0LCB0aGlzLl9vcHRpb25zLnZpZGVvRW5jb2RpbmcsIHRoaXMuX29wdGlvbnMuYXVkaW9FbmNvZGluZylcbiAgICB9KVxuICAgIC5jYXRjaCgoKSA9PiB7XG4gICAgICB3YXJuKE5BTUUsICdDb3VsZCBub3QgZXN0YWJsaXNoIFJUQ1BlZXJDb25uZWN0aW9uLicpXG4gICAgICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChTdWJzY3JpYmVyRXZlbnRUeXBlcy5DT05ORUNUX0ZBSUxVUkUsIHRoaXMpKVxuICAgIH0pXG4gICAgLy8gIFRPRE86IE5vcm1hbGl6ZSByZXR1cm5zIHRvIGVpdGhlciBhbGwgYmUgY2hhaW5hYmxlIG9yIG5vdCBiZSBjaGFpbmFibGVcbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgLyoqXG4gICAqIERpc2Nvbm5lY3QgYW5kIHRlYXJkb3duIGFmdGVyIGNsb3NlIG9mIHN1YnNjcmlwdGlvbi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9kaXNjb25uZWN0ICgpIHtcbiAgICBpZiAodGhpcy5fc29ja2V0SGVscGVyKSB7XG4gICAgICBkZWJ1ZyhOQU1FLCAnW2Rpc2Nvbm5lY3Q6c29ja2V0XScpXG4gICAgICB0aGlzLl9zb2NrZXRIZWxwZXIudGVhckRvd24oKVxuICAgIH1cbiAgICBpZiAodGhpcy5fcGVlckhlbHBlcikge1xuICAgICAgZGVidWcoTkFNRSwgJ1tkaXNjb25uZWN0OnBlZXJdJylcbiAgICAgIHRoaXMuX3BlZXJIZWxwZXIudGVhckRvd24oKVxuICAgIH1cbiAgICBpZiAodGhpcy5fc291cmNlSGFuZGxlcikge1xuICAgICAgZGVidWcoTkFNRSwgJ1tkaXNjb25uZWN0OnNvdXJjZV0nKVxuICAgICAgdGhpcy5fc291cmNlSGFuZGxlci5kaXNjb25uZWN0KClcbiAgICB9XG4gICAgdGhpcy5fY29ubmVjdGlvbkNsb3NlZCA9IHRydWVcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIGtpY2sgb2ZmIGF1dG9wbGF5IGlmIHNldHRpbmcgaXMgZmxhZ2dlZC5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICogICAgICAgIFRoZSBpbml0aWFsaXphdGlvbiBvYmplY3QuXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gdmlld1xuICAgKiAgICAgICAgVGhlIHRhcmdldCBlbGVtZW50IHZpZXcgdGhhdCB3aWxsIHBsYXliYWNrIHRoZSBzdHJlYW0uXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfcGxheUlmQXV0b3BsYXlTZXQgKG9wdGlvbnMsIHZpZXcpIHtcbiAgICBpZiAob3B0aW9ucyAmJiB2aWV3KSB7XG4gICAgICBvcHRpb25zLmF1dG9wbGF5ID0gZW52aXJvbm1lbnQuaGFzQXR0cmlidXRlRGVmaW5lZCh2aWV3LnZpZXcsICdhdXRvcGxheScpXG4gICAgICBpZiAob3B0aW9ucy5hdXRvcGxheSkge1xuICAgICAgICB0aGlzLnBsYXkoKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIGJlZ2luIHN1YnNjcmlwdGlvbiBvbiBzZXJ2ZXIgb3ZlciBXZWJTb2NrZXQuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfc2VuZFN1YnNjcmliZSAoKSB7XG4gICAgZGVidWcoTkFNRSwgJ1tzZW5kc3Vic2NyaWJlXScpXG4gICAgdGhpcy5fc29ja2V0SGVscGVyLnBvc3Qoe1xuICAgICAgc3Vic2NyaWJlOiB0aGlzLl9vcHRpb25zLnN0cmVhbU5hbWUsXG4gICAgICByZXF1ZXN0SWQ6IHRoaXMuX29wdGlvbnMuc3Vic2NyaXB0aW9uSWRcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gaW5pdGlhbGl6ZSB0aGUgV2ViUlRDLWJhc2VkIFN1YnNjcmliZXIgYmFzZWQgb24gY29uZmlndXJhdGlvbi5cbiAgICogVGhlIHJldHVybmVkIGBQcm9taXNlYCB3aWxsIGVpdGhlciByZXNvbHZlIHdpdGggYSByZWZlcmVuY2UgdG8gdGhpcyBpbnN0YW5jZSBvciByZWplY3Qgd2l0aCBhbiBlcnJvciBgU3RyaW5nYCBpbiBmYWlsdXJlLlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICAgKiAgICAgICAgVGhlIGluaXRpYWxpemF0aW9uIGNvbmZpZ3VyYXRpb24gbWFwLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKi9cbiAgaW5pdCAob3B0aW9ucykge1xuICAgIGNvbnN0IGRlZmVycmVkID0gbmV3IERlZmVycmVkUHJvbWlzZSgpXG4gICAgaWYgKCF3ZWJydGMuaXNTdXBwb3J0ZWQoKSB8fCAhd2Vic29ja2V0LmlzU3VwcG9ydGVkKCkpIHtcbiAgICAgIGRlZmVycmVkLnJlamVjdCgnQ2Fubm90IGNyZWF0ZSBXZWJSVEMgcGxheWJhY2sgaW5zdGFuY2UuIFlvdXIgZW52aXJvbm1lbnQgZG9lcyBub3Qgc3VwcG9ydCBXZWJSVEMgYW5kL29yIFdlYlNvY2tldHMuJylcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICB0aGlzLl9kaXNjb25uZWN0KClcbiAgICAgIHRoaXMuX29wdGlvbnMgPSBPYmplY3QuYXNzaWduKHt9LCBkZWZhdWx0T3B0aW9ucywgb3B0aW9ucylcbiAgICAgIHRoaXMuX29wdGlvbnMuc3Vic2NyaXB0aW9uSWQgPSB0aGlzLl9vcHRpb25zLnN1YnNjcmlwdGlvbklkIHx8IGdlbmVyYXRlU3Vic2NyaXB0aW9uSWQoKVxuXG4gICAgICB0aGlzLl9wZWVySGVscGVyID0gbmV3IFN1YnNjcmlwdGlvblBlZXJIZWxwZXIodGhpcylcbiAgICAgIHRoaXMuX3NvY2tldEhlbHBlciA9IG5ldyBTdWJzY3JpcHRpb25Tb2NrZXRIZWxwZXIodGhpcylcbiAgICAgIGNvbnN0IHNvY2tldFByb21pc2UgPSBuZXcgRGVmZXJyZWRQcm9taXNlKClcbiAgICAgIGNvbnN0IHNvY2tldHVybCA9IGVuZHBvaW50RnJvbU9wdGlvbnModGhpcy5fb3B0aW9ucywge1xuICAgICAgICBpZDogdGhpcy5fb3B0aW9ucy5zdWJzY3JpcHRpb25JZFxuICAgICAgfSlcblxuICAgICAgc29ja2V0UHJvbWlzZS5wcm9taXNlXG4gICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICBkZWZlcnJlZC5yZXNvbHZlKHRoaXMpXG4gICAgICAgICAgdGhpcy5fY29ubmVjdGlvbkNsb3NlZCA9IGZhbHNlXG4gICAgICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoU3Vic2NyaWJlckV2ZW50VHlwZXMuQ09OTkVDVF9TVUNDRVNTLCB0aGlzKSlcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICBkZWZlcnJlZC5yZWplY3QoZXJyb3IpXG4gICAgICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoU3Vic2NyaWJlckV2ZW50VHlwZXMuQ09OTkVDVF9GQUlMVVJFLCB0aGlzLCBlcnJvcikpXG4gICAgICAgIH0pXG5cbiAgICAgIHRoaXMuX3NvY2tldEhlbHBlci5zZXRVcChzb2NrZXR1cmwsIHNvY2tldFByb21pc2UpXG5cbiAgICB9XG4gICAgcmV0dXJuIGRlZmVycmVkLnByb21pc2VcbiAgfVxuXG4gIC8qKlxuICAgKiBTdGlsbCBpbiB1c2UgZm9yIGFzc2lnbmluZyBkb2N1bWVudCBlbGVtZW50IHZpZXcgbWFuYWdlbWVudCB0byB0aGlzIGluc3RhbmNlLlxuICAgKiBBUEkgZGVwcmVjYXRlZCBpbiA0LjAuMC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHNldFZpZXcgKHZpZXcpIHtcbiAgICB0aGlzLl92aWV3ID0gdmlld1xuICAgIHRoaXMuX3ZpZXdSZXNvbHZlci5yZXNvbHZlKHRoaXMuX3ZpZXcpXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIGJlZ2luIHN1YnNjcmliaW5nIHRvIGEgc3RyZWFtLlxuICAgKlxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgICAgICAgICBUaGUgcmV0dXJuZWQgYFByb21pc2VgIHdpbGwgcmVzb2x2ZSBvciByZWplY3Qgb24gc3VjY2Vzc2Z1bCBzdGFydCBvZiBwbGF5YmFjay5cbiAgICogICAgICAgIFRoZXJlIGFyZSBzZXZlcmFsIHByb2Nlc3NlcyB0aGF0IG9jY3VyIGluIG9yZGVyIHRvIGVzdGFibGlzaCBhIFdlYlJUQyBzdWJzY3JpcHRpb24gdGhhdCBpbnZvbHZlIC0gYnV0IGFyZSBub3QgbGltaXRlZCB0byAtIElDRSBjb21tdW5pY2F0aW9uIGFuZCBhc3NpZ25pbmcgb2YgbG9jYWwgYW5kIHJlbW90ZSBTRFBzIG9uIHBlZXIgY29ubmVjdGlvbnMuXG4gICAqL1xuICBzdWJzY3JpYmUgKCkge1xuICAgIHRoaXMuX2dldFZpZXdSZXNvbHZlclByb21pc2UoKVxuICAgICAgLnRoZW4odmlldyA9PiB7XG4gICAgICAgIHRoaXMuX3NvdXJjZUhhbmRsZXIgPSBuZXcgUlRDU291cmNlSGFuZGxlcih2aWV3LnZpZXcsIHRoaXMuZ2V0VHlwZSgpKVxuICAgICAgICB0aGlzLl9nbG9tU291cmNlSGFuZGxlckFQSSh0aGlzLl9zb3VyY2VIYW5kbGVyKVxuICAgICAgICB0aGlzLl9pbml0SGFuZGxlcih0aGlzLl9vcHRpb25zLCB0aGlzLl9zb3VyY2VIYW5kbGVyKVxuICAgICAgfSlcbiAgICB0aGlzLl9nZXRBdmFpbGFiaWxpdHlSZXNvbHZlclByb21pc2UoKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLl9jb25uZWN0KHRoaXMuX29wdGlvbnMuaWNlU2VydmVycylcbiAgICAgIH0pXG4gICAgdGhpcy5fc2V0Vmlld0lmTm90RXhpc3QodGhpcy5fdmlldywgdGhpcy5fb3B0aW9ucy5tZWRpYUVsZW1lbnRJZClcbiAgICB0aGlzLl9yZXF1ZXN0QXZhaWxhYmlsaXR5KHRoaXMuX29wdGlvbnMuc3RyZWFtTmFtZSwgdGhpcy5fb3B0aW9ucy5zdHJlYW1UeXBlKVxuICAgIHJldHVybiB0aGlzLl9nZXRTdWJzY3JpcHRpb25SZXNvbHZlclByb21pc2UoKVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gc3RvcCBhIHN1YnNjcmlwdGlvbi5cbiAgICogVGhlIHJldHVybmVkIGBQcm9taXNlYCB3aWxsIGVpdGhlciByZXNvbHZlIG9yIHJlamVjdCBvbiBzdWNjZXNzZnVsIHN0b3Agb2Ygc3Vic2NyaXB0aW9uLlxuICAgKlxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKi9cbiAgdW5zdWJzY3JpYmUgKCkge1xuICAgIGRlYnVnKE5BTUUsICdbdW5zdWJzY3JpYmVdJylcbiAgICBjb25zdCBkZWZlcnJlZCA9IG5ldyBEZWZlcnJlZFByb21pc2UoKVxuICAgIHRoaXMuc3RvcCgpXG4gICAgdGhpcy5fZGlzY29ubmVjdCgpXG4gICAgdGhpcy5fbWVkaWFTdHJlYW0gPSB1bmRlZmluZWRcbiAgICBkZWZlcnJlZC5yZXNvbHZlKHRoaXMpXG4gICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoU3Vic2NyaWJlckV2ZW50VHlwZXMuU1VCU0NSSUJFX1NUT1AsIHRoaXMpKVxuICAgIHJldHVybiBkZWZlcnJlZC5wcm9taXNlXG4gIH1cblxuICAvKipcbiAgICogRXZlbnQgaGFuZGxlciBmb3Igc3RyZWFtIGJlaW5nIGF2YWlsYWJsZSBvbiBzZXJ2ZXIuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBvblN0cmVhbUF2YWlsYWJsZSAocmVjZWlwdCkge1xuICAgIGRlYnVnKE5BTUUsICdbb25zdHJlYW1hdmFpbGFibGVdOiAnICsgSlNPTi5zdHJpbmdpZnkocmVjZWlwdCwgbnVsbCwgMikpXG4gICAgdGhpcy5fYXZhaWxhYmlsaXR5UmVzb2x2ZXIucmVzb2x2ZSh0aGlzKVxuICB9XG5cbiAgLyoqXG4gICAqIEV2ZW50IGhhbmRsZXIgZm9yIHN0cmVhbSBiZWluZyB1bmF2YWlsYWJsZSBvbiBzZXJ2ZXIuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBvblN0cmVhbVVuYXZhaWxhYmxlIChyZWNlaXB0KSB7XG4gICAgZGVidWcoTkFNRSwgYFN0cmVhbSAke3RoaXMuX29wdGlvbnMuc3RyZWFtTmFtZX0gZG9lcyBub3QgZXhpc3QuYClcbiAgICBkZWJ1ZyhOQU1FLCAnW29uc3RyZWFtdW5hdmFpbGFibGVdOiAnICsgSlNPTi5zdHJpbmdpZnkocmVjZWlwdCwgbnVsbCwgMikpXG4gICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoU3Vic2NyaWJlckV2ZW50VHlwZXMuU1VCU0NSSUJFX0lOVkFMSURfTkFNRSwgdGhpcykpXG4gICAgdGhpcy5fYXZhaWxhYmlsaXR5UmVzb2x2ZXIucmVqZWN0KGBTdHJlYW0gJHt0aGlzLl9vcHRpb25zLnN0cmVhbU5hbWV9IGRvZXMgbm90IGV4aXN0LmApXG4gICAgdGhpcy5fc3Vic2NyaXB0aW9uUmVzb2x2ZXIucmVqZWN0KGBTdHJlYW0gJHt0aGlzLl9vcHRpb25zLnN0cmVhbU5hbWV9IGRvZXMgbm90IGV4aXN0LmApXG4gICAgaWYgKCF0aGlzLl9vcHRpb25zLm1haW50YWluQ29ubmVjdGlvbk9uU3Vic2NyaWJlRXJyb3JzKSB7XG4gICAgICB0aGlzLl9kaXNjb25uZWN0KClcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gUmVzZXQgcHJvbWlzZSBmb3IgcG9zc2libGUgcmV0cnkuXG4gICAgICB0aGlzLl9hdmFpbGFiaWxpdHlSZXNvbHZlciA9IG5ldyBEZWZlcnJlZFByb21pc2UoKVxuICAgICAgdGhpcy5fc3Vic2NyaXB0aW9uUmVzb2x2ZXIgPSBuZXcgRGVmZXJyZWRQcm9taXNlKClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRXZlbnQgaGFuZGxlciBmb3Igc3VjY2VzcyBvZiBTRFAgYmVpbmcgYWRkZWQgcmVtb3RlbHkgYW5kIGxvY2FsbHkgdGhyb3VnaCB0aGUgUGVlciBDb25uZWN0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gcmVjZWlwdFxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgb25TRFBTdWNjZXNzIChyZWNlaXB0KSB7XG4gICAgZGVidWcoTkFNRSwgJ1tvbnNkcHN1Y2Nlc3NdOiAnICsgSlNPTi5zdHJpbmdpZnkocmVjZWlwdCwgbnVsbCwgMikpXG4gIH1cblxuICAvKipcbiAgICogRXZlbnQgaGFuZGxlciBmb3Igc3VjY2VzcyBpbiBTRFAgb2ZmZXIuXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSByZWNlaXB0XG4gICAqICAgICAgICBUaGUgb3B0aW9uYWwgc3VjY2Vzc2Z1bCBvYmplY3QuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBvblNEUE9mZmVyIChyZWNlaXB0KSB7XG4gICAgZGVidWcoTkFNRSwgJ1tvbnNkcG9mZmVyXTogJyArIEpTT04uc3RyaW5naWZ5KHJlY2VpcHQsIG51bGwsIDIpKVxuICAgIGNvbnN0IHNkcCA9IG5ldyB3ZWJydGMuUlRDU2Vzc2lvbkRlc2NyaXB0aW9uKHJlY2VpcHQuc2RwKVxuICAgIHRoaXMudHJpZ2dlcihuZXcgU3Vic2NyaWJlckV2ZW50KFJUQ1N1YnNjcmliZXJFdmVudFR5cGVzLk9GRkVSX0VORCwgdGhpcykpXG4gICAgdGhpcy5fcmVxdWVzdEFuc3dlcihzZHApXG4gIH1cblxuICAvKipcbiAgICogRXZlbnQgaGFuZGxlciBmb3IgYWxsIGVycm9ycyByZWxhdGVkIHRvIFNEUCB0aHJvdWdoIHRoZSBQZWVyIENvbm5lY3Rpb24uXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSByZWNlaXB0XG4gICAqICAgICAgICBUaGUgb3B0aW9uYWwgZXJyb3Igb2JqZWN0LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgb25TRFBFcnJvciAocmVjZWlwdCkge1xuICAgIHRoaXMudHJpZ2dlcihuZXcgU3Vic2NyaWJlckV2ZW50KFN1YnNjcmliZXJFdmVudFR5cGVzLlNVQlNDUklCRV9GQUlMLCB0aGlzLCByZWNlaXB0KSlcbiAgICB0aGlzLl9zdWJzY3JpcHRpb25SZXNvbHZlci5yZWplY3QoJ0ludmFsaWQgU0RQLicpXG4gICAgZXJyb3IoTkFNRSwgJ1tvbnNkcGVycm9yXScpXG4gICAgZXJyb3IoTkFNRSwgcmVjZWlwdClcbiAgfVxuXG4gIC8qKlxuICAgKiBFdmVudCBoYW5kbGVyIGZvciByZWNlaXB0IG9mIGEgYE1lZGlhU3RyZWFtYC5cbiAgICpcbiAgICogQHBhcmFtIHtNZWRpYVN0cmVhbX0gc3RyZWFtXG4gICAqICAgICAgICBUaGUgc3RyZWFtIHJldHVybmVkIG9uIHRoZSBQZWVyIENvbm5lY3Rpb24uXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBvbkFuc3dlck1lZGlhU3RyZWFtIChzdHJlYW0gPSB1bmRlZmluZWQpIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuICAgIHRoaXMudHJpZ2dlcihuZXcgU3Vic2NyaWJlckV2ZW50KFJUQ1N1YnNjcmliZXJFdmVudFR5cGVzLkFOU1dFUl9FTkQsIHRoaXMpKVxuICB9XG5cbiAgLyoqXG4gICAqIEV2ZW50IGhhbmRsZXIgb24gcmVjZWlwdCBvZiBJQ0UgY2FuZGlkYXRlLlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gY2FuZGlkYXRlXG4gICAqICAgICAgICBUaGUgSUNFIGNhbmRpZGF0ZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIG9uSWNlQ2FuZGlkYXRlIChjYW5kaWRhdGUpIHtcbiAgICBkZWJ1ZyhOQU1FLCAnW29uaWNlY2FuZGlkYXRlXScpXG4gICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoUlRDU3Vic2NyaWJlckV2ZW50VHlwZXMuQ0FORElEQVRFX0VORCwgdGhpcykpXG4gICAgdGhpcy5fc2VuZENhbmRpZGF0ZShjYW5kaWRhdGUpXG4gIH1cblxuICAvKipcbiAgICogRXZlbnQgaGFuZGxlciBmb3IgZW5kIG9mIElDRSBjb21tdW5pY2F0aW9uICh0cmlja2xlKS5cbiAgICpcbiAgICogQHBhcmFtIHtNZWRpYVN0cmVhbX0gc3RyZWFtXG4gICAqICAgICAgICBUaGUgYE1lZGlhU3RyZWFtYCB0aGF0IGhhcyBiZWNvbWUgYXZhaWxhYmxlIHBvc3QtdHJpY2tsZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIG9uSWNlQ2FuZGlkYXRlVHJpY2tsZUVuZCAoc3RyZWFtKSB7XG4gICAgZGVidWcoTkFNRSwgJ1tvbmljZXRyaWNrbGVlbmRdJylcbiAgICB0aGlzLl9nZXRWaWV3UmVzb2x2ZXJQcm9taXNlKClcbiAgICAgIC50aGVuKHZpZXcgPT4ge1xuICAgICAgICB2aWV3LmF0dGFjaFN0cmVhbShzdHJlYW0pXG4gICAgICAgIHRoaXMuX21lZGlhU3RyZWFtID0gc3RyZWFtXG4gICAgICAgIHRoaXMudHJpZ2dlcihuZXcgU3Vic2NyaWJlckV2ZW50KFJUQ1N1YnNjcmliZXJFdmVudFR5cGVzLk9OX0FERF9TVFJFQU0sIHRoaXMsIHRoaXMuX21lZGlhU3RyZWFtKSlcbiAgICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogRXZlbnQgaGFuZGxlciB0byBhZGQgSUNFIGNhbmRpZGF0ZSB0byBQZWVyIENvbm5lY3Rpb24uXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBjYW5kaWRhdGVcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIG9uQWRkSWNlQ2FuZGlkYXRlIChjYW5kaWRhdGUpIHtcbiAgICBkZWJ1ZyhOQU1FLCAnW29uYWRkaWNlY2FuZGlkYXRlXScpXG4gICAgdGhpcy5fcGVlckhlbHBlci5hZGRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlKVxuICB9XG5cbiAgLyoqXG4gICAqIEV2ZW50IGhhbmRsZXIgZm9yIHJlY2VpcHQgb2YgZW1wdHkgY2FuZGlkYXRlIGR1cmluZyBJQ0UgbmVnb3RpYXRpb24uXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBvbkVtcHR5Q2FuZGlkYXRlICgpIHtcbiAgICBkZWJ1ZyhOQU1FLCAnW2ljZWNhbmRpZGF0ZXRyaWNrbGU6ZW1wdHldJylcbiAgICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChSVENTdWJzY3JpYmVyRXZlbnRUeXBlcy5QRUVSX0NBTkRJREFURV9FTkQpKVxuICB9XG5cbiAgLyoqXG4gICAqIEV2ZW50IGhhbmRsZXIgZm9yIGNvbXBsZXRpb24gb2YgcGVlciBpY2UgY2FuZGlkYXRlIGdhdGhlcmluZy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIG9uUGVlckdhdGhlcmluZ0NvbXBsZXRlICgpIHtcbiAgICBkZWJ1ZyhOQU1FLCAnW2ljZWNhbmRpZGF0ZWdhdGhlcmluZzplbmRdJylcbiAgICBpZiAodGhpcy5fc29ja2V0SGVscGVyKSB7XG4gICAgICB0aGlzLl9zb2NrZXRIZWxwZXIucG9zdEVuZE9mQ2FuZGlkYXRlcyh0aGlzLl9vcHRpb25zLnN0cmVhbU5hbWUpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEV2ZW50IGhhbmRsZXIgZm9yIG5vdGlmaWNhdGlvbiBvZiBlbmQgaW4gaWNlIGNhbmRpZGF0ZXMgb3ZlciB0aGUgV2ViU29ja2V0LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgb25Tb2NrZXRJY2VDYW5kaWRhdGVFbmQgKCkge1xuICAgIGRlYnVnKE5BTUUsICdbb25zb2NrZXRpY2VjYW5kaWRhdGVlbmRdJylcbiAgICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChSVENTdWJzY3JpYmVyRXZlbnRUeXBlcy5JQ0VfVFJJQ0tMRV9DT01QTEVURSwgdGhpcykpXG4gICAgdGhpcy5fc2VuZFN1YnNjcmliZSgpXG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhbCBldmVudCBoYW5kbGVyIGZvciBlcnJvcnMgY29taW5nIG92ZXIgdGhlIFdlYlNvY2tldC5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGRldGFpbFxuICAgKiAgICAgICAgT3B0aW9uYWwgYWRkaXRpb25hbCBkZXRhaWwuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBvblNvY2tldE1lc3NhZ2VFcnJvciAobWVzc2FnZSwgZGV0YWlsID0gdW5kZWZpbmVkKSB7XG4gICAgZXJyb3IoTkFNRSwgYEVycm9yIGluIHN0cmVhbSBzdWJzY3JpcHRpb246ICR7bWVzc2FnZX0uXFxuW09wdGlvbmFsIGRldGFpbF06ICR7ZGV0YWlsfWApXG4gICAgdGhpcy5fc3Vic2NyaXB0aW9uUmVzb2x2ZXIucmVqZWN0KGBFcnJvciBpbiBzdHJlYW0gc3Vic2NyaXB0aW9uOiAke21lc3NhZ2V9LmApXG4gICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoU3Vic2NyaWJlckV2ZW50VHlwZXMuU1VCU0NSSUJFX0ZBSUwsIHRoaXMsIG1lc3NhZ2UpKVxuICB9XG5cbiAgLyoqXG4gICAqIEV2ZW50IGhhbmRsZXIgZm9yIGNsb3NlIG9uIHRoZSBXZWJTb2NrZXQuXG4gICAqXG4gICAqIEBwYXJhbSB7RXZlbnR9IGNsb3NlRXZlbnRcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIG9uU29ja2V0Q2xvc2UgKGNsb3NlRXZlbnQpIHtcbiAgICBkZWJ1ZyhOQU1FLCAnW29uc29ja2V0Y2xvc2VdJylcbiAgICBpZiAodGhpcy5fcGVlckhlbHBlcikge1xuICAgICAgdGhpcy5fcGVlckhlbHBlci50ZWFyRG93bigpXG4gICAgfVxuICAgIHRoaXMub25Db25uZWN0aW9uQ2xvc2VkKGNsb3NlRXZlbnQpXG4gIH1cblxuICAvKipcbiAgICogRXZlbnQgaGFuZGxlciBmb3IgY2xvc2Ugb2YgUGVlciBDb25uZWN0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0ge0V2ZW50fSBldmVudFxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgb25QZWVyQ29ubmVjdGlvbkNsb3NlIChldmVudCkge1xuICAgIGRlYnVnKE5BTUUsICdbb25wZWVyY29ubmVjdGlvbmNsb3NlXScpXG4gICAgaWYgKHRoaXMuX3NvY2tldEhlbHBlcikge1xuICAgICAgdGhpcy5fc29ja2V0SGVscGVyLnRlYXJEb3duKClcbiAgICB9XG4gICAgdGhpcy5vblNvY2tldENsb3NlKGV2ZW50KVxuICB9XG5cbiAgLyoqXG4gICAqIEV2ZW50IGhhbmRsZXIgZm9yIGBVbnB1Ymxpc2hgIG9mIHN0cmVhbSBzdWJzY3JpYmVkIHRvLiBPY2N1cnMgd2hlbiBhIGJyb2FkY2FzdGVyIHN0b3BzIHRoZWlyIHN0cmVhbSB3aGlsZSB0aGlzIHN1YnNjcmlwdGlvbiBzdHJlYW0gaXMgb3Blbi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIG9uVW5wdWJsaXNoICgpIHtcbiAgICBkZWJ1ZyhOQU1FLCAnW29udW5wdWJsaXNoXScpXG4gICAgaWYgKHRoaXMuX3NvdXJjZUhhbmRsZXIpIHtcbiAgICAgIHRoaXMuX3NvdXJjZUhhbmRsZXIudW5wdWJsaXNoKClcbiAgICB9XG4gICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoU3Vic2NyaWJlckV2ZW50VHlwZXMuUExBWV9VTlBVQkxJU0gsIHRoaXMpKVxuICB9XG5cbiAgLyoqXG4gICAqIEV2ZW50IGhhbmRsZXIgZm9yIGNvbm5lY3Rpb24gb24gc3RyZWFtIGJlaW5nIGNsb3NlZC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIG9uQ29ubmVjdGlvbkNsb3NlZCAoZXZlbnQgPSB1bmRlZmluZWQpIHtcbiAgICBpZiAoIXRoaXMuX2Nvbm5lY3Rpb25DbG9zZWQpIHtcbiAgICAgIGRlYnVnKE5BTUUsICdbb25jb25uZWN0aW9uY2xvc2VkXScpXG4gICAgICB0aGlzLl9kaXNjb25uZWN0KClcbiAgICAgIHRoaXMudHJpZ2dlcihuZXcgU3Vic2NyaWJlckV2ZW50KFN1YnNjcmliZXJFdmVudFR5cGVzLkNPTk5FQ1RJT05fQ0xPU0VELCB0aGlzLCBldmVudCkpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEV2ZW50IGhhbmRsZXIgZm9yIGFjY2VwdGluZyBkYXRhIHRocm91Z2ggdGhlIGBzZW5kYCBBUEkgb2YgYSBQdWJsaXNoZXIuIFRoaXMgaXMgdGhlIHJlY2VpdmluZyBlbmQgb2YgdGhlIGNvbW11bmljYXRpb24gY2hhbm5lbCBpbiB3aGljaCBhIFB1Ymxpc2hlciBjYW4gc2VuZCBkYXRhIHRvIGFsbCBzdWJzY3JpYmVycy5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZE5hbWVcbiAgICogICAgICAgIFRoZSB0YXJnZXQgbWV0aG9kIG5hbWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBjb21tdW5pY2F0aW9uLlxuICAgKiBAcGFyYW0ge09iamVjdH0gZGF0YVxuICAgKiAgICAgICAgVGhlIGRhdGEgYmVpbmcgc2VudC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIG9uU2VuZFJlY2VpdmVkIChtZXRob2ROYW1lLCBkYXRhKSB7XG4gICAgaWYgKG1ldGhvZE5hbWUgPT09ICdvbk1ldGFEYXRhJykge1xuICAgICAgdGhpcy5vbk1ldGFEYXRhKGRhdGEpXG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgLy8gZW52aXJvbm1lbnQuaW52b2tlKG1ldGhvZE5hbWUsIGRhdGEpXG4gICAgICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChTdWJzY3JpYmVyRXZlbnRUeXBlcy5TVUJTQ1JJQkVfU0VORF9JTlZPS0UsIHRoaXMsIHtcbiAgICAgICAgbWV0aG9kTmFtZTogbWV0aG9kTmFtZSxcbiAgICAgICAgZGF0YTogZGF0YVxuICAgICAgfSkpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEV2ZW50IGhhbmRsZXIgZm9yIHN0YXR1cyBub3RpZmljYXRpb25zIG9mIHRoZSBzdWJzY3JpcHRpb24gc3RyZWFtIGNvbWluZyBvdmVyIHRoZSBXZWJTb2NrZXQuXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBzdGF0dXNcbiAgICogICAgICAgIFRoZSBzdGF0dXMgb2JqZWN0LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgb25TdWJzY3JpYmVyU3RhdHVzIChzdGF0dXMpIHtcbiAgICBkZWJ1ZyhOQU1FLCAnW3N1YnNjcmliZXJzdGF0dXNdIC0gJyArIEpTT04uc3RyaW5naWZ5KHN0YXR1cywgbnVsbCwgMikpXG4gICAgY29uc3Qgc3RhcnRSZXN1bHQgPSBzdWJTdGFydFJlZ2V4LmV4ZWMoc3RhdHVzLm1lc3NhZ2UpXG4gICAgaWYgKHN0YXJ0UmVzdWx0ICYmIHN0YXJ0UmVzdWx0WzFdID09PSB0aGlzLl9vcHRpb25zLnN0cmVhbU5hbWUpIHtcbiAgICAgIHRoaXMuX3N1YnNjcmlwdGlvblJlc29sdmVyLnJlc29sdmUodGhpcylcbiAgICAgIHRoaXMudHJpZ2dlcihuZXcgU3Vic2NyaWJlckV2ZW50KFN1YnNjcmliZXJFdmVudFR5cGVzLlNVQlNDUklCRV9TVEFSVCwgdGhpcykpXG4gICAgICB0aGlzLl9wbGF5SWZBdXRvcGxheVNldCh0aGlzLl9vcHRpb25zLCB0aGlzLl92aWV3KVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBFdmVudCBoYW5kbGVyIGZvciBtZXRhZGF0YSBiZWluZyBzZW50IHJlbGF0ZWQgdG8gdGhlIHN1YnNjcmlwdGlvbiBzdHJlYW0gY29taW5nIG92ZXIgdGhlIFdlYlNvY2tldC5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IG1ldGFkYXRhXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBvbk1ldGFEYXRhIChtZXRhZGF0YSkge1xuICAgIGlmICh0eXBlb2YgbWV0YWRhdGEub3JpZW50YXRpb24gIT09ICd1bmRlZmluZWQnXG4gICAgICAgICYmIG1ldGFkYXRhLm9yaWVudGF0aW9uICE9PSB0aGlzLl9vcmllbnRhdGlvbikge1xuICAgICAgdGhpcy5fb3JpZW50YXRpb24gPSBtZXRhZGF0YS5vcmllbnRhdGlvblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMuYXV0b0xheW91dE9yaWVudGF0aW9uKSB7XG4gICAgICAgIGFwcGx5T3JpZW50YXRpb24odGhpcy5fdmlldy52aWV3LCBwYXJzZUludChtZXRhZGF0YS5vcmllbnRhdGlvbiwgMTApLCBtZXRhZGF0YVJlc29sdXRpb25Ub09iamVjdChtZXRhZGF0YS5yZXNvbHV0aW9uKSlcbiAgICAgICAgaWYgKHRoaXMuX3NvdXJjZUhhbmRsZXIpIHtcbiAgICAgICAgICB0aGlzLl9zb3VyY2VIYW5kbGVyLmhhbmRsZU9yaWVudGF0aW9uQ2hhbmdlKHBhcnNlSW50KG1ldGFkYXRhLm9yaWVudGF0aW9uKSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoU3Vic2NyaWJlckV2ZW50VHlwZXMuT1JJRU5UQVRJT05fQ0hBTkdFLCB0aGlzLCB7XG4gICAgICAgIG9yaWVudGF0aW9uOiBwYXJzZUludChtZXRhZGF0YS5vcmllbnRhdGlvbiksXG4gICAgICAgIHZpZXdFbGVtZW50OiB0aGlzLl92aWV3LnZpZXdcbiAgICAgIH0pKVxuICAgIH1cbiAgICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChTdWJzY3JpYmVyRXZlbnRUeXBlcy5TVUJTQ1JJQkVfTUVUQURBVEEsIHRoaXMsIG1ldGFkYXRhKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIGludm9rZSBhIG1ldGhvZCBvbiB0aGUgQXBwbGljYXRpb24gQWRhcHRlciByZWxhdGVkIHRvIHRoZSBgYXBwYCBjb25maWcgc2V0dGluZy5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZE5hbWVcbiAgICogICAgICAgIFRoZSBuYW1lIG9mIHRoZSBtZXRob2QgdG8gaW52b2tlIG9uIHRodyBBcHBsaWNhdGlvbiBBZGFwdGVyXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFyZ3NcbiAgICogICAgICAgIFRoZSBvcmRlcmVkIGxpc3Qgb2YgYXJndW1lbnRzIHRvIGludm9rZSBvbiB0aGUgbWV0aG9kLiBEbyBub3QgcHJvdmlkZSBhbnl0aGluZyBpZiB0aGUgbWV0aG9kIHRha2VzIG5vIGFyZ3VtZW50cy5cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICovXG4gIGNhbGxTZXJ2ZXIgKG1ldGhvZE5hbWUsIGFyZ3MpIHtcbiAgICByZXR1cm4gdGhpcy5fc29ja2V0SGVscGVyLnBvc3RBc3luYyh7XG4gICAgICBjYWxsQWRhcHRlcjoge1xuICAgICAgICBtZXRob2Q6IG1ldGhvZE5hbWUsXG4gICAgICAgIGFyZ3VtZW50czogYXJnc1xuICAgICAgfVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogRW50ZXJzIHN1YnNjcmliZXIgaW50byBzdGFuZGJ5IG1vZGUgLSBrZWVwaW5nIGNvbm5lY3Rpb24gb3BlbiBidXQgbm90IGJvdGhlcmluZyB0byBjb25zdW1lIHZpZGVvIG9yIGF1ZGlvLlxuICAgKi9cbiAgZW5hYmxlU3RhbmRieSAoKSB7XG4gICAgdGhpcy5fc29ja2V0SGVscGVyLnBvc3Qoe1xuICAgICAgc3RhbmRieTogdHJ1ZVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyBzdWJzY3JpYmVyIGZyb20gc3RhbmRieSBtb2RlIC0gdHVybmluZyB0aGUgYXVkaW8gYW5kIHZpZGVvIGJhY2sgb24gYW5kIGNvbnN1bWFibGUgYWZ0ZXIgYSBtdXRlIHJlcXVlc3QuXG4gICAqL1xuICBkaXNhYmxlU3RhbmRieSAoKSB7XG4gICAgdGhpcy5fc29ja2V0SGVscGVyLnBvc3Qoe1xuICAgICAgc3RhbmRieTogZmFsc2VcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGN1cnJlbnQgV2ViU29ja2V0IGNvbm5lY3Rpb24gaGVscGVyIGlmIGVzdGFibGlzaGVkLlxuICAgKiBVc2VkIGluIFNoYXJlZE9iamVjdCBjb21tdW5pY2F0aW9uLlxuICAgKlxuICAgKiBAcmV0dXJuIHtQdWJsaXNoZXJTb2NrZXRIZWxwZXJ9XG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBnZXRDb25uZWN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5fc29ja2V0SGVscGVyXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY3VycmVudCBSVENQZWVyQ29ubmVjdGlvbiBoZWxwZXIgaWYgZXN0YWJsaXNoZWQuXG4gICAqXG4gICAqIEByZXR1cm4ge1JUQ1BlZXJDb25uZWN0aW9ufVxuICAgKi9cbiAgIGdldFBlZXJDb25uZWN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5fcGVlckhlbHBlciA/IHRoaXMuX3BlZXJIZWxwZXIuY29ubmVjdGlvbiA6IHVuZGVmaW5lZFxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGBNZWRpYVN0cmVhbWAgaW5zdGFuY2UgaWYgZ2VuZXJhdGVkIHRocm91Z2ggYGdldFVzZXJNZWRpYWAgYW5kIGV4aXN0cyBmb3IgYnJvYWRjYXN0LlxuICAgKlxuICAgKiBAcmV0dXJuIHtNZWRpYVN0cmVhbX1cbiAgICovXG4gIGdldE1lZGlhU3RyZWFtICgpIHtcbiAgICByZXR1cm4gdGhpcy5fbWVkaWFTdHJlYW1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHJlZmVyZW5jZSB0byBwbGF5YmFjayBjb250cm9scyBpZiBhdmFpbGFibGUuXG4gICAqXG4gICAqIEByZXR1cm4ge1BsYXliYWNrQ29udHJvbHN9XG4gICAqL1xuICBnZXRDb250cm9scyAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3NvdXJjZUhhbmRsZXIgPyB0aGlzLl9zb3VyY2VIYW5kbGVyLmdldENvbnRyb2xzKCkgOiB1bmRlZmluZWRcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSB0YXJnZXQgdmlldyBFbGVtZW50LlxuICAgKlxuICAgKiBAcmV0dXJuIHtFbGVtZW50fVxuICAgKi9cbiAgZ2V0UGxheWVyICgpIHtcbiAgICByZXR1cm4gdGhpcy5fdmlldy52aWV3XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgaW5pdGlhbGl6YXRpb24gY29uZmlndXJhdGlvbiB1c2VkIGluIGBpbml0KClgLlxuICAgKlxuICAgKiBAcmV0dXJuIHtPYmplY3R9XG4gICAqL1xuICBnZXRPcHRpb25zICgpIHtcbiAgICByZXR1cm4gdGhpcy5fb3B0aW9uc1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHR5cGUgb2YgaW1wbGVtZW50YXRpb246IGBSVENgLlxuICAgKlxuICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAqL1xuICBnZXRUeXBlICgpIHtcbiAgICByZXR1cm4gUGxheWJhY2tUeXBlcy5SVEMudG9VcHBlckNhc2UoKVxuICB9XG5cbn1cblxuZXhwb3J0IGRlZmF1bHQgUlRDU3Vic2NyaWJlclxuXG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvanMvc3Vic2NyaWJlci9yZWQ1cHJvLXJ0Yy5qcyIsIid1c2Ugc3RyaWN0J1xuXG5pbXBvcnQgZW52aXJvbm1lbnQgZnJvbSAnLi4vZW52L2Jyb3dzZXInXG5pbXBvcnQgUlRNUFNvdXJjZUhhbmRsZXIgZnJvbSAnLi9yZWQ1cHJvLXNvdXJjZS1oYW5kbGVyLXJ0bXAnXG5pbXBvcnQgUGxheWJhY2tWaWV3IGZyb20gJy4uL3ZpZXcvcGxheWJhY2snXG5pbXBvcnQgeyBQbGF5YmFja0NvbnRyb2xsZXIgfSBmcm9tICcuL2NvbnRyb2xzJ1xuaW1wb3J0IHsgU3Vic2NyaWJlckV2ZW50IH0gZnJvbSAnLi4vZXZlbnQnXG5pbXBvcnQgeyBQbGF5YmFja1R5cGVzIH0gZnJvbSAnLi4vZW51bS9wbGF5YmFjaydcbmltcG9ydCB7XG4gIFN1YnNjcmliZXJFdmVudFR5cGVzLFxuICBSVE1QU3Vic2NyaWJlckV2ZW50VHlwZXNcbn0gZnJvbSAnLi4vZXZlbnQnXG5pbXBvcnQgeyBQbGF5YmFja1N0YXRlUmVhZGFibGUgfSBmcm9tICcuL2NvbnRyb2xzL3N0YXRlJ1xuaW1wb3J0IHsgRGVmZXJyZWRQcm9taXNlLCBGdXR1cmUgfSBmcm9tICcuLi91dGlsL3Byb21pc2UnXG5pbXBvcnQgeyBkZWJ1Zywgd2FybiwgZXJyb3IgfSBmcm9tICcuLi9sb2cnXG5cbmNvbnN0IE5BTUUgPSAnUlRNUFN1YmNyaWJlcidcblxuY29uc3QgZGVmYXVsdE9wdGlvbnMgPSB7XG4gIHByb3RvY29sOiAncnRtcCcsXG4gIHBvcnQ6IDE5MzUsXG4gIHdpZHRoOiAzMjAsIC8vIG1lZGlhIHBsYXliYWNrXG4gIGhlaWdodDogMjQwLCAvLyBtZWRpYSBwbGF5YmFja1xuICBlbWJlZFdpZHRoOiAnMTAwJScsIC8vIERPTSBkaXNwbGF5IHN0eWxlXG4gIGVtYmVkSGVpZ2h0OiAnMTAwJScsIC8vIERPTSBkaXNwbGF5IHN0eWxlXG4gIG1pbkZsYXNoVmVyc2lvbjogJzEwLjAuMCcsXG4gIHN3ZjogJ2xpYi9yZWQ1cHJvL3JlZDVwcm8tc3Vic2NyaWJlci5zd2YnLFxuICBzd2ZvYmplY3RVUkw6ICdsaWIvc3dmb2JqZWN0L3N3Zm9iamVjdC5qcycsXG4gIHByb2R1Y3RJbnN0YWxsVXJsOiAnbGliL3N3Zm9iamVjdC9wbGF5ZXJQcm9kdWN0SW5zdGFsbC5zd2YnLFxuICBtZWRpYUVsZW1lbnRJZDogJ3JlZDVwcm8tc3Vic2NyaWJlcicsXG4gIC8vIHdpdGggQXV0b3NjYWxlIGVuYWJsZWQgc2VydmVyIG9ubHkgPT5cbiAgdXNlQWRhcHRpdmVCaXRyYXRlQ29udHJvbGxlcjogZmFsc2UsXG4gIGFiclZhcmlhbnRzOiB1bmRlZmluZWQsXG4gIGFiclZhcmlhbnRVcGdyYWRlU2V0dGluZ3M6IHtcbiAgICBtaW5pbXVtRG93bmdyYWRlUGxheWJhY2tTcGFuOiAxMDAwMCwgLy8gQW1vdW50IG9mIHRpbWUgcGxheWJhY2sgbmVlZHMgdG8gZXhjZWVkIGJldHdlZW4gcGxheWJhY2sgYW5kIGRvd25ncmFkZSBpbiBvcmRlciB0byBiZSBlbGlnaWJsZSBmb3IgdXBncmFkZVxuICAgIHVwZ3JhZGU6IFtcbiAgICAgIHtcbiAgICAgICAgbGV2ZWw6IDEsXG4gICAgICAgIHJldHJ5VGltZW91dDogMFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgbGV2ZWw6IDIsXG4gICAgICAgIHJldHJ5VGltZW91dDogMTAwMDAgLy8gSWYgb24gbGV2ZWwgMiwgaW4gMTAgc2Vjb25kcyBhZnRlciBwbGF5YmFjaywgdHJ5IGFuZCBzd2l0Y2ggdXAuXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBsZXZlbDogMyxcbiAgICAgICAgcmV0cnlUaW1lb3V0OiAyMDAwMCAvLyBJZiBvbiBsZXZlbCAzLCBpbiAyMCBzZWNvbmRzIGFmdGVyIHBsYXliYWNrLCB0cnkgYW5kIHN3aXRjaCB1cC5cbiAgICAgIH1cbiAgICBdXG4gIH1cbn1cblxuLyoqXG4gKiBNYWluIGVudHJ5IGZvciBGbGFzaC1iYXNlZCBTdWJzY3JpYmVyIG92ZXIgUlRNUC5cbiAqXG4gKiBAZXh0ZW5kcyBFdmVudEVtaXR0ZXJcbiAqIEBleHRlbmRzIFN1YnNjcmliZXJQbGF5YmFja0NvbnRyb2xsZXJcbiAqL1xuY2xhc3MgUlRNUFN1YnNjcmliZXIgZXh0ZW5kcyBQbGF5YmFja0NvbnRyb2xsZXIge1xuXG4gIGNvbnN0cnVjdG9yICgpIHtcbiAgICBzdXBlcigpXG4gICAgdGhpcy5fb3B0aW9ucyA9IHVuZGVmaW5lZFxuICAgIHRoaXMuX3ZpZXcgPSB1bmRlZmluZWRcbiAgICB0aGlzLl9zb3VyY2VIYW5kbGVyID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fZWxlbWVudElkID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fZW1iZWRQcm9taXNlID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fZ2V0RW1iZWRQcm9taXNlKClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgdGhpcy5vbkVtYmVkQ29tcGxldGUoKVxuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnIgPT4gdGhpcy5vbkVtYmVkRmFpbHVyZShlcnIpKVxuICAgIHRoaXMuX3ZpZXdSZXNvbHZlciA9IG5ldyBEZWZlcnJlZFByb21pc2UoKVxuICAgIHRoaXMuX3N1YnNjcmlwdGlvblJlc29sdmVyID0gbmV3IERlZmVycmVkUHJvbWlzZSgpXG4gIH1cblxuICBfZ2V0Vmlld1Jlc29sdmVyUHJvbWlzZSAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3ZpZXdSZXNvbHZlci5wcm9taXNlXG4gIH1cblxuICBfZ2V0U3Vic2NyaXB0aW9uUmVzb2x2ZXJQcm9taXNlKCkge1xuICAgIHJldHVybiB0aGlzLl9zdWJzY3JpcHRpb25SZXNvbHZlci5wcm9taXNlXG4gIH1cblxuICBfZ2V0RW1iZWRQcm9taXNlICgpIHtcbiAgICB0aGlzLl9lbWJlZFByb21pc2UgPSBGdXR1cmUuY3JlYXRlSWZOb3RFeGlzdCh0aGlzLl9lbWJlZFByb21pc2UpXG4gICAgcmV0dXJuIHRoaXMuX2VtYmVkUHJvbWlzZS5wcm9taXNlXG4gIH1cblxuICAvKipcbiAgICogR2xvbXMgdGhlIFBsYXliYWNrIENvbnRyb2xzIEFQSSBvbnRvIHRoaXMgaW5zdGFuY2UgdG8gcHJvdmlkZSBlYXNlIGluIHVzZS5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IGhhbmRsZXJcbiAgICogICAgICAgIFRoZSBtZXRob2QgcmVxdWVzdCBoYW5kbGVyIHRvIGJpbmQgYW5kIGZvcndhcmQgY2FsbHMgb24uXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfZ2xvbVNvdXJjZUhhbmRsZXJBUEkgKGhhbmRsZXIpIHtcbiAgICAvKlxuICAgICAqIHx8IE5vdGUgfHxcbiAgICAgKiBwbGF5KCkgaXMgbm90IGdsb21tZWQgYXMgaXQgbmVlZHMgdG8gYmUgaGFuZGxlZCBkaWZmZXJlbnRseS5cbiAgICAgKi9cblxuICAgIHRoaXMucGF1c2UgPSBoYW5kbGVyLnBhdXNlLmJpbmQoaGFuZGxlcilcbiAgICB0aGlzLnJlc3VtZSA9IGhhbmRsZXIucmVzdW1lLmJpbmQoaGFuZGxlcilcbiAgICB0aGlzLnN0b3AgPSBoYW5kbGVyLnN0b3AuYmluZChoYW5kbGVyKVxuICAgIHRoaXMubXV0ZSA9IGhhbmRsZXIubXV0ZS5iaW5kKGhhbmRsZXIpXG4gICAgdGhpcy51bm11dGUgPSBoYW5kbGVyLnVubXV0ZS5iaW5kKGhhbmRsZXIpXG4gICAgdGhpcy5zZXRWb2x1bWUgPSBoYW5kbGVyLnNldFZvbHVtZS5iaW5kKGhhbmRsZXIpXG4gICAgdGhpcy5zZWVrVG8gPSBoYW5kbGVyLnNlZWtUby5iaW5kKGhhbmRsZXIpXG4gICAgdGhpcy50b2dnbGVGdWxsU2NyZWVuID0gaGFuZGxlci50b2dnbGVGdWxsU2NyZWVuLmJpbmQoaGFuZGxlcilcblxuICAgIC8vIEFkYXB0aXZlIEJpdHJhdGUgQ29udHJvbGxlciAtIEF1dG9zY2FsZSBlbmFibGVkIG9ubHkuXG4gICAgdGhpcy5zZXRBQlJMZXZlbCA9IGhhbmRsZXIuc2V0QUJSTGV2ZWwuYmluZChoYW5kbGVyKVxuICAgIHRoaXMuc2V0QUJSVmFyaWFudHMgPSBoYW5kbGVyLnNldEFCUlZhcmlhbnRzLmJpbmQoaGFuZGxlcilcbiAgICB0aGlzLnN0b3BBQlJDb250cm9sbGVyID0gaGFuZGxlci5zdG9wQUJSQ29udHJvbGxlci5iaW5kKGhhbmRsZXIpXG4gICAgdGhpcy5zdGFydEFCUkNvbnRyb2xsZXIgPSBoYW5kbGVyLnN0YXJ0QUJSQ29udHJvbGxlci5iaW5kKGhhbmRsZXIpXG4gICAgdGhpcy5zZXRBQlJWYXJpYW50VXBncmFkZVNldHRpbmdzID0gaGFuZGxlci5zZXRBQlJWYXJpYW50VXBncmFkZVNldHRpbmdzLmJpbmQoaGFuZGxlcilcblxuICAgIGhhbmRsZXIub24oJyonLCAoZXZlbnQpID0+IHtcbiAgICAgIHRoaXMudHJpZ2dlcihuZXcgU3Vic2NyaWJlckV2ZW50KGV2ZW50LnR5cGUsIHRoaXMsIGV2ZW50LmRhdGEpKVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogU3RpbGwgaW4gdXNlLCBidXQgaG9sZC1vdmVyIG9mIHByZXZpb3VzIDMueCBTREsgdmVyc2lvbnMgZGVzaWduZWQgdG8gcGFpciB2aWV3cyBhbmQgc3Vic2NyaWJlcnMuIEluIDQuMC4wIGl0IGhhcyBiZWVuIGludGVybmFsaXplZC5cbiAgICogQVBJIGRlcHJlY2F0ZWQuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfc2V0Vmlld0lmTm90RXhpc3QgKGN1cnJlbnRWaWV3LCBtZWRpYUVsZW1lbnRJZCA9IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKHR5cGVvZiBjdXJyZW50VmlldyA9PT0gJ3VuZGVmaW5lZCcgJiYgbWVkaWFFbGVtZW50SWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBsZXQgdmlldyA9IG5ldyBQbGF5YmFja1ZpZXcobWVkaWFFbGVtZW50SWQpXG4gICAgICAgIHZpZXcuYXR0YWNoU3Vic2NyaWJlcih0aGlzKVxuICAgICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlZmluZSBnbG9iYWwgZnVuY3Rpb24gaGFuZGxlcnMgZm9yIEV4dGVybmFsSW50ZXJmYWNlIHRvIGludm9rZSBmb3IgQVBJIGNvbW11bmljYXRpb24uXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfZXN0YWJsaXNoRXh0SW50SGFuZGxlcnMgKGlkKSB7XG4gICAgZGVidWcoTkFNRSwgYFN1YnNjcmliZXIgSUQgcHJvdmlkZWQgdG8gY2xpZW50OiAoJHtpZH0pLmApXG4gICAgY29uc3QgaW52b2tlRm4gPSAobGFiZWwpID0+IHtcbiAgICAgIHJldHVybiBbJ3N1YnNjcmliZXInLCBsYWJlbCwgaWQuc3BsaXQoJy0nKS5qb2luKCdfJyldLmpvaW4oJ18nKVxuICAgIH1cbiAgICB3aW5kb3dbaW52b2tlRm4oJ3I1cHJvQ29ubmVjdENsb3NlZCcpXSA9ICgpID0+IHRoaXMudHJpZ2dlcihuZXcgU3Vic2NyaWJlckV2ZW50KFN1YnNjcmliZXJFdmVudFR5cGVzLkNPTk5FQ1RJT05fQ0xPU0VELCB0aGlzKSlcbiAgICB3aW5kb3dbaW52b2tlRm4oJ3I1cHJvQ29ubmVjdFN1Y2Nlc3MnKV0gPSAoKSA9PiB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChTdWJzY3JpYmVyRXZlbnRUeXBlcy5DT05ORUNUX1NVQ0NFU1MsIHRoaXMpKVxuICAgIHdpbmRvd1tpbnZva2VGbigncjVwcm9Db25uZWN0RmFpbHVyZScpXSA9ICgpID0+IHtcbiAgICAgIHRoaXMudHJpZ2dlcihuZXcgU3Vic2NyaWJlckV2ZW50KFN1YnNjcmliZXJFdmVudFR5cGVzLkNPTk5FQ1RfRkFJTFVSRSwgdGhpcykpXG4gICAgfVxuICAgIHdpbmRvd1tpbnZva2VGbigncjVwcm9TdWJzY3JpYmVTdG9wJyldID0gKCkgPT4gdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoU3Vic2NyaWJlckV2ZW50VHlwZXMuU1VCU0NSSUJFX1NUT1AsIHRoaXMpKVxuICAgIHdpbmRvd1tpbnZva2VGbigncjVwcm9TdWJzY3JpYmVNZXRhZGF0YScpXSA9IChtZXRhZGF0YSkgPT4gdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoU3Vic2NyaWJlckV2ZW50VHlwZXMuU1VCU0NSSUJFX01FVEFEQVRBLCB0aGlzLCBKU09OLnBhcnNlKG1ldGFkYXRhKSkpXG4gICAgd2luZG93W2ludm9rZUZuKCdyNXByb1N1YnNjcmliZVVucHVibGlzaCcpXSA9ICgpID0+IHRoaXMudHJpZ2dlcihuZXcgU3Vic2NyaWJlckV2ZW50KFN1YnNjcmliZXJFdmVudFR5cGVzLlBMQVlfVU5QVUJMSVNILCB0aGlzKSlcbiAgICB3aW5kb3dbaW52b2tlRm4oJ3I1cHJvU3Vic2NyaWJlU2VuZEludm9rZScpXSA9IChwYXlsb2FkKSA9PiB7XG4gICAgICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChTdWJzY3JpYmVyRXZlbnRUeXBlcy5TVUJTQ1JJQkVfU0VORF9JTlZPS0UsIHRoaXMsIHR5cGVvZiBwYXlsb2FkID09PSAnc3RyaW5nJyA/IEpTT04ucGFyc2UocGF5bG9hZCkgOiBwYXlsb2FkKSlcbiAgICB9XG4gICAgd2luZG93W2ludm9rZUZuKCdyNXByb1N1YnNjcmliZVBsYXlSZXF1ZXN0JyldID0gKCkgPT4ge1xuICAgICAgdGhpcy5wbGF5KClcbiAgICB9XG4gICAgd2luZG93W2ludm9rZUZuKCdyNXByb1N1YnNjcmliZVN0YXJ0JyldID0gKCkgPT4ge1xuICAgICAgdGhpcy5fc3Vic2NyaXB0aW9uUmVzb2x2ZXIucmVzb2x2ZSh0aGlzKVxuICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoU3Vic2NyaWJlckV2ZW50VHlwZXMuU1VCU0NSSUJFX1NUQVJULCB0aGlzKSlcbiAgICB9XG4gICAgd2luZG93W2ludm9rZUZuKCdyNXByb1N1YnNjcmliZUludmFsaWROYW1lJyldID0gKCkgPT4ge1xuICAgICAgdGhpcy5fc3Vic2NyaXB0aW9uUmVzb2x2ZXIucmVqZWN0KCdOZXRTdHJlYW0uUGxheS5TdHJlYW1Ob3RGb3VuZCcsIHRoaXMpXG4gICAgICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChTdWJzY3JpYmVyRXZlbnRUeXBlcy5TVUJTQ1JJQkVfSU5WQUxJRF9OQU1FLCB0aGlzKSlcbiAgICB9XG4gICAgd2luZG93W2ludm9rZUZuKCdyNXByb1N1YnNjcmliZUZhaWwnKV0gPSAoKSA9PiB7XG4gICAgICB0aGlzLl9zdWJzY3JpcHRpb25SZXNvbHZlci5yZWplY3QoJ05ldFN0cmVhbS5GYWlsZWQnLCB0aGlzKVxuICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoU3Vic2NyaWJlckV2ZW50VHlwZXMuU1VCU0NSSUJFX0ZBSUwsIHRoaXMpKVxuICAgIH1cbiAgICB3aW5kb3dbaW52b2tlRm4oJ3I1cHJvU3Vic2NyaWJlVm9sdW1lQ2hhbmdlJyldID0gKHBheWxvYWQpID0+IHtcbiAgICAgIHRoaXMudHJpZ2dlcihuZXcgU3Vic2NyaWJlckV2ZW50KFN1YnNjcmliZXJFdmVudFR5cGVzLlZPTFVNRV9DSEFOR0UsIHRoaXMsIHtcbiAgICAgICAgdm9sdW1lOiBKU09OLnBhcnNlKHBheWxvYWQpLnZvbHVtZVxuICAgICAgfSkpXG4gICAgfVxuICAgIHdpbmRvd1tpbnZva2VGbigncjVwcm9TdWJzY3JpYmVQbGF5YmFja1RpbWVDaGFuZ2UnKV0gPSAocGF5bG9hZCkgPT4ge1xuICAgICAgY29uc3QgZGF0YSA9IEpTT04ucGFyc2UocGF5bG9hZClcbiAgICAgIHRoaXMudHJpZ2dlcihuZXcgU3Vic2NyaWJlckV2ZW50KFN1YnNjcmliZXJFdmVudFR5cGVzLlBMQVlCQUNLX1RJTUVfVVBEQVRFLCB0aGlzLCB7XG4gICAgICAgIHRpbWU6IGRhdGEudmFsdWUsXG4gICAgICAgIGR1cmF0aW9uOiBkYXRhLmR1cmF0aW9uXG4gICAgICB9KSlcbiAgICB9XG4gICAgd2luZG93W2ludm9rZUZuKCdyNXByb1N1YnNjcmliZVBsYXliYWNrU3RhdGVDaGFuZ2UnKV0gPSAocGF5bG9hZCkgPT4ge1xuICAgICAgY29uc3QgY29kZSA9IEpTT04ucGFyc2UocGF5bG9hZCkuY29kZVxuICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoU3Vic2NyaWJlckV2ZW50VHlwZXMuUExBWUJBQ0tfU1RBVEVfQ0hBTkdFLCB0aGlzLCB7XG4gICAgICAgIGNvZGU6IGNvZGUsXG4gICAgICAgIHN0YXRlOiBQbGF5YmFja1N0YXRlUmVhZGFibGVbY29kZV1cbiAgICAgIH0pKVxuICAgIH1cbiAgICB3aW5kb3dbaW52b2tlRm4oJ3I1cHJvU3Vic2NyaWJlQUJSTGV2ZWxDaGFuZ2UnKV0gPSAocGF5bG9hZCkgPT4ge1xuICAgICAgY29uc3QgZGF0YSA9IEpTT04ucGFyc2UocGF5bG9hZClcbiAgICAgIGNvbnN0IHsgbGV2ZWwsIHN0cmVhbSB9ID0gZGF0YVxuICAgICAgY29uc3Qgc2V0dGluZ3MgPSBKU09OLnBhcnNlKGRlY29kZVVSSUNvbXBvbmVudChzdHJlYW0pKVxuICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoUlRNUFN1YnNjcmliZXJFdmVudFR5cGVzLkFCUl9MRVZFTF9DSEFOR0UsIHRoaXMsIHtcbiAgICAgICAgbGV2ZWw6IGxldmVsLFxuICAgICAgICBzdHJlYW06IHNldHRpbmdzXG4gICAgICB9KSlcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBpbml0aWFsaXplIHRoZSBITFMtYmFzZWQgU3Vic2NyaWJlciBiYXNlZCBvbiBjb25maWd1cmF0aW9uLlxuICAgKiBUaGUgcmV0dXJuZWQgYFByb21pc2VgIHdpbGwgZWl0aGVyIHJlc29sdmUgd2l0aCBhIHJlZmVyZW5jZSB0byB0aGlzIGluc3RhbmNlIG9yIHJlamVjdCB3aXRoIGFuIGVycm9yIGBTdHJpbmdgIGluIGZhaWx1cmUuXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqICAgICAgICBUaGUgaW5pdGlhbGl6YXRpb24gY29uZmlndXJhdGlvbiBtYXAuXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqL1xuICBpbml0IChvcHRpb25zKSB7XG4gICAgY29uc3QgZGVmZXJyZWQgPSBuZXcgRGVmZXJyZWRQcm9taXNlKClcbiAgICBjb25zdCB2ZXJzaW9uID0gb3B0aW9ucy5taW5GbGFzaFZlcnNpb24gfHwgZGVmYXVsdE9wdGlvbnMubWluRmxhc2hWZXJzaW9uXG4gICAgaWYgKCFlbnZpcm9ubWVudC5zdXBwb3J0c0ZsYXNoVmVyc2lvbih2ZXJzaW9uKSkge1xuICAgICAgd2FybihOQU1FLCBgQ291bGQgbm90IHJlc29sdmUgUlRNUFN1YnNjcmliZXIgaW5zdGFuY2UuIFJlcXVpcmVzIG1pbmltdW0gRmxhc2ggUGxheWVyIGluc3RhbGwgb2YgJHt2ZXJzaW9ufS5gKVxuICAgICAgZGVmZXJyZWQucmVqZWN0KGBDb3VsZCBub3QgcmVzb2x2ZSBSVE1QU3Vic2NyaWJlciBpbnN0YW5jZS4gUmVxdWlyZXMgbWluaW11bSBGbGFzaCBQbGF5ZXIgaW5zdGFsbCBvZiAke3ZlcnNpb259LmApXG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgdGhpcy5fb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oe30sIGRlZmF1bHRPcHRpb25zLCBvcHRpb25zKVxuICAgICAgY29uc3QgZXN0YWJsaXNoU291cmNlSGFuZGxlciA9ICgpID0+IHtcbiAgICAgICB0aGlzLl9nZXRWaWV3UmVzb2x2ZXJQcm9taXNlKClcbiAgICAgICAgLnRoZW4odmlldyA9PiB7XG4gICAgICAgICAgdGhpcy5fc291cmNlSGFuZGxlciA9IG5ldyBSVE1QU291cmNlSGFuZGxlcih0aGlzLCB2aWV3LnZpZXcsIHRoaXMuZ2V0VHlwZSgpKVxuICAgICAgICAgIHRoaXMuX2dsb21Tb3VyY2VIYW5kbGVyQVBJKHRoaXMuX3NvdXJjZUhhbmRsZXIpXG4gICAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMpIHtcbiAgICAgICAgICAgIGNvbnN0IGRmZCA9IHRoaXMuX2VtYmVkUHJvbWlzZVxuICAgICAgICAgICAgdGhpcy5fc291cmNlSGFuZGxlci5hZGRTb3VyY2UodGhpcy5fZWxlbWVudElkLCB0aGlzLl9vcHRpb25zKVxuICAgICAgICAgICAgICAudGhlbihzdWJzY3JpYmVySWQgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuX2VzdGFibGlzaEV4dEludEhhbmRsZXJzKHN1YnNjcmliZXJJZClcbiAgICAgICAgICAgICAgICBkZmQucmVzb2x2ZSh0aGlzKVxuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAuY2F0Y2goZXJyID0+IGRmZC5yZWplY3QoZXJyKSlcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICB9XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGVudmlyb25tZW50LmluamVjdFNjcmlwdCh0aGlzLl9vcHRpb25zLnN3Zm9iamVjdFVSTClcbiAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBlbWJlZERmZCA9IHRoaXMuX2VtYmVkUHJvbWlzZVxuICAgICAgICAgICAgZGVidWcoTkFNRSwgJ1NXRk9iamVjdCBlbWJlZGRlZC4nKVxuICAgICAgICAgICAgaWYgKHRoaXMuX3NvdXJjZUhhbmRsZXIpIHtcbiAgICAgICAgICAgICAgdGhpcy5fc291cmNlSGFuZGxlci5hZGRTb3VyY2UodGhpcy5fZWxlbWVudElkLCB0aGlzLl9vcHRpb25zKVxuICAgICAgICAgICAgICAgIC50aGVuKHN1YnNjcmliZXJJZCA9PiB7XG4gICAgICAgICAgICAgICAgICB0aGlzLl9lc3RhYmxpc2hFeHRJbnRIYW5kbGVycyhzdWJzY3JpYmVySWQpXG4gICAgICAgICAgICAgICAgICBlbWJlZERmZC5yZXNvbHZlKHRoaXMpXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgICAgICAgICAgIGVtYmVkRGZkLnJlamVjdChlcnIpXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2dldEVtYmVkUHJvbWlzZSgpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlc3RhYmxpc2hTb3VyY2VIYW5kbGVyKClcbiAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgICAgfSlcbiAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLl9zZXRWaWV3SWZOb3RFeGlzdCh0aGlzLl92aWV3LCB0aGlzLl9vcHRpb25zLm1lZGlhRWxlbWVudElkKVxuICAgICAgICAgICAgZGVmZXJyZWQucmVzb2x2ZSh0aGlzKVxuICAgICAgICAgIH0pXG4gICAgICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgICAgICBlcnJvcihOQU1FLCBgQ291bGQgbm90IGVtYmVkIEZsYXNoLWJhc2VkIFJUTVAgUGxheWVyLiBSZWFzb246ICR7ZXJyfWApXG4gICAgICAgICAgICBpZiAodGhpcy5fc291cmNlSGFuZGxlcikge1xuICAgICAgICAgICAgICB0aGlzLl9zb3VyY2VIYW5kbGVyLmRpc2Nvbm5lY3QoKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICBkZWZlcnJlZC5yZWplY3QoZXJyKVxuICAgICAgICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoUlRNUFN1YnNjcmliZXJFdmVudFR5cGVzLkVNQkVEX0ZBSUxVUkUsIHRoaXMpKVxuICAgICAgICAgIH0pXG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGRlZmVycmVkLnJlamVjdChgQ291bGQgbm90IGluamVjdCBGbGFzaC1iYXNlZCBQbGF5ZXIgaW50byB0aGUgcGFnZS4gUmVhc29uOiAke2UubWVzc2FnZX1gKVxuICAgICAgICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChSVE1QU3Vic2NyaWJlckV2ZW50VHlwZXMuRU1CRURfRkFJTFVSRSwgdGhpcykpXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBkZWZlcnJlZC5wcm9taXNlXG4gIH1cblxuICAvKipcbiAgICogU3RpbGwgaW4gdXNlIGZvciBhc3NpZ25pbmcgZG9jdW1lbnQgZWxlbWVudCB2aWV3IG1hbmFnZW1lbnQgdG8gdGhpcyBpbnN0YW5jZS5cbiAgICogQVBJIGRlcHJlY2F0ZWQgaW4gNC4wLjAuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBzZXRWaWV3ICh2aWV3LCBlbGVtZW50SWQpIHtcbiAgICB0aGlzLl92aWV3ID0gdmlld1xuICAgIHRoaXMuX2VsZW1lbnRJZCA9IGVsZW1lbnRJZFxuICAgIHRoaXMuX3ZpZXdSZXNvbHZlci5yZXNvbHZlKHRoaXMuX3ZpZXcpXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIGJlZ2luIHN1YnNjcmliaW5nIHRvIGEgc3RyZWFtLlxuICAgKlxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgICAgICAgICBUaGUgcmV0dXJuZWQgYFByb21pc2VgIHdpbGwgcmVzb2x2ZSBvciByZWplY3Qgb24gc3VjY2Vzc2Z1bCBzdGFydCBvZiBwbGF5YmFjay5cbiAgICovXG4gIHN1YnNjcmliZSAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2dldFN1YnNjcmlwdGlvblJlc29sdmVyUHJvbWlzZSgpXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBzdG9wIGEgc3Vic2NyaXB0aW9uLlxuICAgKiBUaGUgcmV0dXJuZWQgYFByb21pc2VgIHdpbGwgZWl0aGVyIHJlc29sdmUgb3IgcmVqZWN0IG9uIHN1Y2Nlc3NmdWwgc3RvcCBvZiBzdWJzY3JpcHRpb24uXG4gICAqXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqL1xuICB1bnN1YnNjcmliZSAoKSB7XG4gICAgZGVidWcoTkFNRSwgJ1t1bnN1YnNjcmliZV0nKTtcbiAgICBjb25zdCBjYiA9IChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHRoaXMuX3NvdXJjZUhhbmRsZXIuZGlzY29ubmVjdCgpXG4gICAgICAgIHJlc29sdmUoKVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZWplY3QoZS5tZXNzYWdlKVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbmV3IFByb21pc2UoY2IpXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBzdGFydCBwbGF5aW5nIHRoZSBzdHJlYW0uXG4gICAqL1xuICBwbGF5ICgpIHtcbiAgICBkZWJ1ZyhOQU1FLCAnW3BsYXldJyk7XG4gICAgdGhpcy5fZ2V0RW1iZWRQcm9taXNlKCkudGhlbigoKSA9PiB7XG4gICAgICB0aGlzLl9zb3VyY2VIYW5kbGVyLnBsYXkoKVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogRXZlbnQgaGFuZGxlciBmb3IgY29tcGxldGlvbiBvZiBlbWJlZGRpbmcgRmxhc2ggZWxlbWVudCBpbnRvIHBhZ2UuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBvbkVtYmVkQ29tcGxldGUgKCkge1xuICAgIGRlYnVnKE5BTUUsICdbZW1iZWQ6Y29tcGxldGVdJylcbiAgICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChSVE1QU3Vic2NyaWJlckV2ZW50VHlwZXMuRU1CRURfU1VDQ0VTUywgdGhpcykpXG4gIH1cblxuICAvKipcbiAgICogRXZlbnQgaGFuZGxlciBmb3IgZmFpbHVyZSBpbiBlbWJlZGRpbmcgRmxhc2ggZWxlbWVudCBpbnRvIHBhZ2UuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBvbkVtYmVkRmFpbHVyZSAoZXJyKSB7XG4gICAgZGVidWcoTkFNRSwgYFtlbWJlZDpmYWlsdXJlXSAtICR7ZXJyfWApXG4gICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoUlRNUFN1YnNjcmliZXJFdmVudFR5cGVzLkVNQkVEX0ZBSUxVUkUsIHRoaXMpKVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgY29ubmVjdGlvbiBoYW5kbGVyIGZvciBwbGF5YmFjay5cbiAgICogVXNlZCBpbiBTaGFyZWRPYmplY3QgY29tbXVuaWNhdGlvbi5cbiAgICpcbiAgICogQHJldHVybiB7T2JqZWN0fVxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgZ2V0Q29ubmVjdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3NvdXJjZUhhbmRsZXJcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHJlZmVyZW5jZSB0byBwbGF5YmFjayBjb250cm9scyBpZiBhdmFpbGFibGUuXG4gICAqXG4gICAqIEByZXR1cm4ge1BsYXliYWNrQ29udHJvbHN9XG4gICAqL1xuICBnZXRDb250cm9scyAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3NvdXJjZUhhbmRsZXIgPyB0aGlzLl9zb3VyY2VIYW5kbGVyLmdldENvbnRyb2xzKCkgOiB1bmRlZmluZWRcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBpbml0aWFsaXphdGlvbiBjb25maWd1cmF0aW9uIHVzZWQgaW4gYGluaXQoKWAuXG4gICAqXG4gICAqIEByZXR1cm4ge09iamVjdH1cbiAgICovXG4gIGdldE9wdGlvbnMgKCkge1xuICAgIHJldHVybiB0aGlzLl9vcHRpb25zXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgdGFyZ2V0IHZpZXcgRWxlbWVudC5cbiAgICpcbiAgICogQHJldHVybiB7RWxlbWVudH1cbiAgICovXG4gIGdldFBsYXllciAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3NvdXJjZUhhbmRsZXIgPyB0aGlzLl9zb3VyY2VIYW5kbGVyLmdldEVtYmVkZGVkVmlldygpIDogdW5kZWZpbmVkXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgdHlwZSBvZiBpbXBsZW1lbnRhdGlvbjogYFJUTVBgLlxuICAgKlxuICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAqL1xuICBnZXRUeXBlICgpIHtcbiAgICByZXR1cm4gUGxheWJhY2tUeXBlcy5SVE1QLnRvVXBwZXJDYXNlKClcbiAgfVxuXG59XG5cbmV4cG9ydCBkZWZhdWx0IFJUTVBTdWJzY3JpYmVyXG5cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9qcy9zdWJzY3JpYmVyL3JlZDVwcm8tcnRtcC5qcyIsIid1c2Ugc3RyaWN0J1xuXG5pbXBvcnQgZW52aXJvbm1lbnQgZnJvbSAnLi4vZW52L2Jyb3dzZXInXG5pbXBvcnQgeyBhcHBseU9yaWVudGF0aW9uIH0gZnJvbSAnLi4vZW52L3RyYW5zbGF0aW9uLXV0aWwnXG5pbXBvcnQgeyBtZXRhZGF0YVJlc29sdXRpb25Ub09iamVjdCB9IGZyb20gJy4uL3V0aWwvb2JqZWN0J1xuaW1wb3J0IHsgUGxheWJhY2tDb250cm9sbGVyLCBQbGF5YmFja0NvbnRyb2xzSW1wbCB9IGZyb20gJy4vY29udHJvbHMnXG5pbXBvcnQgeyBQbGF5YmFja1N0YXRlLCBQbGF5YmFja1N0YXRlUmVhZGFibGUgfSBmcm9tICcuL2NvbnRyb2xzL3N0YXRlJ1xuaW1wb3J0IHsgU3Vic2NyaWJlckV2ZW50LCBTdWJzY3JpYmVyRXZlbnRUeXBlcyB9IGZyb20gJy4uL2V2ZW50J1xuaW1wb3J0IHsgRGVmZXJyZWRQcm9taXNlIH0gZnJvbSAnLi4vdXRpbC9wcm9taXNlJ1xuaW1wb3J0IHsgZGVidWcsIGVycm9yIH0gZnJvbSAnLi4vbG9nJ1xuXG5jb25zdCBOQU1FID0gJ0hMU1NvdXJjZUhhbmRsZXInXG5cbi8qKlxuICogU291cmNlIEhhbmRsZXIgZm9yIEhMUy1iYXNlZCBTdWJzY3JpYmVycywgd2hpY2ggc2VydmVzIGFzIGEgUHJlc2VudGF0aW9uIENvbnRyb2xsZXIgYmV0d2VlbiB2aWV3IGFuZCBzdWJzY3JpYmVyLlxuICpcbiAqIEBleHRlbmRzIEV2ZW50RW1pdHRlclxuICogQGV4dGVuZHMgU3Vic2NyaWJlclBsYXliYWNrQ29udHJvbGxlclxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmNsYXNzIEhMU1NvdXJjZUhhbmRsZXIgZXh0ZW5kcyBQbGF5YmFja0NvbnRyb2xsZXIge1xuXG4gIGNvbnN0cnVjdG9yIChtZWRpYSwgdHlwZSkge1xuICAgIHN1cGVyKClcbiAgICB0aGlzLm1lZGlhID0gbWVkaWFcbiAgICB0aGlzLmNsb25lID0gdGhpcy5tZWRpYS5jbG9uZU5vZGUodHJ1ZSlcbiAgICB0aGlzLnBhcmVudCA9IHRoaXMubWVkaWEucGFyZW50Tm9kZVxuICAgIHRoaXMuaG9sZGVyID0gdGhpcy5fZGV0ZXJtaW5lSG9sZGVyKG1lZGlhKVxuICAgIHRoaXMucGxheWVyVHlwZSA9IHR5cGVcbiAgICB0aGlzLl9pc1ZPRCA9IGZhbHNlXG4gICAgdGhpcy5fY29udHJvbHMgPSB1bmRlZmluZWRcbiAgICB0aGlzLl9wbGF5YmFja05vdGlmaWNhdGlvbkNlbnRlciA9IHRoaXMubWVkaWFcbiAgICBlbnZpcm9ubWVudC5vbkZ1bGxTY3JlZW5TdGF0ZUNoYW5nZSh0aGlzLl9oYW5kbGVGdWxsU2NyZWVuQ2hhbmdlLmJpbmQodGhpcykpXG4gIH1cblxuICAvKipcbiAgICogRXN0YWJsaXNoZWQgRE9NIEVsZW1lbnQgb3JkZXIgZm9yIHBsYXliYWNrLlxuICAgKlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IG1lZGlhXG4gICAqICAgICAgICBUaGUgdGFyZ2V0IG1lZGlhIGVsZW1lbnQ6IGUuZy4sIGB2aWRlb2Agb3IgYGF1ZGlvYC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9kZXRlcm1pbmVIb2xkZXIgKG1lZGlhKSB7XG4gICAgaWYgKG1lZGlhLnBhcmVudE5vZGUuY2xhc3NMaXN0LmNvbnRhaW5zKCdyZWQ1cHJvLW1lZGlhLWNvbnRhaW5lcicpKSB7XG4gICAgICByZXR1cm4gbWVkaWEucGFyZW50Tm9kZVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIGNvbnN0IHBhcmVudCA9IG1lZGlhLnBhcmVudE5vZGVcbiAgICAgIGNvbnN0IGRpdiA9IGVudmlyb25tZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpXG4gICAgICBkaXYuY2xhc3NMaXN0LmFkZCgncmVkNXByby1tZWRpYS1jb250YWluZXInKVxuICAgICAgcGFyZW50Lmluc2VydEJlZm9yZShkaXYsIG1lZGlhKVxuICAgICAgcGFyZW50LnJlbW92ZUNoaWxkKG1lZGlhKVxuICAgICAgZGl2LmFwcGVuZENoaWxkKG1lZGlhKVxuICAgICAgcmV0dXJuIGRpdlxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhbiB1cCBvZiBET00gRWxlbWVudCBvcmRlciB1cG9uIHN0b3Agb2YgcGxheWJhY2suXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfY2xlYW5VcCAoKSB7XG4gICAgLy8gUmV0dXJuIHRvIHByaW9yIERPTSBtYW5pcHVsYXRpb24uXG4gICAgbGV0IGVsID0gdGhpcy5tZWRpYVxuICAgIGxldCBlbFBhcmVudCA9IGVsLnBhcmVudE5vZGVcbiAgICBsZXQgbWVkaWFIb2xkZXIgPSB0aGlzLmhvbGRlclxuICAgIGlmIChlbFBhcmVudCkge1xuICAgICAgZWxQYXJlbnQucmVtb3ZlQ2hpbGQoZWwpXG4gICAgICAvLyBUaGUgb2JqZWN0IHBhcmVudCBjb3VsZCBiZSBhIHdyYXBwZXIgY2hpbGQgaW4gdGhlIG9yaWdpbmFsIHBhcmVudCBlbGVtZW50LlxuICAgICAgaWYgKGVsUGFyZW50ICE9PSB0aGlzLnBhcmVudCkge1xuICAgICAgICBlbFBhcmVudC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGVsUGFyZW50KVxuICAgICAgICBtZWRpYUhvbGRlciA9IHRoaXMucGFyZW50XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGVsLnJlbW92ZSgpXG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHdhcm4oTkFNRSwgYElzc3VlIGluIERPTSBjbGVhbnVwIG9mIGZsYXNoIG9iamVjdCBlbWJlZDogJHtlLm1lc3NhZ2V9YClcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5tZWRpYSA9IHRoaXMuY2xvbmUuY2xvbmVOb2RlKHRydWUpXG4gICAgbWVkaWFIb2xkZXIuYXBwZW5kQ2hpbGQodGhpcy5tZWRpYSlcbiAgICBpZiAodGhpcy5fY29udHJvbHMpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xzLmRldGFjaCgpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFzc2lnbnMgYW5kIGhhbmRsZXJzIGV2ZW50IG5vdGlmaWNpYXRpb25zIGNvbWluZyBmcm9tIHRoZSBtZWRpYSBub3RpZmllciAoZS5nLiwgYHZpZGVvYCBvciBgYXVkaW9gIGVsZW1lbnQpLlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gbm90aWZpZXJcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9hZGRQbGF5YmFja0hhbmRsZXJzIChub3RpZmllcikge1xuICAgIGNvbnN0IGNvbnRyb2xzID0gdGhpcy5nZXRDb250cm9scygpXG4gICAgY29uc3QgaGFzQ29udHJvbHMgPSB0eXBlb2YgY29udHJvbHMgIT09ICd1bmRlZmluZWQnXG5cbiAgICBub3RpZmllci5vbmNhbnBsYXkgPSAoKSA9PiB7XG4gICAgICBpZiAoY29udHJvbHMpIHtcbiAgICAgICAgY29udHJvbHMuZW5hYmxlKHRydWUpXG4gICAgICB9XG4gICAgICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChTdWJzY3JpYmVyRXZlbnRUeXBlcy5QTEFZQkFDS19TVEFURV9DSEFOR0UsIHVuZGVmaW5lZCwge1xuICAgICAgICBjb2RlOiBQbGF5YmFja1N0YXRlLkFWQUlMQUJMRSxcbiAgICAgICAgc3RhdGU6IFBsYXliYWNrU3RhdGVSZWFkYWJsZVtQbGF5YmFja1N0YXRlLkFWQUlMQUJMRV1cbiAgICAgIH0pKVxuICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoU3Vic2NyaWJlckV2ZW50VHlwZXMuVk9MVU1FX0NIQU5HRSwgdW5kZWZpbmVkLCB7XG4gICAgICAgIHZvbHVtZTogbm90aWZpZXIudm9sdW1lXG4gICAgICB9KSlcbiAgICB9XG4gICAgbm90aWZpZXIub25kdXJhdGlvbmNoYW5nZSA9IChldmVudCkgPT4geyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gICAgICBpZiAoIWlzTmFOKG5vdGlmaWVyLmR1cmF0aW9uKSAmJiBOdW1iZXIuaXNGaW5pdGUobm90aWZpZXIuZHVyYXRpb24pKSB7XG4gICAgICAgIHRoaXMuaXNWT0QgPSB0cnVlXG4gICAgICB9XG4gICAgICBpZiAoaGFzQ29udHJvbHMpIHtcbiAgICAgICAgY29udHJvbHMuc2V0UGxheWJhY2tEdXJhdGlvbihub3RpZmllci5kdXJhdGlvbilcbiAgICAgIH1cbiAgICB9XG4gICAgbm90aWZpZXIub25lbmRlZCA9ICgpID0+IHtcbiAgICAgIGRlYnVnKE5BTUUsICdbdmlkZW9lbGVtZW50Om9uZW5kZWRdJylcbiAgICAgIGlmIChoYXNDb250cm9scykge1xuICAgICAgICBjb250cm9scy5zZXRTdGF0ZShQbGF5YmFja1N0YXRlLklETEUpXG4gICAgICB9XG4gICAgICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChTdWJzY3JpYmVyRXZlbnRUeXBlcy5QTEFZQkFDS19TVEFURV9DSEFOR0UsIHVuZGVmaW5lZCwge1xuICAgICAgICBjb2RlOiBQbGF5YmFja1N0YXRlLklETEUsXG4gICAgICAgIHN0YXRlOiBQbGF5YmFja1N0YXRlUmVhZGFibGVbUGxheWJhY2tTdGF0ZS5JRExFXVxuICAgICAgfSkpXG4gICAgfVxuICAgIG5vdGlmaWVyLm9udGltZXVwZGF0ZSA9IChldmVudCkgPT4geyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gICAgICBpZiAoaGFzQ29udHJvbHMpIHtcbiAgICAgICAgY29udHJvbHMuc2V0U2Vla1RpbWUobm90aWZpZXIuY3VycmVudFRpbWUsIHNlbGYuaXNWT0QgPyBub3RpZmllci5kdXJhdGlvbiA6IHVuZGVmaW5lZClcbiAgICAgIH1cbiAgICAgIHRoaXMudHJpZ2dlcihuZXcgU3Vic2NyaWJlckV2ZW50KFN1YnNjcmliZXJFdmVudFR5cGVzLlBMQVlCQUNLX1RJTUVfVVBEQVRFLCB1bmRlZmluZWQsIHtcbiAgICAgICAgdGltZTogbm90aWZpZXIuY3VycmVudFRpbWUsXG4gICAgICAgIGR1cmF0aW9uOiBub3RpZmllci5kdXJhdGlvblxuICAgICAgfSkpXG4gICAgfVxuICAgIG5vdGlmaWVyLm9uc2Vla2VkID0gKGV2ZW50KSA9PiB7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW51c2VkLXZhcnNcbi8vICAgICAgZGVidWcoTkFNRSwgJ1NlZWtlZC4nKVxuICAgIH1cbiAgICBub3RpZmllci5vbnNlZWtpbmcgPSAoZXZlbnQpID0+IHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuLy8gICAgICBkZWJ1ZyhOQU1FLCAnU2Vla2luZy4nKVxuICAgIH1cbiAgICBub3RpZmllci5vbnBsYXkgPSAoKSA9PiB7XG4gICAgICBpZiAoaGFzQ29udHJvbHMpIHtcbiAgICAgICAgY29udHJvbHMuc2V0U3RhdGUoUGxheWJhY2tTdGF0ZS5QTEFZSU5HKVxuICAgICAgfVxuICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoU3Vic2NyaWJlckV2ZW50VHlwZXMuUExBWUJBQ0tfU1RBVEVfQ0hBTkdFLCB1bmRlZmluZWQsIHtcbiAgICAgICAgY29kZTogUGxheWJhY2tTdGF0ZS5QTEFZSU5HLFxuICAgICAgICBzdGF0ZTogUGxheWJhY2tTdGF0ZVJlYWRhYmxlW1BsYXliYWNrU3RhdGUuUExBWUlOR11cbiAgICAgIH0pKVxuICAgIH1cbiAgICBub3RpZmllci5vbnBhdXNlID0gKCkgPT4ge1xuICAgICAgaWYgKGhhc0NvbnRyb2xzKSB7XG4gICAgICAgIGNvbnRyb2xzLnNldFN0YXRlKFBsYXliYWNrU3RhdGUuUEFVU0VEKVxuICAgICAgfVxuICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoU3Vic2NyaWJlckV2ZW50VHlwZXMuUExBWUJBQ0tfU1RBVEVfQ0hBTkdFLCB1bmRlZmluZWQsIHtcbiAgICAgICAgY29kZTogUGxheWJhY2tTdGF0ZS5QQVVTRUQsXG4gICAgICAgIHN0YXRlOiBQbGF5YmFja1N0YXRlUmVhZGFibGVbUGxheWJhY2tTdGF0ZS5QQVVTRURdXG4gICAgICB9KSlcbiAgICB9XG4gICAgbm90aWZpZXIub252b2x1bWVjaGFuZ2UgPSAoZXZlbnQpID0+IHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuICAgICAgaWYgKGhhc0NvbnRyb2xzICYmIGNvbnRyb2xzLmdldFZvbHVtZSgpICE9PSB0aGlzLm1lZGlhLnZvbHVtZSkge1xuICAgICAgICBjb250cm9scy5zZXRWb2x1bWUodGhpcy5tZWRpYS52b2x1bWUpXG4gICAgICB9XG4gICAgICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChTdWJzY3JpYmVyRXZlbnRUeXBlcy5WT0xVTUVfQ0hBTkdFLCB1bmRlZmluZWQsIHtcbiAgICAgICAgdm9sdW1lOiBub3RpZmllci5tdXRlZCA/IDAgOiBub3RpZmllci52b2x1bWVcbiAgICAgIH0pKVxuICAgIH1cbiAgICAvLyBmb3IgZGVidWdnaW5nIHB1cnBvc2VzLlxuICAgIG5vdGlmaWVyLm9uZW5jcnlwdGVkID0gKCkgPT4geyBkZWJ1ZyhOQU1FLCAnW3ZpZGVvZWxlbWVudDpldmVudF0gZW5jcnlwdGVkJykgfVxuICAgIG5vdGlmaWVyLm9uZW1wdGllZCA9ICgpID0+IHsgZGVidWcoTkFNRSwgJ1t2aWRlb2VsZW1lbnQ6ZXZlbnRdIGVtcHRpZWQnKSB9XG4gICAgbm90aWZpZXIub25sb2FkZWRkYXRhID0gKCkgPT4geyBkZWJ1ZyhOQU1FLCAnW3ZpZGVvZWxlbWVudDpldmVudF0gbG9hZGVkZGF0YScpIH1cbiAgICBub3RpZmllci5vbmxvYWRlZG1ldGFkYXRhID0gKCkgPT4geyBkZWJ1ZyhOQU1FLCAnW3ZpZGVvZWxlbWVudDpldmVudF0gbG9hZGVkbWV0YWRhdGEnKSB9XG4gICAgbm90aWZpZXIub25sb2Fkc3RhcnQgPSAoKSA9PiB7IGRlYnVnKE5BTUUsICdbdmlkZW9lbGVtZW50OmV2ZW50XSBsb2FkZWRzdGFydCcpIH1cbiAgICBub3RpZmllci5vbnN0YWxsZWQgPSAoKSA9PiB7IGRlYnVnKE5BTUUsICdbdmlkZW9lbGVtZW50OmV2ZW50XSBzdGFsbGVkJykgfVxuICAgIG5vdGlmaWVyLm9uc3VzcGVuZCA9ICgpID0+IHsgZGVidWcoTkFNRSwgJ1t2aWRlb2VsZW1lbnQ6ZXZlbnRdIHN1c3BlbmQnKSB9XG4gICAgbm90aWZpZXIub253YWl0aW5nID0gKCkgPT4geyBkZWJ1ZyhOQU1FLCAnW3ZpZGVvZWxlbWVudDpldmVudF0gd2FpdGluZycpIH1cbiAgICAvLyAgICBub3RpZmllci5vbnByb2dyZXNzID0gKCkgPT4geyBkZWJ1ZyhOQU1FLCAnW3ZpZGVvZWxlbWVudDpldmVudF0gcHJvZ3Jlc3MuIFBsYXllZDogJyArIG5vdGlmaWVyLnBsYXllZC5sZW5ndGggKyAnLCBCdWZmZXJlZDogJyArIG5vdGlmaWVyLmJ1ZmZlcmVkLmxlbmd0aCArICcuJykgfVxuICB9XG5cbiAgLyoqXG4gICAqIEV2ZW50IGhhbmRsZXIgZm9yIGNoYW5nZSBpbiBmdWxsc2NyZWVuIHN0YXRlLlxuICAgKlxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IGlzRnVsbFNjcmVlblxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX2hhbmRsZUZ1bGxTY3JlZW5DaGFuZ2UgKGlzRnVsbFNjcmVlbikge1xuICAgIGlmIChpc0Z1bGxTY3JlZW4pIHtcbiAgICAgIHRoaXMuaG9sZGVyLmNsYXNzTGlzdC5hZGQoJ3JlZDVwcm8tbWVkaWEtY29udGFpbmVyLWZ1bGwtc2NyZWVuJylcbiAgICAgIHRoaXMubWVkaWEuY2xhc3NMaXN0LmFkZCgncmVkNXByby1tZWRpYS1jb250YWluZXItZnVsbC1zY3JlZW4nKVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHRoaXMuaG9sZGVyLmNsYXNzTGlzdC5yZW1vdmUoJ3JlZDVwcm8tbWVkaWEtY29udGFpbmVyLWZ1bGwtc2NyZWVuJylcbiAgICAgIHRoaXMubWVkaWEuY2xhc3NMaXN0LnJlbW92ZSgncmVkNXByby1tZWRpYS1jb250YWluZXItZnVsbC1zY3JlZW4nKVxuICAgIH1cbiAgICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChTdWJzY3JpYmVyRXZlbnRUeXBlcy5GVUxMX1NDUkVFTl9TVEFURV9DSEFOR0UsIHVuZGVmaW5lZCwgaXNGdWxsU2NyZWVuKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWZpbmUgdGhlIHNvdXJjZSBlbGVtZW50IG9uIHRoZSBITFMgcGxheWJhY2sgZWxlbWVudC5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IHVybFxuICAgKiAgICAgICAgVGhlIHBsYXliYWNrIGVuZHBvaW50IFVSTC5cbiAgICogQHBhcmFtIHtTdHJpbmd9IHR5cGVcbiAgICogICAgICAgIFRoZSBtaW1lIHR5cGUgb2YgdGhlIHBsYXliYWNrIHN0cmVhbS5cbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICogICAgICAgIFRoZSBpbml0aWFsaXphdGlvbiBjb25maWd1cmF0aW9uIG1hcC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9lbWJlZE1lZGlhU291cmNlICh1cmwsIHR5cGUsIG9wdGlvbnMpIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzXG4gICAgY29uc3QgZGVmZXJyZWQgPSBuZXcgRGVmZXJyZWRQcm9taXNlKClcbiAgICB0cnkge1xuICAgICAgbGV0IHNvdXJjZSA9IGVudmlyb25tZW50LmNyZWF0ZUVsZW1lbnQoJ3NvdXJjZScpXG4gICAgICBzb3VyY2UudHlwZSA9IHR5cGVcbiAgICAgIHNvdXJjZS5zcmMgPSB1cmxcbiAgICAgIGlmICh0aGlzLm1lZGlhLmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgdGhpcy5tZWRpYS5pbnNlcnRCZWZvcmUoc291cmNlLCB0aGlzLm1lZGlhLmZpcnN0Q2hpbGQpXG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgdGhpcy5tZWRpYS5hcHBlbmRDaGlsZChzb3VyY2UpXG4gICAgICB9XG4gICAgICBzZWxmLm9yaWVudGF0aW9uID0gMFxuICAgICAgZW52aXJvbm1lbnQub25PcmllbnRhdGlvbk1ldGFkYXRhKHRoaXMubWVkaWEsIChtZXRhZGF0YSkgPT4ge1xuICAgICAgICBkZWJ1ZyhOQU1FLCAnTWV0YWRhdGEgcmVjZWl2ZWQ6ICcgKyBKU09OLnN0cmluZ2lmeShtZXRhZGF0YSwgbnVsbCwgMikpXG4gICAgICAgIGlmIChzZWxmLm9yaWVudGF0aW9uICE9PSBtZXRhZGF0YS5vcmllbnRhdGlvbikge1xuICAgICAgICAgIHNlbGYub3JpZW50YXRpb24gPSBtZXRhZGF0YS5vcmllbnRhdGlvblxuICAgICAgICAgIGlmIChvcHRpb25zLmF1dG9MYXlvdXRPcmllbnRhdGlvbikge1xuICAgICAgICAgICAgYXBwbHlPcmllbnRhdGlvbihzZWxmLm1lZGlhLCBwYXJzZUludChtZXRhZGF0YS5vcmllbnRhdGlvbiwgMTApLCBtZXRhZGF0YVJlc29sdXRpb25Ub09iamVjdChtZXRhZGF0YS5yZXNvbHV0aW9uKSlcbiAgICAgICAgICAgIHNlbGYuaGFuZGxlT3JpZW50YXRpb25DaGFuZ2UocGFyc2VJbnQoc2VsZi5vcmllbnRhdGlvbikpXG4gICAgICAgICAgfVxuICAgICAgICAgIHNlbGYudHJpZ2dlcihuZXcgU3Vic2NyaWJlckV2ZW50KFN1YnNjcmliZXJFdmVudFR5cGVzLk9SSUVOVEFUSU9OX0NIQU5HRSwgdW5kZWZpbmVkLCB7XG4gICAgICAgICAgICBvcmllbnRhdGlvbjogcGFyc2VJbnQoc2VsZi5vcmllbnRhdGlvbiksXG4gICAgICAgICAgICB2aWV3RWxlbWVudDogc2VsZi5tZWRpYVxuICAgICAgICAgIH0pKVxuICAgICAgICAgIHNlbGYudHJpZ2dlcihuZXcgU3Vic2NyaWJlckV2ZW50KFN1YnNjcmliZXJFdmVudFR5cGVzLlNVQlNDUklCRV9NRVRBREFUQSwgdW5kZWZpbmVkLCBtZXRhZGF0YSkpXG4gICAgICAgIH1cbiAgICAgICAgc2VsZi5vcmllbnRhdGlvbiA9IG1ldGFkYXRhLm9yaWVudGF0aW9uXG4gICAgICAgIH0pXG4gICAgICBkZWZlcnJlZC5yZXNvbHZlKClcbiAgICB9XG4gICAgY2F0Y2ggKGUpIHtcbiAgICAgIGRlZmVycmVkLnJlamVjdChlLm1lc3NhZ2UpXG4gICAgfVxuICAgIHJldHVybiBkZWZlcnJlZC5wcm9taXNlXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBzZXR1cCB0aGUgcHJlc2VudGF0aW9uIG9mIGEgcGxheWJhY2sgc3RyZWFtIHVzaW5nIEhMUy5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IHVybFxuICAgKiAgICAgICAgVGhlIGVuZHBvaW50IFVSTCBmb3IgcGxheWJhY2suXG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlXG4gICAqICAgICAgICBUaGUgbWltZSB0eXBlIGZvciBwbGF5YmFjay5cbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICogICAgICAgIFRoZSBpbml0aWFsaXphdGlvbiBjb25maWd1cmF0aW9uIG1hcC5cbiAgICpcbiAgICogQHJldHVybnMge1Byb21pc2V9XG4gICAqL1xuICBhZGRTb3VyY2UgKHVybCwgdHlwZSwgb3B0aW9ucykge1xuICAgIGRlYnVnKE5BTUUsICdbYWRkc291cmNlXScpXG4gICAgdGhpcy5ob2xkZXIgPSB0aGlzLl9kZXRlcm1pbmVIb2xkZXIodGhpcy5tZWRpYSlcbiAgICBjb25zdCBkZWZlcnJlZCA9IG5ldyBEZWZlcnJlZFByb21pc2UoKVxuICAgIGNvbnN0IGhhc0RlZmluZWRDb250cm9scyA9IG9wdGlvbnMuY29udHJvbHNcbiAgICBjb25zdCBpc011dGVkID0gZW52aXJvbm1lbnQuaGFzQXR0cmlidXRlRGVmaW5lZCh0aGlzLm1lZGlhLCAnbXV0ZWQnKVxuICAgIGNvbnN0IHVzZVBsYXliYWNrQ29udHJvbHMgPSBlbnZpcm9ubWVudC5oYXNBdHRyaWJ1dGVEZWZpbmVkKHRoaXMubWVkaWEsICdjb250cm9scycpICYmIGVudmlyb25tZW50Lmhhc0NsYXNzRGVmaW5lZCh0aGlzLm1lZGlhLCAncmVkNXByby1tZWRpYScpXG4gICAgdGhpcy5fZW1iZWRNZWRpYVNvdXJjZSh1cmwsIHR5cGUsIG9wdGlvbnMpXG4gICAgICAudGhlbiggKCkgPT4ge1xuICAgICAgICBpZiAoaGFzRGVmaW5lZENvbnRyb2xzIHx8IHVzZVBsYXliYWNrQ29udHJvbHMpIHtcbiAgICAgICAgICBpZiAoaGFzRGVmaW5lZENvbnRyb2xzKSB7XG4gICAgICAgICAgICB0aGlzLl9jb250cm9scyA9IG9wdGlvbnMuY29udHJvbHNcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9jb250cm9scyA9IG5ldyBQbGF5YmFja0NvbnRyb2xzSW1wbCh0aGlzLCB0aGlzLmhvbGRlcilcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5tZWRpYS5jb250cm9scyA9IGZhbHNlXG4gICAgICAgICAgdGhpcy5fY29udHJvbHMuc2V0QXNWT0QodGhpcy5pc1ZPRClcbiAgICAgICAgICB0aGlzLl9jb250cm9scy5zZXRNdXRlZFN0YXRlKGlzTXV0ZWQpXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fYWRkUGxheWJhY2tIYW5kbGVycyh0aGlzLl9wbGF5YmFja05vdGlmaWNhdGlvbkNlbnRlcilcbiAgICAgICAgZGVmZXJyZWQucmVzb2x2ZSgpXG4gICAgICB9KVxuICAgICAgLmNhdGNoKGUgPT4gZGVmZXJyZWQucmVqZWN0KGUpKVxuICAgIHJldHVybiBkZWZlcnJlZC5wcm9taXNlXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBjb25uZWN0IHRvIHN0cmVhbS5cbiAgICovXG4gIGNvbm5lY3QgKCkge1xuICAgIGRlYnVnKE5BTUUsICdbY29ubmVjdF0nKVxuICB9XG5cbiAgcGxheSAoKSB7XG4gICAgZGVidWcoTkFNRSwgJ1t2aWRlb2VsZW1lbnQ6YWN0aW9uXSBwbGF5JylcbiAgICB0cnkge1xuICAgICAgbGV0IG1heWJlUHJvbWlzZSA9IHRoaXMubWVkaWEucGxheSgpXG4gICAgICBpZiAobWF5YmVQcm9taXNlKSB7XG4gICAgICAgIG1heWJlUHJvbWlzZS50aGVuKCgpID0+IGRlYnVnKE5BTUUsICdbdmlkZW9lbGVtZW50OmFjdGlvbl0gcGxheSAoU1RBUlQpJykpXG4gICAgICAgICAgICAgICAgICAgIC5jYXRjaCgoZXJyKSA9PiBlcnJvcihOQU1FLCAnW3ZpZGVvZWxlbWVudDphY3Rpb25dIHBsYXkgKEZBVUxUKSAnICsgKGVyci5tZXNzYWdlID8gZXJyLm1lc3NhZ2UgOiBlcnIpKSlcbiAgICAgIH1cbiAgICB9XG4gICAgY2F0Y2ggKGUpIHtcbiAgICAgIGVycm9yKE5BTUUsICdbdmlkZW9lbGVtZW50OmFjdGlvbl0gcGxheSAoRkFVTFQpIC0gJyArIGUubWVzc2FnZSk7XG4gICAgfVxuICB9XG5cbiAgcGF1c2UgKCkge1xuICAgIGRlYnVnKE5BTUUsICdbdmlkZW9lbGVtZW50OmFjdGlvbl0gcGF1c2UnKVxuICAgIHRyeSB7XG4gICAgICB0aGlzLm1lZGlhLnBhdXNlKClcbiAgICB9XG4gICAgY2F0Y2ggKGUpIHtcbiAgICAgIGRlYnVnKE5BTUUsICdbdmlkZW9lbGVtZW50OmFjdGlvbl0gcGF1c2UgKEZBVUxUKSAtICcgKyBlLm1lc3NhZ2UpO1xuICAgIH1cbiAgfVxuXG4gIHJlc3VtZSAoKSB7XG4gICAgZGVidWcoTkFNRSwgJ1t2aWRlb2VsZW1lbnQ6YWN0aW9uXSByZXN1bWUnKVxuICAgIHRyeSB7XG4gICAgICBsZXQgbWF5YmVQcm9taXNlID0gdGhpcy5tZWRpYS5wbGF5KClcbiAgICAgIGlmIChtYXliZVByb21pc2UpIHtcbiAgICAgICAgbWF5YmVQcm9taXNlLnRoZW4oKCkgPT4gZGVidWcoTkFNRSwgJ1t2aWRlb2VsZW1lbnQ6YWN0aW9uXSBwbGF5IChTVEFSVCknKSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKChlcnIpID0+IGVycm9yKE5BTUUsICdbdmlkZW9lbGVtZW50OmFjdGlvbl0gcGxheSAoRkFVTFQpICcgKyAoZXJyLm1lc3NhZ2UgPyBlcnIubWVzc2FnZSA6IGVycikpKVxuICAgICAgfVxuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgZXJyb3IoTkFNRSwgJ1t2aWRlb2VsZW1lbnQ6YWN0aW9uXSByZXN1bWUgKEZBVUxUKSAtICcgKyBlLm1lc3NhZ2UpO1xuICAgIH1cbiAgfVxuXG4gIHN0b3AgKCkge1xuICAgIHRyeSB7XG4gICAgICB0aGlzLm1lZGlhLnN0b3AoKVxuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgLy8gb2suXG4gICAgfVxuICB9XG5cbiAgbXV0ZSAoKSB7XG4gICAgdGhpcy5tZWRpYS5tdXRlZCA9IHRydWVcbiAgfVxuXG4gIHVubXV0ZSAoKSB7XG4gICAgdGhpcy5tZWRpYS5tdXRlZCA9IGZhbHNlXG4gIH1cblxuICBzZXRWb2x1bWUgKHZhbHVlKSB7XG4gICAgdGhpcy51bm11dGUoKVxuICAgIHRoaXMubWVkaWEudm9sdW1lID0gdmFsdWVcbiAgfVxuXG4gIHNlZWtUbyAocGVyY2VudGFnZSwgZHVyYXRpb24gPSB1bmRlZmluZWQpIHtcbiAgICB0aGlzLm1lZGlhLmN1cnJlbnRUaW1lID0gZHVyYXRpb24gPyBwZXJjZW50YWdlICogZHVyYXRpb24gOiBwZXJjZW50YWdlXG4gIH1cblxuICB0b2dnbGVGdWxsU2NyZWVuICgpIHtcbiAgICB0cnkge1xuICAgICAgZW52aXJvbm1lbnQudG9nZ2xlRnVsbFNjcmVlbih0aGlzLmhvbGRlcilcbiAgICB9XG4gICAgY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IGU7XG4gICAgICAvLyBuYWRhLlxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBOb3RpZmljYXRpb24gb2YgY3VycmVudCBzdHJlYW0gYmVpbmcgaW4gYW4gdW5wdWJsaXNoZWQgc3RhdGUuXG4gICAqIFRoZSBzdHJlYW0gZW50ZXJzIGFuIHVucHVibGlzaGVkIHN0YXRlIHdoZW4gdGhlIGJyb2FkY2FzdGVyIHN0b3AgdGhlIHN0cmVhbSBhbmQgdGhlIHN1YnNjcmliZXIgaXMgc3RpbGwgY29ubmVjdGVkLlxuICAgKi9cbiAgdW5wdWJsaXNoICgpIHtcbiAgICB0cnkge1xuICAgICAgdGhpcy5zdG9wKClcbiAgICAgIHRoaXMubWVkaWEub25lbmRlZC5jYWxsKHRoaXMubWVkaWEpXG4gICAgfVxuICAgIGNhdGNoIChlKSB7XG4gICAgICAvLyBuYWRhLlxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIGRpc2Nvbm5lY3QgcGxheWJhY2suXG4gICAqL1xuICBkaXNjb25uZWN0ICgpIHtcbiAgICB0aGlzLl9jbGVhblVwKClcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNwb25kZXIgdG8gY2hhbmdlIGluIG9yaWVudGF0aW9uIHJlY2VpdmVkIHRocm91Z2ggbWV0YWRhdGEuXG4gICAqXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBvcmllbnRhdGlvblxuICAgKiAgICAgICAgVGhlIG9yaWVudGF0aW9uIHZhbHVlLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgaGFuZGxlT3JpZW50YXRpb25DaGFuZ2UgKG9yaWVudGF0aW9uKSB7XG4gICAgaWYgKHRoaXMuX2NvbnRyb2xzICYmIChvcmllbnRhdGlvbiAlIDE4MCAhPT0gMCkpIHtcbiAgICAgIHRoaXMuaG9sZGVyLmNsYXNzTGlzdC5hZGQoJ3JlZDVwcm8tbWVkaWEtYmFja2dyb3VuZCcpXG4gICAgICB0aGlzLm1lZGlhLmNsYXNzTGlzdC5yZW1vdmUoJ3JlZDVwcm8tbWVkaWEtYmFja2dyb3VuZCcpXG4gICAgfVxuICB9XG5cbiAgLypcbiAgICogfHwgU0hBUkVEIE9CSkVDVCBJTlRFR1JBVElPTiBOT1QgQVZBSUxBQkxFIEZPUiBITFMgUExBWUJBQ0sgfHxcbiAgICovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bnVzZWQtdmFyc1xuICBhZGRTaGFyZWRPYmplY3RSZXNwb25zZUhhbmRsZXIgKGhhbmRsZXIpIHt9XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVudXNlZC12YXJzXG4gIHJlbW92ZVNoYXJlZE9iamVjdFJlc3BvbnNlSGFuZGxlciAoaGFuZGxlcikge31cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW51c2VkLXZhcnNcbiAgc2VuZFRvU2hhcmVkT2JqZWN0IChuYW1lLCBjYWxsTmFtZSwgbWVzc2FnZSkge31cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW51c2VkLXZhcnNcbiAgc2VuZFByb3BlcnR5VG9TaGFyZWRPYmplY3QgKG5hbWUsIGtleSwgdmFsdWUpIHt9XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVudXNlZC12YXJzXG4gIGdldFJlbW90ZVNoYXJlZE9iamVjdCAoc2hhcmVkT2JqZWN0TmFtZSkge31cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW51c2VkLXZhcnNcbiAgY29ubmVjdFRvU2hhcmVkT2JqZWN0IChzaGFyZWRPYmplY3ROYW1lKSB7fVxuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bnVzZWQtdmFyc1xuICBjbG9zZVNoYXJlZE9iamVjdCAoc2hhcmVkT2JqZWN0TmFtZSkge31cblxuICAvKipcbiAgICogUmV0dXJucyBwbGF5YmFjayBjb250cm9scyBpZiBhdmFpbGFibGUuXG4gICAqXG4gICAqIEByZXR1cm5zIHtQbGF5YmFja0NvbnRyb2xzfVxuICAgKi9cbiAgZ2V0Q29udHJvbHMgKCkge1xuICAgIHJldHVybiB0aGlzLl9jb250cm9sc1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHN1YnNjcmliZXIgdHlwZSBhc3NvY2lhdGVkIHdpdGggdGhpcyBjb250cm9sbGVyLlxuICAgKlxuICAgKiBAcmV0dXJucyB7U3RyaW5nfVxuICAgKi9cbiAgZ2V0VHlwZSAoKSB7XG4gICAgcmV0dXJuIHRoaXMucGxheWVyVHlwZVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgZmxhZyBvZiB2aWRlbyBiZWluZyByZWNvZ25pemVkIGFzIFZPRCAoVmlkZW8gT24gRGVtYW5kKS5cbiAgICpcbiAgICogQHJldHVybnMge0Jvb2xlYW59XG4gICAqL1xuICBnZXQgaXNWT0QgKCkge1xuICAgIHJldHVybiB0aGlzLl9pc1ZPRFxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgZmxhZyBvZiB2aWRlbyBiZWluZyBjb25zaWRlcmVkIGFzIFZPRCAoVmlkZW8gT24gRGVtYW5kKS5cbiAgICpcbiAgICogQHBhcmFtIHtCb29sZWFufSB2YWx1ZVxuICAgKi9cbiAgc2V0IGlzVk9EICh2YWx1ZSkge1xuICAgIHRoaXMuX2lzVk9EID0gdmFsdWVcbiAgICBpZiAodGhpcy5fY29udHJvbHMpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xzLnNldEFzVk9EKHZhbHVlKVxuICAgIH1cbiAgfVxuXG59XG5cbmV4cG9ydCBkZWZhdWx0IEhMU1NvdXJjZUhhbmRsZXJcblxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2pzL3N1YnNjcmliZXIvcmVkNXByby1zb3VyY2UtaGFuZGxlci1obHMuanMiLCIndXNlIHN0cmljdCdcblxuaW1wb3J0IGVudmlyb25tZW50IGZyb20gJy4uL2Vudi9icm93c2VyJ1xuaW1wb3J0IHsgUGxheWJhY2tDb250cm9sbGVyLCBQbGF5YmFja0NvbnRyb2xzSW1wbCB9IGZyb20gJy4vY29udHJvbHMnXG5pbXBvcnQgeyBQbGF5YmFja1N0YXRlLCBQbGF5YmFja1N0YXRlUmVhZGFibGUgfSBmcm9tICcuL2NvbnRyb2xzL3N0YXRlJ1xuaW1wb3J0IHsgU3Vic2NyaWJlckV2ZW50LCBTdWJzY3JpYmVyRXZlbnRUeXBlcyB9IGZyb20gJy4uL2V2ZW50J1xuaW1wb3J0IHsgRGVmZXJyZWRQcm9taXNlIH0gZnJvbSAnLi4vdXRpbC9wcm9taXNlJ1xuaW1wb3J0IHsgZGVidWcsIGVycm9yLCB3YXJuIH0gZnJvbSAnLi4vbG9nJ1xuXG5jb25zdCBOQU1FID0gJ1JUQ1NvdXJjZUhhbmRsZXInXG5cbi8qKlxuICogU291cmNlIEhhbmRsZXIgZm9yIFdlYlJUQy1iYXNlZCBTdWJzY3JpYmVycywgd2hpY2ggc2VydmVzIGFzIGEgUHJlc2VudGF0aW9uIENvbnRyb2xsZXIgYmV0d2VlbiB2aWV3IGFuZCBzdWJzY3JpYmVyLlxuICpcbiAqIEBleHRlbmRzIEV2ZW50RW1pdHRlclxuICogQGV4dGVuZHMgU3Vic2NyaWJlclBsYXliYWNrQ29udHJvbGxlclxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmNsYXNzIFJUQ1NvdXJjZUhhbmRsZXIgZXh0ZW5kcyBQbGF5YmFja0NvbnRyb2xsZXIge1xuXG4gIGNvbnN0cnVjdG9yIChtZWRpYSwgdHlwZSkge1xuICAgIHN1cGVyKClcbiAgICB0aGlzLm1lZGlhID0gbWVkaWFcbiAgICB0aGlzLmNsb25lID0gdGhpcy5tZWRpYS5jbG9uZU5vZGUodHJ1ZSlcbiAgICB0aGlzLnBhcmVudCA9IHRoaXMubWVkaWEucGFyZW50Tm9kZVxuICAgIHRoaXMuaG9sZGVyID0gdGhpcy5fZGV0ZXJtaW5lSG9sZGVyKHRoaXMubWVkaWEpXG4gICAgdGhpcy5wbGF5ZXJUeXBlID0gdHlwZVxuICAgIHRoaXMuX2lzVk9EID0gZmFsc2VcbiAgICB0aGlzLl9jb250cm9scyA9IHVuZGVmaW5lZFxuICAgIHRoaXMuX3BsYXliYWNrTm90aWZpY2F0aW9uQ2VudGVyID0gdGhpcy5tZWRpYVxuICAgIGVudmlyb25tZW50Lm9uRnVsbFNjcmVlblN0YXRlQ2hhbmdlKHRoaXMuX2hhbmRsZUZ1bGxTY3JlZW5DaGFuZ2UuYmluZCh0aGlzKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBFc3RhYmxpc2hlZCBET00gRWxlbWVudCBvcmRlciBmb3IgcGxheWJhY2suXG4gICAqXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gbWVkaWFcbiAgICogICAgICAgIFRoZSB0YXJnZXQgbWVkaWEgZWxlbWVudDogZS5nLiwgYHZpZGVvYCBvciBgYXVkaW9gLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX2RldGVybWluZUhvbGRlciAobWVkaWEpIHtcbiAgICBpZiAobWVkaWEucGFyZW50Tm9kZS5jbGFzc0xpc3QuY29udGFpbnMoJ3JlZDVwcm8tbWVkaWEtY29udGFpbmVyJykpIHtcbiAgICAgIHJldHVybiBtZWRpYS5wYXJlbnROb2RlXG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgY29uc3QgcGFyZW50ID0gbWVkaWEucGFyZW50Tm9kZVxuICAgICAgY29uc3QgZGl2ID0gZW52aXJvbm1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JylcbiAgICAgIGRpdi5jbGFzc0xpc3QuYWRkKCdyZWQ1cHJvLW1lZGlhLWNvbnRhaW5lcicpXG4gICAgICBwYXJlbnQuaW5zZXJ0QmVmb3JlKGRpdiwgbWVkaWEpXG4gICAgICBwYXJlbnQucmVtb3ZlQ2hpbGQobWVkaWEpXG4gICAgICBkaXYuYXBwZW5kQ2hpbGQobWVkaWEpXG4gICAgICByZXR1cm4gZGl2XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEVzdGFibGlzaGVkIERPTSBFbGVtZW50IG9yZGVyIGZvciBwbGF5YmFjay5cbiAgICpcbiAgICogQHBhcmFtIHtFbGVtZW50fSBtZWRpYVxuICAgKiAgICAgICAgVGhlIHRhcmdldCBtZWRpYSBlbGVtZW50OiBlLmcuLCBgdmlkZW9gIG9yIGBhdWRpb2AuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfY2xlYW5VcCAoKSB7XG4gICAgLy8gUmV0dXJuIHRvIHByaW9yIERPTSBtYW5pcHVsYXRpb24uXG4gICAgbGV0IGVsID0gdGhpcy5tZWRpYVxuICAgIGxldCBlbFBhcmVudCA9IGVsLnBhcmVudE5vZGVcbiAgICBsZXQgbWVkaWFIb2xkZXIgPSB0aGlzLmhvbGRlclxuICAgIGlmIChlbFBhcmVudCkge1xuICAgICAgZWxQYXJlbnQucmVtb3ZlQ2hpbGQoZWwpXG4gICAgICAvLyBUaGUgb2JqZWN0IHBhcmVudCBjb3VsZCBiZSBhIHdyYXBwZXIgY2hpbGQgaW4gdGhlIG9yaWdpbmFsIHBhcmVudCBlbGVtZW50LlxuICAgICAgaWYgKGVsUGFyZW50ICE9PSB0aGlzLnBhcmVudCkge1xuICAgICAgICBlbFBhcmVudC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGVsUGFyZW50KVxuICAgICAgICBtZWRpYUhvbGRlciA9IHRoaXMucGFyZW50XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGVsLnJlbW92ZSgpXG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHdhcm4oTkFNRSwgYElzc3VlIGluIERPTSBjbGVhbnVwIG9mIGZsYXNoIG9iamVjdCBlbWJlZDogJHtlLm1lc3NhZ2V9YClcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5tZWRpYSA9IHRoaXMuY2xvbmUuY2xvbmVOb2RlKHRydWUpXG4gICAgbWVkaWFIb2xkZXIuYXBwZW5kQ2hpbGQodGhpcy5tZWRpYSlcbiAgICBpZiAodGhpcy5fY29udHJvbHMpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xzLmRldGFjaCgpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFzc2lnbnMgYW5kIGhhbmRsZXJzIGV2ZW50IG5vdGlmaWNpYXRpb25zIGNvbWluZyBmcm9tIHRoZSBtZWRpYSBub3RpZmllciAoZS5nLiwgYHZpZGVvYCBvciBgYXVkaW9gIGVsZW1lbnQpLlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gbm90aWZpZXJcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9hZGRQbGF5YmFja0hhbmRsZXJzIChub3RpZmllcikge1xuICAgIGNvbnN0IGNvbnRyb2xzID0gdGhpcy5nZXRDb250cm9scygpXG4gICAgY29uc3QgaGFzQ29udHJvbHMgPSB0eXBlb2YgY29udHJvbHMgIT09ICd1bmRlZmluZWQnXG5cbiAgICBub3RpZmllci5vbmNhbnBsYXkgPSAoKSA9PiB7XG4gICAgICBkZWJ1ZyhOQU1FLCAnW3ZpZGVvZWxlbWVudDpldmVudF0gY2FucGxheScpXG4gICAgICBpZiAoY29udHJvbHMpIHtcbiAgICAgICAgY29udHJvbHMuZW5hYmxlKHRydWUpXG4gICAgICB9XG4gICAgICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChTdWJzY3JpYmVyRXZlbnRUeXBlcy5QTEFZQkFDS19TVEFURV9DSEFOR0UsIHVuZGVmaW5lZCwge1xuICAgICAgICBjb2RlOiBQbGF5YmFja1N0YXRlLkFWQUlMQUJMRSxcbiAgICAgICAgc3RhdGU6IFBsYXliYWNrU3RhdGVSZWFkYWJsZVtQbGF5YmFja1N0YXRlLkFWQUlMQUJMRV1cbiAgICAgIH0pKVxuICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoU3Vic2NyaWJlckV2ZW50VHlwZXMuVk9MVU1FX0NIQU5HRSwgdW5kZWZpbmVkLCB7XG4gICAgICAgIHZvbHVtZTogbm90aWZpZXIudm9sdW1lXG4gICAgICB9KSlcbiAgICB9XG4gICAgbm90aWZpZXIub25kdXJhdGlvbmNoYW5nZSA9IChldmVudCkgPT4geyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gICAgICBkZWJ1ZyhOQU1FLCAnW3ZpZGVvZWxlbWVudDpldmVudF0gZHVyYXRpb25jaGFuZ2UnKVxuICAgICAgaWYgKCFpc05hTihub3RpZmllci5kdXJhdGlvbikgJiYgTnVtYmVyLmlzRmluaXRlKG5vdGlmaWVyLmR1cmF0aW9uKSkge1xuICAgICAgICB0aGlzLmlzVk9EID0gdHJ1ZVxuICAgICAgfVxuICAgICAgaWYgKGhhc0NvbnRyb2xzKSB7XG4gICAgICAgIGNvbnRyb2xzLnNldFBsYXliYWNrRHVyYXRpb24obm90aWZpZXIuZHVyYXRpb24pXG4gICAgICB9XG4gICAgfVxuICAgIG5vdGlmaWVyLm9uZW5kZWQgPSAoKSA9PiB7XG4gICAgICBkZWJ1ZyhOQU1FLCAnW3ZpZGVvZWxlbWVudDpldmVudF0gZW5kZWQnKVxuICAgICAgaWYgKGhhc0NvbnRyb2xzKSB7XG4gICAgICAgIGNvbnRyb2xzLnNldFN0YXRlKFBsYXliYWNrU3RhdGUuSURMRSlcbiAgICAgIH1cbiAgICAgIHRoaXMudHJpZ2dlcihuZXcgU3Vic2NyaWJlckV2ZW50KFN1YnNjcmliZXJFdmVudFR5cGVzLlBMQVlCQUNLX1NUQVRFX0NIQU5HRSwgdW5kZWZpbmVkLCB7XG4gICAgICAgIGNvZGU6IFBsYXliYWNrU3RhdGUuSURMRSxcbiAgICAgICAgc3RhdGU6IFBsYXliYWNrU3RhdGVSZWFkYWJsZVtQbGF5YmFja1N0YXRlLklETEVdXG4gICAgICB9KSlcbiAgICB9XG4gICAgbm90aWZpZXIub250aW1ldXBkYXRlID0gKGV2ZW50KSA9PiB7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW51c2VkLXZhcnNcbiAgICAgIGlmIChoYXNDb250cm9scykge1xuICAgICAgICBjb250cm9scy5zZXRTZWVrVGltZShub3RpZmllci5jdXJyZW50VGltZSwgc2VsZi5pc1ZPRCA/IG5vdGlmaWVyLmR1cmF0aW9uIDogdW5kZWZpbmVkKVxuICAgICAgfVxuICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoU3Vic2NyaWJlckV2ZW50VHlwZXMuUExBWUJBQ0tfVElNRV9VUERBVEUsIHVuZGVmaW5lZCwge1xuICAgICAgICB0aW1lOiBub3RpZmllci5jdXJyZW50VGltZSxcbiAgICAgICAgZHVyYXRpb246IG5vdGlmaWVyLmR1cmF0aW9uXG4gICAgICB9KSlcbiAgICB9XG4gICAgbm90aWZpZXIub25zZWVrZWQgPSAoZXZlbnQpID0+IHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuLy8gICAgICBkZWJ1ZyhOQU1FLCAnU2Vla2VkLicpXG4gICAgfVxuICAgIG5vdGlmaWVyLm9uc2Vla2luZyA9IChldmVudCkgPT4geyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4vLyAgICAgIGRlYnVnKE5BTUUsICdTZWVraW5nLicpXG4gICAgfVxuICAgIG5vdGlmaWVyLm9ucGxheSA9ICgpID0+IHtcbiAgICAgIGRlYnVnKE5BTUUsICdbdmlkZW9lbGVtZW50OmV2ZW50XSBwbGF5JylcbiAgICAgIGlmIChoYXNDb250cm9scykge1xuICAgICAgICBjb250cm9scy5zZXRTdGF0ZShQbGF5YmFja1N0YXRlLlBMQVlJTkcpXG4gICAgICB9XG4gICAgICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChTdWJzY3JpYmVyRXZlbnRUeXBlcy5QTEFZQkFDS19TVEFURV9DSEFOR0UsIHVuZGVmaW5lZCwge1xuICAgICAgICBjb2RlOiBQbGF5YmFja1N0YXRlLlBMQVlJTkcsXG4gICAgICAgIHN0YXRlOiBQbGF5YmFja1N0YXRlUmVhZGFibGVbUGxheWJhY2tTdGF0ZS5QTEFZSU5HXVxuICAgICAgfSkpXG4gICAgfVxuICAgIG5vdGlmaWVyLm9ucGF1c2UgPSAoKSA9PiB7XG4gICAgICBkZWJ1ZyhOQU1FLCAnW3ZpZGVvZWxlbWVudDpldmVudF0gcGF1c2UnKVxuICAgICAgaWYgKGhhc0NvbnRyb2xzKSB7XG4gICAgICAgIGNvbnRyb2xzLnNldFN0YXRlKFBsYXliYWNrU3RhdGUuUEFVU0VEKVxuICAgICAgfVxuICAgICAgdGhpcy50cmlnZ2VyKG5ldyBTdWJzY3JpYmVyRXZlbnQoU3Vic2NyaWJlckV2ZW50VHlwZXMuUExBWUJBQ0tfU1RBVEVfQ0hBTkdFLCB1bmRlZmluZWQsIHtcbiAgICAgICAgY29kZTogUGxheWJhY2tTdGF0ZS5QQVVTRUQsXG4gICAgICAgIHN0YXRlOiBQbGF5YmFja1N0YXRlUmVhZGFibGVbUGxheWJhY2tTdGF0ZS5QQVVTRURdXG4gICAgICB9KSlcbiAgICB9XG4gICAgbm90aWZpZXIub252b2x1bWVjaGFuZ2UgPSAoZXZlbnQpID0+IHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuICAgICAgaWYgKGhhc0NvbnRyb2xzICYmIGNvbnRyb2xzLmdldFZvbHVtZSgpICE9PSB0aGlzLm1lZGlhLnZvbHVtZSkge1xuICAgICAgICBjb250cm9scy5zZXRWb2x1bWUodGhpcy5tZWRpYS52b2x1bWUpXG4gICAgICB9XG4gICAgICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChTdWJzY3JpYmVyRXZlbnRUeXBlcy5WT0xVTUVfQ0hBTkdFLCB1bmRlZmluZWQsIHtcbiAgICAgICAgdm9sdW1lOiBub3RpZmllci5tdXRlZCA/IDAgOiBub3RpZmllci52b2x1bWVcbiAgICAgIH0pKVxuICAgIH1cbiAgICAvLyBmb3IgZGVidWdnaW5nIHB1cnBvc2VzLlxuICAgIG5vdGlmaWVyLm9uZW5jcnlwdGVkID0gKCkgPT4geyBkZWJ1ZyhOQU1FLCAnW3ZpZGVvZWxlbWVudDpldmVudF0gZW5jcnlwdGVkJykgfVxuICAgIG5vdGlmaWVyLm9uZW1wdGllZCA9ICgpID0+IHsgZGVidWcoTkFNRSwgJ1t2aWRlb2VsZW1lbnQ6ZXZlbnRdIGVtcHRpZWQnKSB9XG4gICAgbm90aWZpZXIub25sb2FkZWRkYXRhID0gKCkgPT4geyBkZWJ1ZyhOQU1FLCAnW3ZpZGVvZWxlbWVudDpldmVudF0gbG9hZGVkZGF0YScpIH1cbiAgICBub3RpZmllci5vbmxvYWRlZG1ldGFkYXRhID0gKCkgPT4geyBkZWJ1ZyhOQU1FLCAnW3ZpZGVvZWxlbWVudDpldmVudF0gbG9hZGVkbWV0YWRhdGEnKSB9XG4gICAgbm90aWZpZXIub25sb2Fkc3RhcnQgPSAoKSA9PiB7IGRlYnVnKE5BTUUsICdbdmlkZW9lbGVtZW50OmV2ZW50XSBsb2FkZWRzdGFydCcpIH1cbiAgICBub3RpZmllci5vbnN0YWxsZWQgPSAoKSA9PiB7IGRlYnVnKE5BTUUsICdbdmlkZW9lbGVtZW50OmV2ZW50XSBzdGFsbGVkJykgfVxuICAgIG5vdGlmaWVyLm9uc3VzcGVuZCA9ICgpID0+IHsgZGVidWcoTkFNRSwgJ1t2aWRlb2VsZW1lbnQ6ZXZlbnRdIHN1c3BlbmQnKSB9XG4gICAgbm90aWZpZXIub253YWl0aW5nID0gKCkgPT4geyBkZWJ1ZyhOQU1FLCAnW3ZpZGVvZWxlbWVudDpldmVudF0gd2FpdGluZycpIH1cbiAgICAvLyAgICBub3RpZmllci5vbnByb2dyZXNzID0gKCkgPT4geyBkZWJ1ZyhOQU1FLCAnW3ZpZGVvZWxlbWVudDpldmVudF0gcHJvZ3Jlc3MuIFBsYXllZDogJyArIG5vdGlmaWVyLnBsYXllZC5sZW5ndGggKyAnLCBCdWZmZXJlZDogJyArIG5vdGlmaWVyLmJ1ZmZlcmVkLmxlbmd0aCArICcuJykgfVxuICB9XG5cbiAgLyoqXG4gICAqIEV2ZW50IGhhbmRsZXIgZm9yIGNoYW5nZSBpbiBmdWxsc2NyZWVuIHN0YXRlLlxuICAgKlxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IGlzRnVsbFNjcmVlblxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX2hhbmRsZUZ1bGxTY3JlZW5DaGFuZ2UgKGlzRnVsbFNjcmVlbikge1xuICAgIGlmIChpc0Z1bGxTY3JlZW4pIHtcbiAgICAgIHRoaXMuaG9sZGVyLmNsYXNzTGlzdC5hZGQoJ3JlZDVwcm8tbWVkaWEtY29udGFpbmVyLWZ1bGwtc2NyZWVuJylcbiAgICAgIHRoaXMubWVkaWEuY2xhc3NMaXN0LmFkZCgncmVkNXByby1tZWRpYS1jb250YWluZXItZnVsbC1zY3JlZW4nKVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHRoaXMuaG9sZGVyLmNsYXNzTGlzdC5yZW1vdmUoJ3JlZDVwcm8tbWVkaWEtY29udGFpbmVyLWZ1bGwtc2NyZWVuJylcbiAgICAgIHRoaXMubWVkaWEuY2xhc3NMaXN0LnJlbW92ZSgncmVkNXByby1tZWRpYS1jb250YWluZXItZnVsbC1zY3JlZW4nKVxuICAgIH1cbiAgICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChTdWJzY3JpYmVyRXZlbnRUeXBlcy5GVUxMX1NDUkVFTl9TVEFURV9DSEFOR0UsIHVuZGVmaW5lZCwgaXNGdWxsU2NyZWVuKSlcbiB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gc2V0dXAgdGhlIHByZXNlbnRhdGlvbiBvZiBhIHBsYXliYWNrIHN0cmVhbSB1c2luZyBXZWJSVEMuXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqICAgICAgICBUaGUgaW5pdGlhbGl6YXRpb24gY29uZmlndXJhdGlvbiBtYXAuXG4gICAqXG4gICAqIEByZXR1cm5zIHtQcm9taXNlfVxuICAgKi9cbiAgYWRkU291cmNlIChvcHRpb25zKSB7XG4gICAgZGVidWcoTkFNRSwgJ1thZGRzb3VyY2VdJylcbiAgICB0aGlzLmhvbGRlciA9IHRoaXMuX2RldGVybWluZUhvbGRlcih0aGlzLm1lZGlhKVxuICAgIGNvbnN0IGRlZmVycmVkID0gbmV3IERlZmVycmVkUHJvbWlzZSgpXG4gICAgY29uc3QgaGFzRGVmaW5lZENvbnRyb2xzID0gb3B0aW9ucy5jb250cm9sc1xuICAgIGNvbnN0IGlzTXV0ZWQgPSBlbnZpcm9ubWVudC5oYXNBdHRyaWJ1dGVEZWZpbmVkKHRoaXMubWVkaWEsICdtdXRlZCcpXG4gICAgY29uc3QgdXNlUGxheWJhY2tDb250cm9scyA9IGVudmlyb25tZW50Lmhhc0F0dHJpYnV0ZURlZmluZWQodGhpcy5tZWRpYSwgJ2NvbnRyb2xzJykgJiYgZW52aXJvbm1lbnQuaGFzQ2xhc3NEZWZpbmVkKHRoaXMubWVkaWEsICdyZWQ1cHJvLW1lZGlhJylcbiAgICBpZiAoaGFzRGVmaW5lZENvbnRyb2xzIHx8IHVzZVBsYXliYWNrQ29udHJvbHMpIHtcbiAgICAgIGlmIChoYXNEZWZpbmVkQ29udHJvbHMpIHtcbiAgICAgICAgdGhpcy5fY29udHJvbHMgPSBvcHRpb25zLmNvbnRyb2xzXG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgdGhpcy5fY29udHJvbHMgPSBuZXcgUGxheWJhY2tDb250cm9sc0ltcGwodGhpcywgdGhpcy5ob2xkZXIpXG4gICAgICB9XG4gICAgICB0aGlzLm1lZGlhLmNvbnRyb2xzID0gZmFsc2VcbiAgICAgIHRoaXMuX2NvbnRyb2xzLnNldEFzVk9EKHRoaXMuaXNWT0QpXG4gICAgICB0aGlzLl9jb250cm9scy5zZXRNdXRlZFN0YXRlKGlzTXV0ZWQpXG4gICAgfVxuICAgIHRoaXMuX2FkZFBsYXliYWNrSGFuZGxlcnModGhpcy5fcGxheWJhY2tOb3RpZmljYXRpb25DZW50ZXIpXG4gICAgZGVmZXJyZWQucmVzb2x2ZSgpXG4gICAgcmV0dXJuIGRlZmVycmVkLnByb21pc2VcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIGNvbm5lY3QgdG8gc3RyZWFtLlxuICAgKi9cbiAgY29ubmVjdCAoKSB7XG4gICAgZGVidWcoTkFNRSwgJ1tjb25uZWN0XScpXG4gIH1cblxuICBwbGF5ICgpIHtcbiAgICBkZWJ1ZyhOQU1FLCAnW3ZpZGVvZWxlbWVudDphY3Rpb25dIHBsYXknKVxuICAgIHRyeSB7XG4gICAgICBsZXQgbWF5YmVQcm9taXNlID0gdGhpcy5tZWRpYS5wbGF5KClcbiAgICAgIGlmIChtYXliZVByb21pc2UpIHtcbiAgICAgICAgbWF5YmVQcm9taXNlLnRoZW4oKCkgPT4gZGVidWcoTkFNRSwgJ1t2aWRlb2VsZW1lbnQ6YWN0aW9uXSBwbGF5IChTVEFSVCknKSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKChlcnIpID0+IGVycm9yKE5BTUUsICdbdmlkZW9lbGVtZW50OmFjdGlvbl0gcGxheSAoRkFVTFQpICcgKyAoZXJyLm1lc3NhZ2UgPyBlcnIubWVzc2FnZSA6IGVycikpKVxuICAgICAgfVxuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgZXJyb3IoTkFNRSwgJ1t2aWRlb2VsZW1lbnQ6YWN0aW9uXSBwbGF5IChGQVVMVCkgLSAnICsgZS5tZXNzYWdlKTtcbiAgICB9XG4gIH1cblxuICBwYXVzZSAoKSB7XG4gICAgZGVidWcoTkFNRSwgJ1t2aWRlb2VsZW1lbnQ6YWN0aW9uXSBwYXVzZScpXG4gICAgdHJ5IHtcbiAgICAgIHRoaXMubWVkaWEucGF1c2UoKVxuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgd2FybihOQU1FLCAnW3ZpZGVvZWxlbWVudDphY3Rpb25dIHBhdXNlIChDQVRDSDo6RkFVTFQpIC0gJyArIGUubWVzc2FnZSk7XG4gICAgfVxuICB9XG5cbiAgcmVzdW1lICgpIHtcbiAgICBkZWJ1ZyhOQU1FLCAnW3ZpZGVvZWxlbWVudDphY3Rpb25dIHJlc3VtZScpXG4gICAgdHJ5IHtcbiAgICAgIGxldCBtYXliZVByb21pc2UgPSB0aGlzLm1lZGlhLnBsYXkoKVxuICAgICAgaWYgKG1heWJlUHJvbWlzZSkge1xuICAgICAgICBtYXliZVByb21pc2UudGhlbigoKSA9PiBkZWJ1ZyhOQU1FLCAnW3ZpZGVvZWxlbWVudDphY3Rpb25dIHBsYXkgKFNUQVJUKScpKVxuICAgICAgICAgICAgICAgICAgICAuY2F0Y2goKGVycikgPT4gd2FybihOQU1FLCAnW3ZpZGVvZWxlbWVudDphY3Rpb25dIHBsYXkgKENBVENIOjpGQVVMVCkgJyArIChlcnIubWVzc2FnZSA/IGVyci5tZXNzYWdlIDogZXJyKSkpXG4gICAgICB9XG4gICAgfVxuICAgIGNhdGNoIChlKSB7XG4gICAgICB3YXJuKE5BTUUsICdbdmlkZW9lbGVtZW50OmFjdGlvbl0gcmVzdW1lIChDQVRDSDo6RkFVTFQpIC0gJyArIGUubWVzc2FnZSk7XG4gICAgfVxuICB9XG5cbiAgc3RvcCAoKSB7XG4gICAgZGVidWcoTkFNRSwgJ1t2aWRlb2VsZW1lbnQ6YWN0aW9uXSBzdG9wJylcbiAgICB0cnkge1xuICAgICAgdGhpcy5tZWRpYS5zdG9wKClcbiAgICB9XG4gICAgY2F0Y2ggKGUpIHtcbiAgICAgIC8vIG9rLlxuICAgIH1cbiAgfVxuXG4gIG11dGUgKCkge1xuICAgIHRoaXMubWVkaWEubXV0ZWQgPSB0cnVlXG4gICAgY29uc3QgY29udHJvbHMgPSB0aGlzLmdldENvbnRyb2xzKClcbiAgICBpZiAoY29udHJvbHMpIHtcbiAgICAgIGNvbnRyb2xzLnNldE11dGVkU3RhdGUodHJ1ZSlcbiAgICB9XG4gIH1cblxuICB1bm11dGUgKCkge1xuICAgIHRoaXMubWVkaWEubXV0ZWQgPSBmYWxzZVxuICAgIGNvbnN0IGNvbnRyb2xzID0gdGhpcy5nZXRDb250cm9scygpXG4gICAgaWYgKGNvbnRyb2xzKSB7XG4gICAgICBjb250cm9scy5zZXRNdXRlZFN0YXRlKGZhbHNlKVxuICAgIH1cbiAgfVxuXG4gIHNldFZvbHVtZSAodmFsdWUpIHtcbiAgICB0aGlzLnVubXV0ZSgpXG4gICAgdGhpcy5tZWRpYS52b2x1bWUgPSB2YWx1ZVxuICB9XG5cbiAgc2Vla1RvIChwZXJjZW50YWdlLCBkdXJhdGlvbiA9IHVuZGVmaW5lZCkge1xuICAgIHRoaXMubWVkaWEuY3VycmVudFRpbWUgPSBkdXJhdGlvbiA/IHBlcmNlbnRhZ2UgKiBkdXJhdGlvbiA6IHBlcmNlbnRhZ2VcbiAgfVxuXG4gIHRvZ2dsZUZ1bGxTY3JlZW4gKCkge1xuICAgIHRyeSB7XG4gICAgICBlbnZpcm9ubWVudC50b2dnbGVGdWxsU2NyZWVuKHRoaXMuaG9sZGVyKVxuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgdGhyb3cgZTtcbiAgICAgIC8vIG5hZGEuXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE5vdGlmaWNhdGlvbiBvZiBjdXJyZW50IHN0cmVhbSBiZWluZyBpbiBhbiB1bnB1Ymxpc2hlZCBzdGF0ZS5cbiAgICogVGhlIHN0cmVhbSBlbnRlcnMgYW4gdW5wdWJsaXNoZWQgc3RhdGUgd2hlbiB0aGUgYnJvYWRjYXN0ZXIgc3RvcCB0aGUgc3RyZWFtIGFuZCB0aGUgc3Vic2NyaWJlciBpcyBzdGlsbCBjb25uZWN0ZWQuXG4gICAqL1xuICB1bnB1Ymxpc2ggKCkge1xuICAgIHRyeSB7XG4gICAgICB0aGlzLnN0b3AoKVxuICAgICAgdGhpcy5tZWRpYS5vbmVuZGVkLmNhbGwodGhpcy5tZWRpYSlcbiAgICB9XG4gICAgY2F0Y2ggKGUpIHtcbiAgICAgIC8vIG5hZGEuXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gZGlzY29ubmVjdCBwbGF5YmFjay5cbiAgICovXG4gIGRpc2Nvbm5lY3QgKCkge1xuICAgIHRoaXMuX2NsZWFuVXAoKVxuICB9XG5cbiAgLyoqXG4gICAqIFJlc3BvbmRlciB0byBjaGFuZ2UgaW4gb3JpZW50YXRpb24gcmVjZWl2ZWQgdGhyb3VnaCBtZXRhZGF0YS5cbiAgICpcbiAgICogQHBhcmFtIHtOdW1iZXJ9IG9yaWVudGF0aW9uXG4gICAqICAgICAgICBUaGUgb3JpZW50YXRpb24gdmFsdWUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBoYW5kbGVPcmllbnRhdGlvbkNoYW5nZSAob3JpZW50YXRpb24pIHtcbiAgICBpZiAodGhpcy5fY29udHJvbHMgJiYgKG9yaWVudGF0aW9uICUgMTgwICE9PSAwKSkge1xuICAgICAgdGhpcy5ob2xkZXIuY2xhc3NMaXN0LmFkZCgncmVkNXByby1tZWRpYS1iYWNrZ3JvdW5kJylcbiAgICAgIHRoaXMubWVkaWEuY2xhc3NMaXN0LnJlbW92ZSgncmVkNXByby1tZWRpYS1iYWNrZ3JvdW5kJylcbiAgICB9XG4gIH1cblxuICAvKlxuICAgKiB8fCBTSEFSRUQgT0JKRUNUIElOVEVHUkFUSU9OIE5PVCBBVkFJTEFCTEUgRk9SIEhMUyBQTEFZQkFDSyB8fFxuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVudXNlZC12YXJzXG4gIGFkZFNoYXJlZE9iamVjdFJlc3BvbnNlSGFuZGxlciAoaGFuZGxlcikge31cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW51c2VkLXZhcnNcbiAgcmVtb3ZlU2hhcmVkT2JqZWN0UmVzcG9uc2VIYW5kbGVyIChoYW5kbGVyKSB7fVxuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bnVzZWQtdmFyc1xuICBzZW5kVG9TaGFyZWRPYmplY3QgKG5hbWUsIGNhbGxOYW1lLCBtZXNzYWdlKSB7fVxuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bnVzZWQtdmFyc1xuICBzZW5kUHJvcGVydHlUb1NoYXJlZE9iamVjdCAobmFtZSwga2V5LCB2YWx1ZSkge31cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW51c2VkLXZhcnNcbiAgZ2V0UmVtb3RlU2hhcmVkT2JqZWN0IChzaGFyZWRPYmplY3ROYW1lKSB7fVxuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bnVzZWQtdmFyc1xuICBjb25uZWN0VG9TaGFyZWRPYmplY3QgKHNoYXJlZE9iamVjdE5hbWUpIHt9XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVudXNlZC12YXJzXG4gIGNsb3NlU2hhcmVkT2JqZWN0IChzaGFyZWRPYmplY3ROYW1lKSB7fVxuXG5cbiAgLyoqXG4gICAqIFJldHVybnMgcGxheWJhY2sgY29udHJvbHMgaWYgYXZhaWxhYmxlLlxuICAgKlxuICAgKiBAcmV0dXJucyB7UGxheWJhY2tDb250cm9sc31cbiAgICovXG4gIGdldENvbnRyb2xzICgpIHtcbiAgICByZXR1cm4gdGhpcy5fY29udHJvbHNcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBzdWJzY3JpYmVyIHR5cGUgYXNzb2NpYXRlZCB3aXRoIHRoaXMgY29udHJvbGxlci5cbiAgICpcbiAgICogQHJldHVybnMge1N0cmluZ31cbiAgICovXG4gIGdldFR5cGUgKCkge1xuICAgIHJldHVybiB0aGlzLnBsYXllclR5cGVcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGZsYWcgb2YgdmlkZW8gYmVpbmcgcmVjb2duaXplZCBhcyBWT0QgKFZpZGVvIE9uIERlbWFuZCkuXG4gICAqXG4gICAqIEByZXR1cm5zIHtCb29sZWFufVxuICAgKi9cbiAgZ2V0IGlzVk9EICgpIHtcbiAgICByZXR1cm4gdGhpcy5faXNWT0RcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGZsYWcgb2YgdmlkZW8gYmVpbmcgY29uc2lkZXJlZCBhcyBWT0QgKFZpZGVvIE9uIERlbWFuZCkuXG4gICAqXG4gICAqIEBwYXJhbSB7Qm9vbGVhbn0gdmFsdWVcbiAgICovXG4gIHNldCBpc1ZPRCAodmFsdWUpIHtcbiAgICB0aGlzLl9pc1ZPRCA9IHZhbHVlXG4gICAgaWYgKHRoaXMuX2NvbnRyb2xzKSB7XG4gICAgICB0aGlzLl9jb250cm9scy5zZXRBc1ZPRCh2YWx1ZSlcbiAgICB9XG4gIH1cblxufVxuXG5leHBvcnQgZGVmYXVsdCBSVENTb3VyY2VIYW5kbGVyXG5cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9qcy9zdWJzY3JpYmVyL3JlZDVwcm8tc291cmNlLWhhbmRsZXItcnRjLmpzIiwiJ3VzZSBzdHJpY3QnXG5cbmltcG9ydCAqIGFzIGVtYmVkIGZyb20gJy4uL2Vudi9lbWJlZCdcbmltcG9ydCBlbnZpcm9ubWVudCBmcm9tICcuLi9lbnYvYnJvd3NlcidcbmltcG9ydCBSVE1QU2hhcmVkT2JqZWN0SGFuZGxlciBmcm9tICcuLi9oZWxwZXIvc2hhcmVkb2JqZWN0LWhlbHBlci1ydG1wJ1xuaW1wb3J0IHsgUGxheWJhY2tDb250cm9sbGVyLCBQbGF5YmFja0NvbnRyb2xzSW1wbCB9IGZyb20gJy4vY29udHJvbHMnXG5pbXBvcnQgeyBQbGF5YmFja1N0YXRlLCBQbGF5YmFja1N0YXRlUmVhZGFibGUgfSBmcm9tICcuL2NvbnRyb2xzL3N0YXRlJ1xuaW1wb3J0IHsgU3Vic2NyaWJlckV2ZW50LCBTdWJzY3JpYmVyRXZlbnRUeXBlcyB9IGZyb20gJy4uL2V2ZW50J1xuaW1wb3J0IHsgRGVmZXJyZWRQcm9taXNlIH0gZnJvbSAnLi4vdXRpbC9wcm9taXNlJ1xuaW1wb3J0IHsgZGVidWcsIHdhcm4gfSBmcm9tICcuLi9sb2cnXG5cbmNvbnN0IE5BTUUgPSAnUlRNUFNvdXJjZUhhbmRsZXInXG5cbi8qKlxuICogU2ltcGxlIHV0aWwgdG8gY29udmVydCB2YWx1ZSB0byBJbnRlZ2VyLlxuICogQHByaXZhdGVcbiAqL1xuY29uc3QgdG9JbnQgPSAodmFsdWUpID0+IHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gcGFyc2VJbnQodmFsdWUsIDEwKVxuICB9XG4gIGVsc2Uge1xuICAgIHJldHVybiBNYXRoLnJvdW5kKHZhbHVlKVxuICB9XG59XG5cbi8qKlxuICogUXVpY2sgdGVzdCBpZiBzdHJlYW1OYW1lIGhhcyBhbiBleHRlbnNpb24gd2hpY2ggaW5mZXJzIFZPRC5cbiAqIEBwYXJhbSB7U3RyaW5nfSBzdHJlYW1OYW1lXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICogQHByaXZhdGVcbiAqL1xuY29uc3QgaXNWT0RTdHJlYW1OYW1lID0gKHN0cmVhbU5hbWUpID0+IHtcbiAgcmV0dXJuIC9eLipcXC4oZmx2fG1wNHxtcDMpLy50ZXN0KHN0cmVhbU5hbWUpXG59XG5cbi8qKlxuICogU291cmNlIEhhbmRsZXIgZm9yIEZsYXNoLWJhc2VkIFN1YnNjcmliZXJzLCB3aGljaCBzZXJ2ZXMgYXMgYSBQcmVzZW50YXRpb24gQ29udHJvbGxlciBiZXR3ZWVuIHZpZXcgYW5kIHN1YnNjcmliZXIuXG4gKlxuICogQGV4dGVuZHMgRXZlbnRFbWl0dGVyXG4gKiBAZXh0ZW5kcyBTdWJzY3JpYmVyUGxheWJhY2tDb250cm9sbGVyXG4gKlxuICogQHByaXZhdGVcbiAqL1xuY2xhc3MgUlRNUFNvdXJjZUhhbmRsZXIgZXh0ZW5kcyBQbGF5YmFja0NvbnRyb2xsZXIge1xuXG4gIGNvbnN0cnVjdG9yIChub3RpZmljYXRpb25DZW50ZXIsIG1lZGlhLCB0eXBlLCBzb1Jlc3BvbmRlciA9IHVuZGVmaW5lZCkge1xuICAgIHN1cGVyKClcbiAgICB0aGlzLm1lZGlhID0gbWVkaWFcbiAgICB0aGlzLmNsb25lID0gdGhpcy5tZWRpYS5jbG9uZU5vZGUodHJ1ZSlcbiAgICB0aGlzLnBhcmVudCA9IHRoaXMubWVkaWEucGFyZW50Tm9kZVxuICAgIHRoaXMuaG9sZGVyID0gdGhpcy5fZGV0ZXJtaW5lSG9sZGVyKHRoaXMubWVkaWEpXG4gICAgdGhpcy5wbGF5ZXJUeXBlID0gdHlwZVxuICAgIHRoaXMuX3N3ZklkID0gdW5kZWZpbmVkXG4gICAgdGhpcy5fY29udHJvbHMgPSB1bmRlZmluZWRcbiAgICB0aGlzLl9zb1Jlc3BvbmRlciA9IHNvUmVzcG9uZGVyIHx8IG5ldyBSVE1QU2hhcmVkT2JqZWN0SGFuZGxlcigpXG4gICAgdGhpcy5fcGxheWJhY2tOb3RpZmljYXRpb25DZW50ZXIgPSBub3RpZmljYXRpb25DZW50ZXJcbiAgICBlbnZpcm9ubWVudC5vbkZ1bGxTY3JlZW5TdGF0ZUNoYW5nZSh0aGlzLl9oYW5kbGVGdWxsU2NyZWVuQ2hhbmdlLmJpbmQodGhpcykpXG4gIH1cblxuICAvKipcbiAgICogRXN0YWJsaXNoZWQgRE9NIEVsZW1lbnQgb3JkZXIgZm9yIHBsYXliYWNrLlxuICAgKlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IG1lZGlhXG4gICAqICAgICAgICBUaGUgdGFyZ2V0IG1lZGlhIGVsZW1lbnQ6IGUuZy4sIGB2aWRlb2Agb3IgYGF1ZGlvYC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9kZXRlcm1pbmVIb2xkZXIgKG1lZGlhKSB7XG4gICAgaWYgKG1lZGlhLnBhcmVudE5vZGUuY2xhc3NMaXN0LmNvbnRhaW5zKCdyZWQ1cHJvLW1lZGlhLWNvbnRhaW5lcicpKSB7XG4gICAgICByZXR1cm4gbWVkaWEucGFyZW50Tm9kZVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIGNvbnN0IHBhcmVudCA9IG1lZGlhLnBhcmVudE5vZGVcbiAgICAgIGNvbnN0IGRpdiA9IGVudmlyb25tZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpXG4gICAgICBkaXYuY2xhc3NMaXN0LmFkZCgncmVkNXByby1tZWRpYS1jb250YWluZXInKVxuICAgICAgcGFyZW50Lmluc2VydEJlZm9yZShkaXYsIG1lZGlhKVxuICAgICAgcGFyZW50LnJlbW92ZUNoaWxkKG1lZGlhKVxuICAgICAgZGl2LmFwcGVuZENoaWxkKG1lZGlhKVxuICAgICAgcmV0dXJuIGRpdlxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhbiB1cCBvZiBET00gRWxlbWVudCBvcmRlciB1cG9uIHN0b3Agb2YgcGxheWJhY2suXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfY2xlYW5VcCAoKSB7XG4gICAgLy8gUmV0dXJuIHRvIHByaW9yIERPTSBtYW5pcHVsYXRpb24uXG4gICAgbGV0IGVsID0gdGhpcy5nZXRFbWJlZGRlZFZpZXcoKVxuICAgIGxldCBlbFBhcmVudCA9IGVsLnBhcmVudE5vZGVcbiAgICBsZXQgbWVkaWFIb2xkZXIgPSB0aGlzLmhvbGRlclxuICAgIGlmIChlbFBhcmVudCkge1xuICAgICAgZWxQYXJlbnQucmVtb3ZlQ2hpbGQoZWwpXG4gICAgICAvLyBUaGUgb2JqZWN0IHBhcmVudCBjb3VsZCBiZSBhIHdyYXBwZXIgY2hpbGQgaW4gdGhlIG9yaWdpbmFsIHBhcmVudCBlbGVtZW50LlxuICAgICAgaWYgKGVsUGFyZW50ICE9PSB0aGlzLnBhcmVudCkge1xuICAgICAgICBlbFBhcmVudC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGVsUGFyZW50KVxuICAgICAgICBtZWRpYUhvbGRlciA9IHRoaXMucGFyZW50XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGVsLnJlbW92ZSgpXG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHdhcm4oTkFNRSwgYElzc3VlIGluIERPTSBjbGVhbnVwIG9mIGZsYXNoIG9iamVjdCBlbWJlZDogJHtlLm1lc3NhZ2V9YClcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5tZWRpYSA9IHRoaXMuY2xvbmUuY2xvbmVOb2RlKHRydWUpXG4gICAgbWVkaWFIb2xkZXIuYXBwZW5kQ2hpbGQodGhpcy5tZWRpYSlcbiAgICBpZiAodGhpcy5fY29udHJvbHMpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xzLmRldGFjaCgpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFzc2lnbnMgYW5kIGhhbmRsZXJzIGV2ZW50IG5vdGlmaWNpYXRpb25zIGNvbWluZyBmcm9tIHRoZSBtZWRpYSBub3RpZmllciAoZS5nLiwgYHZpZGVvYCBvciBgYXVkaW9gIGVsZW1lbnQpLlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gbm90aWZpZXJcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9hZGRQbGF5YmFja0hhbmRsZXJzIChub3RpZmllcikge1xuICAgIGNvbnN0IGNvbnRyb2xzID0gdGhpcy5nZXRDb250cm9scygpXG4gICAgaWYgKHR5cGVvZiBjb250cm9scyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICBub3RpZmllci5vbihTdWJzY3JpYmVyRXZlbnRUeXBlcy5TVUJTQ1JJQkVfU1RBUlQsICgpID0+IHtcbiAgICAgIGNvbnRyb2xzLnNldFN0YXRlKFBsYXliYWNrU3RhdGUuUExBWUlORylcbiAgICB9KVxuICAgIG5vdGlmaWVyLm9uKFN1YnNjcmliZXJFdmVudFR5cGVzLlNVQlNDUklCRV9TVE9QLCAoKSA9PiB7XG4gICAgICBjb250cm9scy5zZXRTdGF0ZShQbGF5YmFja1N0YXRlLklETEUpXG4gICAgfSlcbiAgICBub3RpZmllci5vbihTdWJzY3JpYmVyRXZlbnRUeXBlcy5QTEFZX1VOUFVCTElTSCwgKCkgPT4ge1xuICAgICAgY29udHJvbHMuc2V0U3RhdGUoUGxheWJhY2tTdGF0ZS5JRExFKVxuICAgIH0pXG4gICAgbm90aWZpZXIub24oU3Vic2NyaWJlckV2ZW50VHlwZXMuU1VCU0NSSUJFX01FVEFEQVRBLCAoZXZlbnQpID0+IHtcbiAgICAgIGlmIChldmVudC5kYXRhLmR1cmF0aW9uKSB7XG4gICAgICAgIGNvbnRyb2xzLnNldFBsYXliYWNrRHVyYXRpb24oZXZlbnQuZGF0YS5kdXJhdGlvbilcbiAgICAgIH1cbiAgICB9KVxuICAgIG5vdGlmaWVyLm9uKFN1YnNjcmliZXJFdmVudFR5cGVzLlZPTFVNRV9DSEFOR0UsIChldmVudCkgPT4ge1xuICAgICAgY29udHJvbHMuc2V0Vm9sdW1lKGV2ZW50LmRhdGEudm9sdW1lKVxuICAgIH0pXG4gICAgbm90aWZpZXIub24oU3Vic2NyaWJlckV2ZW50VHlwZXMuUExBWUJBQ0tfU1RBVEVfQ0hBTkdFLCAoZXZlbnQpID0+IHtcbiAgICAgIGlmIChldmVudC5kYXRhLmNvZGUgPT09IFBsYXliYWNrU3RhdGUuQVZBSUxBQkxFKSB7XG4gICAgICAgIGNvbnRyb2xzLmVuYWJsZSh0cnVlKVxuICAgICAgfVxuICAgICAgY29udHJvbHMuc2V0U3RhdGUoZXZlbnQuZGF0YS5jb2RlKVxuICAgIH0pXG4gICAgbm90aWZpZXIub24oU3Vic2NyaWJlckV2ZW50VHlwZXMuUExBWUJBQ0tfVElNRV9VUERBVEUsIChldmVudCkgPT4ge1xuICAgICAgY29udHJvbHMuc2V0U2Vla1RpbWUoZXZlbnQuZGF0YS50aW1lLCBldmVudC5kYXRhLmR1cmF0aW9uKVxuICAgIH0pXG4gICAgbm90aWZpZXIub24oU3Vic2NyaWJlckV2ZW50VHlwZXMuRlVMTF9TQ1JFRU5fU1RBVEVfQ0hBTkdFLCAoZXZlbnQpID0+IHtcbiAgICAgIGNvbnRyb2xzLm9uRnVsbFNjcmVlbkNoYW5nZShldmVudC5kYXRhKVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogRXZlbnQgaGFuZGxlciBmb3IgY2hhbmdlIGluIGZ1bGxzY3JlZW4gc3RhdGUuXG4gICAqXG4gICAqIEBwYXJhbSB7Qm9vbGVhbn0gaXNGdWxsU2NyZWVuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfaGFuZGxlRnVsbFNjcmVlbkNoYW5nZSAoaXNGdWxsU2NyZWVuKSB7XG4gICAgY29uc3Qgc3dmb2JqZWN0ID0gdGhpcy5nZXRFbWJlZGRlZFZpZXcoKVxuICAgIGlmIChpc0Z1bGxTY3JlZW4pIHtcbiAgICAgIHRoaXMuaG9sZGVyLmNsYXNzTGlzdC5hZGQoJ3JlZDVwcm8tbWVkaWEtY29udGFpbmVyLWZ1bGwtc2NyZWVuJylcbiAgICAgIHN3Zm9iamVjdC5jbGFzc0xpc3QuYWRkKCdyZWQ1cHJvLW1lZGlhLWNvbnRhaW5lci1mdWxsLXNjcmVlbicpXG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgdGhpcy5ob2xkZXIuY2xhc3NMaXN0LnJlbW92ZSgncmVkNXByby1tZWRpYS1jb250YWluZXItZnVsbC1zY3JlZW4nKVxuICAgICAgc3dmb2JqZWN0LmNsYXNzTGlzdC5yZW1vdmUoJ3JlZDVwcm8tbWVkaWEtY29udGFpbmVyLWZ1bGwtc2NyZWVuJylcbiAgICB9XG4gICB0aGlzLnRyaWdnZXIobmV3IFN1YnNjcmliZXJFdmVudChTdWJzY3JpYmVyRXZlbnRUeXBlcy5GVUxMX1NDUkVFTl9TVEFURV9DSEFOR0UsIHVuZGVmaW5lZCwgaXNGdWxsU2NyZWVuKSlcbiB9XG5cbiAgLyoqXG4gICAqIEVzdGFibGlzaGVzIGV2ZW50IGhhbmRsZXIgZm9yIHJlY29nbml6aW5nIGNvbXBsZXRlIG9uIGVtYmVkIGFuZCBpbml0aWFsaXphdGlvbiBvZiBGbGFzaC1iYXNlZCBzdWJzY3JpYmVyLlxuICAgKlxuICAgKiBAcGFyYW0ge1Byb21pc2V9IHByb21pc2VcbiAgICogICAgICAgIFRoZSB0YXJnZXQgYFByb21pc2VgIG9iamVjdCB0byByZXNvbHZlIG9yIHJlamVjdCB1cG9uIGNvbXBsZXRpb24uXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfc2V0VXBJbml0Q2FsbGJhY2sgKHByb21pc2UpIHtcbiAgICBjb25zdCBzZWxmID0gdGhpc1xuICAgIGVudmlyb25tZW50LmFkZFN1YnNjcmlwdGlvbkFzc2lnbm1lbnRIYW5kbGVyKHN1Y2Nlc3NJZCA9PiB7XG4gICAgICBkZWJ1ZyhOQU1FLCBgRW1iZWQgYW5kIGluaXQoKSBjb21wbGV0ZSBmb3Igc3Vic2NyaWJlciBzd2YuIHN1Y2Nlc3NJZCgke3N1Y2Nlc3NJZH0pLmApXG4gICAgICBwcm9taXNlLnJlc29sdmUoc3VjY2Vzc0lkKVxuICAgICAgc2VsZi5fdGVhckRvd25Jbml0Q2FsbGJhY2soKVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogVGVhcnMgZG93biBlc3RhYmxpc2hlZCBoYW5kbGVyIGZvciBjb21wbGV0aW9uIG9mIEZsYXNoIGVtYmVkIGFuZCBpbml0LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX3RlYXJEb3duSW5pdENhbGxiYWNrICgpIHt9XG5cbiAvKipcbiAgICogUmVxdWVzdCB0byBzZXR1cCB0aGUgcHJlc2VudGF0aW9uIG9mIGEgcGxheWJhY2sgc3RyZWFtIHVzaW5nIEhMUy5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IHVybFxuICAgKiAgICAgICAgVGhlIGVuZHBvaW50IFVSTCBmb3IgcGxheWJhY2suXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqICAgICAgICBUaGUgaW5pdGlhbGl6YXRpb24gY29uZmlndXJhdGlvbiBtYXAuXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzd2ZVcmxcbiAgICogICAgICAgIFRoZSBlbmRwb2ludCB1cmwgdG8gdGhlIFNXRiB0byBlbWJlZC4gRGVmYXVsdHMgdG8gcmVsYXRpdmUgbGluayB0byByZWQ1cHJvLXN1YnNjcmliZXIuc3dmIG9mIHRoZSBTREsgZGlzdHJpYnV0aW9uLlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWluRmxhc2hWZXJzaW9uXG4gICAqICAgICAgICBUaGUgbWluaW11bSBGbGFzaCB2ZXJzaW9uIGZvciBzdXBwb3J0IG9mIHBsYXliYWNrLiBEZWZhdWx0OiBgMTAuMC4wYC5cbiAgICpcbiAgICogQHJldHVybnMge1Byb21pc2V9XG4gICAqL1xuICBhZGRTb3VyY2UgKHN3ZklkLCBvcHRpb25zLCBzd2ZVcmwgPSBudWxsLCBtaW5GbGFzaFZlcnNpb24gPSBudWxsKSB7XG4gICAgZGVidWcoTkFNRSwgJ1thZGRzb3VyY2VdJylcbiAgICB0aGlzLl9zd2ZJZCA9IHN3ZklkO1xuICAgIHRoaXMuaG9sZGVyID0gdGhpcy5fZGV0ZXJtaW5lSG9sZGVyKHRoaXMubWVkaWEpXG4gICAgY29uc3Qgc29SZXNwb25kZXIgPSB0aGlzLl9zb1Jlc3BvbmRlclxuICAgIGNvbnN0IGRlZmVycmVkID0gbmV3IERlZmVycmVkUHJvbWlzZSgpXG4gICAgY29uc3QgaGFzRGVmaW5lZENvbnRyb2xzID0gb3B0aW9ucy5jb250cm9sc1xuICAgIGNvbnN0IGlzTXV0ZWQgPSBlbnZpcm9ubWVudC5oYXNBdHRyaWJ1dGVEZWZpbmVkKHRoaXMubWVkaWEsICdtdXRlZCcpXG4gICAgY29uc3QgdXNlUGxheWJhY2tDb250cm9scyA9IGVudmlyb25tZW50Lmhhc0F0dHJpYnV0ZURlZmluZWQodGhpcy5tZWRpYSwgJ2NvbnRyb2xzJykgJiYgZW52aXJvbm1lbnQuaGFzQ2xhc3NEZWZpbmVkKHRoaXMubWVkaWEsICdyZWQ1cHJvLW1lZGlhJylcbiAgICBvcHRpb25zLnN3ZiA9IHN3ZlVybCB8fCBvcHRpb25zLnN3ZlxuICAgIG9wdGlvbnMubWluRmxhc2hWZXJzaW9uID0gbWluRmxhc2hWZXJzaW9uIHx8IG9wdGlvbnMubWluRmxhc2hWZXJzaW9uXG4gICAgdGhpcy5fc2V0VXBJbml0Q2FsbGJhY2soZGVmZXJyZWQpXG4gICAgY29uc3QgY2xhc3NMaXN0ID0gdGhpcy5tZWRpYS5jbGFzc0xpc3RcbiAgICBlbWJlZC5kZWZpbmVFbWJlZEVsZW1lbnQodGhpcy5tZWRpYSwgdGhpcy5ob2xkZXIpXG4gICAgICAudGhlbihlbGVtZW50SWQgPT4ge1xuICAgICAgICBsZXQgZmxhc2h2YXJzID0ge1xuICAgICAgICAgIHN0cmVhbTogb3B0aW9ucy5zdHJlYW1OYW1lLFxuICAgICAgICAgIGFwcDogb3B0aW9ucy5jb250ZXh0ID8gYCR7b3B0aW9ucy5hcHB9LyR7b3B0aW9ucy5jb250ZXh0fWAgOiBvcHRpb25zLmFwcCxcbiAgICAgICAgICBob3N0OiBvcHRpb25zLmhvc3QsXG4gICAgICAgICAgbXV0ZWQ6IGVudmlyb25tZW50Lmhhc0F0dHJpYnV0ZURlZmluZWQodGhpcy5tZWRpYSwgJ211dGVkJyksXG4gICAgICAgICAgYXV0b3BsYXk6IGVudmlyb25tZW50Lmhhc0F0dHJpYnV0ZURlZmluZWQodGhpcy5tZWRpYSwgJ2F1dG9wbGF5JyksXG4gICAgICAgICAgdXNlQWRhcHRpdmVCaXRyYXRlQ29udHJvbGxlcjogb3B0aW9ucy51c2VBZGFwdGl2ZUJpdHJhdGVDb250cm9sbGVyXG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMuYmFja2dyb3VuZENvbG9yKSB7XG4gICAgICAgICAgZmxhc2h2YXJzLmJhY2tncm91bmRDb2xvciA9IG9wdGlvbnMuYmFja2dyb3VuZENvbG9yXG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMuYnVmZmVyICYmICFpc05hTihOdW1iZXIob3B0aW9ucy5idWZmZXIpKSkge1xuICAgICAgICAgIGZsYXNodmFycy5idWZmZXIgPSBvcHRpb25zLmJ1ZmZlclxuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLndpZHRoICYmICFpc05hTihvcHRpb25zLndpZHRoKSkge1xuICAgICAgICAgIGZsYXNodmFycy53aWR0aCA9IHRvSW50KG9wdGlvbnMud2lkdGgpXG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMuaGVpZ2h0ICYmICFpc05hTihvcHRpb25zLmhlaWdodCkpIHtcbiAgICAgICAgICBmbGFzaHZhcnMuaGVpZ2h0ID0gdG9JbnQob3B0aW9ucy5oZWlnaHQpXG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMuZW1iZWRXaWR0aCA9PT0gJzEwMCUnIHx8IG9wdGlvbnMuZW1iZWRIZWlnaHQgPT09ICcxMDAlJykge1xuICAgICAgICAgIGZsYXNodmFycy5hdXRvc2l6ZSA9IHRydWVcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9zd2ZJZCA9IHN3ZklkO1xuICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMuY29ubmVjdGlvblBhcmFtcyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICBmbGFzaHZhcnMuY29ubmVjdGlvblBhcmFtcyA9IGVuY29kZVVSSUNvbXBvbmVudChKU09OLnN0cmluZ2lmeShvcHRpb25zLmNvbm5lY3Rpb25QYXJhbXMpKVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5hYnJWYXJpYW50cyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICBmbGFzaHZhcnMuYWJyVmFyaWFudHMgPSBlbmNvZGVVUklDb21wb25lbnQoSlNPTi5zdHJpbmdpZnkob3B0aW9ucy5hYnJWYXJpYW50cykpXG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmFiclZhcmlhbnRVcGdyYWRlU2V0dGluZ3MgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgZmxhc2h2YXJzLmFiclZhcmlhbnRVcGdyYWRlU2V0dGluZ3MgPSBlbmNvZGVVUklDb21wb25lbnQoSlNPTi5zdHJpbmdpZnkob3B0aW9ucy5hYnJWYXJpYW50VXBncmFkZVNldHRpbmdzKSlcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZW1iZWQuZW1iZWRTd2ZPYmplY3Qoc3dmSWQsIG9wdGlvbnMsIGZsYXNodmFycywgZW52aXJvbm1lbnQuZ2V0U3dmT2JqZWN0KCksIGVsZW1lbnRJZClcbiAgICAgIH0pXG4gICAgICAudGhlbiggKCkgPT4ge1xuICAgICAgICBpZiAoaGFzRGVmaW5lZENvbnRyb2xzIHx8IHVzZVBsYXliYWNrQ29udHJvbHMpIHtcbiAgICAgICAgICBpZiAoaGFzRGVmaW5lZENvbnRyb2xzKSB7XG4gICAgICAgICAgICB0aGlzLl9jb250cm9scyA9IG9wdGlvbnMuY29udHJvbHNcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9jb250cm9scyA9IG5ldyBQbGF5YmFja0NvbnRyb2xzSW1wbCh0aGlzLCB0aGlzLmhvbGRlcilcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5tZWRpYS5jb250cm9scyA9IGZhbHNlXG4gICAgICAgICAgdGhpcy5fY29udHJvbHMuc2V0QXNWT0QoaXNWT0RTdHJlYW1OYW1lKG9wdGlvbnMuc3RyZWFtTmFtZSkpXG4gICAgICAgICAgdGhpcy5fY29udHJvbHMuc2V0TXV0ZWRTdGF0ZShpc011dGVkKVxuICAgICAgICAgIGNvbnN0IGVtYmVkZGVkID0gdGhpcy5nZXRFbWJlZGRlZFZpZXcoKVxuICAgICAgICAgIGxldCBpbmRleCA9IGNsYXNzTGlzdC5sZW5ndGgsIGNsYXp6XG4gICAgICAgICAgd2hpbGUgKC0taW5kZXggPiAtMSkge1xuICAgICAgICAgICAgY2xhenogPSBjbGFzc0xpc3QuaXRlbShpbmRleClcbiAgICAgICAgICAgIGVtYmVkZGVkLmNsYXNzTGlzdC5hZGQoY2xhenopXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2FkZFBsYXliYWNrSGFuZGxlcnModGhpcy5fcGxheWJhY2tOb3RpZmljYXRpb25DZW50ZXIpXG4gICAgICAgIHRoaXMudHJpZ2dlcihuZXcgU3Vic2NyaWJlckV2ZW50KFN1YnNjcmliZXJFdmVudFR5cGVzLlBMQVlCQUNLX1NUQVRFX0NIQU5HRSwgdW5kZWZpbmVkLCB7XG4gICAgICAgICAgY29kZTogUGxheWJhY2tTdGF0ZS5BVkFJTEFCTEUsXG4gICAgICAgICAgc3RhdGU6IFBsYXliYWNrU3RhdGVSZWFkYWJsZVtQbGF5YmFja1N0YXRlLkFWQUlMQUJMRV1cbiAgICAgICAgfSkpXG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgICB9KVxuICAgICAgLnRoZW4oICgpID0+IHtcbiAgICAgICAgc29SZXNwb25kZXIuY29ubmVjdChzd2ZJZClcbiAgICAgICAgcmV0dXJuIHRydWVcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZSA9PiBkZWZlcnJlZC5yZWplY3QoZSkpXG4gICAgcmV0dXJuIGRlZmVycmVkLnByb21pc2VcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIGNvbm5lY3QgdG8gc3RyZWFtLlxuICAgKi9cbiAgY29ubmVjdCAoKSB7XG4gICAgZGVidWcoTkFNRSwgJ1tjb25uZWN0XScpXG4gICAgdHJ5IHtcbiAgICAgIHRoaXMuZ2V0RW1iZWRkZWRWaWV3KCkuY29ubmVjdCgpXG4gICAgfVxuICAgIGNhdGNoIChlKSB7XG4gICAgICB0aHJvdyBlXG4gICAgfVxuICB9XG5cbiAgcGxheSAoKSB7XG4gICAgdHJ5IHtcbiAgICAgIHRoaXMuZ2V0RW1iZWRkZWRWaWV3KCkucGxheSgpXG4gICAgfVxuICAgIGNhdGNoIChlKSB7XG4gICAgICB0aHJvdyBlXG4gICAgfVxuICB9XG5cblxuICBwYXVzZSAoKSB7XG4gICAgdHJ5IHtcbiAgICAgIHRoaXMuZ2V0RW1iZWRkZWRWaWV3KCkucGF1c2UoKVxuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgdGhyb3cgZVxuICAgIH1cbiAgfVxuXG4gIHJlc3VtZSAoKSB7XG4gICAgdHJ5IHtcbiAgICAgIHRoaXMuZ2V0RW1iZWRkZWRWaWV3KCkucmVzdW1lKClcbiAgICB9XG4gICAgY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IGVcbiAgICB9XG4gIH1cblxuICBzdG9wICgpIHtcbiAgICB0cnkge1xuICAgICAgdGhpcy5nZXRFbWJlZGRlZFZpZXcoKS5zdG9wKClcbiAgICB9XG4gICAgY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IGVcbiAgICB9XG4gIH1cblxuICBtdXRlICgpIHtcbiAgICB0cnkge1xuICAgICAgdGhpcy5nZXRFbWJlZGRlZFZpZXcoKS5tdXRlKClcbiAgICB9XG4gICAgY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IGVcbiAgICB9XG4gIH1cblxuICB1bm11dGUgKCkge1xuICAgIHRyeSB7XG4gICAgICB0aGlzLmdldEVtYmVkZGVkVmlldygpLnVubXV0ZSgpXG4gICAgfVxuICAgIGNhdGNoIChlKSB7XG4gICAgICB0aHJvdyBlXG4gICAgfVxuICB9XG5cbiAgc2V0Vm9sdW1lICh2YWx1ZSkge1xuICAgIHRyeSB7XG4gICAgICB0aGlzLmdldEVtYmVkZGVkVmlldygpLnNldFZvbHVtZSh2YWx1ZSlcbiAgICB9XG4gICAgY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IGVcbiAgICB9XG4gIH1cblxuICBzZWVrVG8gKHZhbHVlLCBkdXJhdGlvbiA9IHVuZGVmaW5lZCkge1xuICAgIHRyeSB7XG4gICAgICB0aGlzLmdldEVtYmVkZGVkVmlldygpLnNlZWtUbyh2YWx1ZSwgZHVyYXRpb24pXG4gICAgfVxuICAgIGNhdGNoIChlKSB7XG4gICAgICB0aHJvdyBlXG4gICAgfVxuICB9XG5cbiAgdG9nZ2xlRnVsbFNjcmVlbiAoKSB7XG4gICAgdHJ5IHtcbiAgICAgIGVudmlyb25tZW50LnRvZ2dsZUZ1bGxTY3JlZW4odGhpcy5ob2xkZXIpXG4gICAgfVxuICAgIGNhdGNoIChlKSB7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRvIGRpc2Nvbm5lY3QgZnJvbSB0aGUgcGxheWJhY2sgc3RyZWFtLlxuICAgKi9cbiAgZGlzY29ubmVjdCAoKSB7XG4gICAgdHJ5IHtcbiAgICAgIHRoaXMuZ2V0RW1iZWRkZWRWaWV3KCkuZGlzY29ubmVjdCgpXG4gICAgICBkZWJ1ZyhOQU1FLCAnW2Rpc2Nvbm5lY3RdJylcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAvLyBuYWRhLlxuICAgIH1cbiAgICB0aGlzLl9jbGVhblVwKClcbiAgICB0aGlzLl9zb1Jlc3BvbmRlci5kaXNjb25uZWN0KClcbiAgfVxuXG4gIC8qKlxuICAgKiBBc3NpZ24gcmVzcG9uc2UgaGFuZGxlciBmb3IgU2hhcmVkT2JqZWN0IGNvbW11bmljYXRpb24uXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBoYW5kbGVyXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBhZGRTaGFyZWRPYmplY3RSZXNwb25zZUhhbmRsZXIgKGhhbmRsZXIpIHtcbiAgICB0aGlzLl9zb1Jlc3BvbmRlci5hZGRSZXNwb25zZUhhbmRsZXIoaGFuZGxlcilcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgcmVzcG9uc2UgaGFuZGxlciBmcm9tIFNoYXJlZE9iamVjdCBjb21tdW5pY2F0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gaGFuZGxlclxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcmVtb3ZlU2hhcmVkT2JqZWN0UmVzcG9uc2VIYW5kbGVyIChoYW5kbGVyKSB7XG4gICAgdGhpcy5fc29SZXNwb25kZXIucmVtb3ZlUmVzcG9uc2VIYW5kbGVyKGhhbmRsZXIpXG4gIH1cblxuICAvKipcbiAgICogU2VuZCBtZXNzYWdlIG9uIFNoYXJlZE9iamVjdC5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAgICogICAgICAgIFRoZSBuYW1lIG9mIHRoZSBTaGFyZWRPYmplY3QuXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBjYWxsTmFtZVxuICAgKiAgICAgICAgVGhlIG1ldGhvZCBuYW1lIHRvIGludm9rZSBvbiB0aGUgU2hhcmVkT2JqZWN0LlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiAgICAgICAgVGhlIG1lc3NhZ2UgdG8gc2VuZCBhbG9uZy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHNlbmRUb1NoYXJlZE9iamVjdCAobmFtZSwgY2FsbE5hbWUsIG1lc3NhZ2UpIHtcbiAgICB0aGlzLl9zb1Jlc3BvbmRlci5zZW5kVG9TaGFyZWRPYmplY3QobmFtZSwgY2FsbE5hbWUsIG1lc3NhZ2UpXG4gIH1cblxuICAvKipcbiAgICogU2VuZCBwcm9wZXJ0eSB1cGRhdGUgdG8gU2hhcmVkT2JqZWN0LlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZVxuICAgKiAgICAgICAgVGhlIG5hbWUgb2YgdGhlIFNoYXJlZE9iamVjdC5cbiAgICogQHBhcmFtIHtTdHJpbmd9IGtleVxuICAgKiAgICAgICAgVGhlIHByb3BlcnR5IG5hbWUgdG8gdXBkYXRlLlxuICAgKiBAcGFyYW0ge1N0cmluZ30gdmFsdWVcbiAgICogICAgICAgIFRoZSBwcm9wZXJ0eSB2YWx1ZSB0byBzZXQuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBzZW5kUHJvcGVydHlUb1NoYXJlZE9iamVjdCAobmFtZSwga2V5LCB2YWx1ZSkge1xuICAgIHRoaXMuX3NvUmVzcG9uZGVyLnNlbmRQcm9wZXJ0eVRvU2hhcmVkT2JqZWN0KG5hbWUsIGtleSwgdmFsdWUpXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBnZXQgdGhlIHJlbW90ZSBTaGFyZWRPYmplY3Qgb24gdGhlIHNlcnZlciBieSBuYW1lLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gc2hhcmVkT2JqZWN0TmFtZVxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgZ2V0UmVtb3RlU2hhcmVkT2JqZWN0IChzaGFyZWRPYmplY3ROYW1lKSB7XG4gICAgdGhpcy5fc29SZXNwb25kZXIuZ2V0UmVtb3RlU2hhcmVkT2JqZWN0KHNoYXJlZE9iamVjdE5hbWUpXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBjb25uZWN0IHRvIFNoYXJlZE9iamVjdCBieSBuYW1lLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gc2hhcmVkT2JqZWN0TmFtZVxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgY29ubmVjdFRvU2hhcmVkT2JqZWN0IChzaGFyZWRPYmplY3ROYW1lKSB7XG4gICAgdGhpcy5fc29SZXNwb25kZXIuY29ubmVjdFRvU2hhcmVkT2JqZWN0KHNoYXJlZE9iamVjdE5hbWUpXG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byBjbG9zZSB0aGUgU2hhcmVkT2JqZWN0IGJ5IG5hbWUuXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzaGFyZWRPYmplY3ROYW1lXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBjbG9zZVNoYXJlZE9iamVjdCAoc2hhcmVkT2JqZWN0TmFtZSkge1xuICAgIHRoaXMuX3NvUmVzcG9uZGVyLmNsb3NlU2hhcmVkT2JqZWN0KHNoYXJlZE9iamVjdE5hbWUpXG4gIH1cblxuICAvKlxuICAgKiBSZXF1ZXN0IHRvIHN0YXJ0IHRoZSBBZGFwdGl2ZSBCaXRyYXRlIENvbnRyb2xsZXIgdG8gYXV0b21hdGljYWxseSBkb3duZ3JhZGUgYW5kIHVwZ3JhZGUgc3RyZWFtcyBiYXNlZCBvbiBOZXRTdGF0dXMgYW5kIGJhbmR3aWR0aC5cbiAgICogVGhlIEFCUiBpcyBzdGFydGVkIGF1dG9tYXRpY2FsbHkgd2hlbiBwcm92aWRpbmcgdGhlIGB1c2VBZGFwdGl2ZUJpdHJhdGVDb250cm9sbGVyYCBjb25maWd1cmF0aW9uIHByb3BlcnR5LlxuICAgKlxuICAgKiBOT1RFOiBBZGFwdGl2ZSBCaXRyYXRlIENvbnRyb2xsZXIgQVBJIGlzIG9ubHkgYXZhaWxhYmxlIHdoZW4gdXNpbmcgQXV0b3NjYWxlLUVuYWJsZWQgUmVkNSBQcm8gU2VydmVyLlxuICAgKi9cbiAgc3RhcnRBQlJDb250cm9sbGVyICgpIHtcbiAgICB0cnkge1xuICAgICAgdGhpcy5nZXRFbWJlZGRlZFZpZXcoKS5zdGFydEFCUkNvbnRyb2xsZXIoKTtcbiAgICB9XG4gICAgY2F0Y2ggKGUpIHtcbiAgICAgIGRlYnVnKE5BTUUsIGBDb3VsZCBub3Qgc3RhcnQgdGhlIEFkYXB0aXZlIEJpdHJhdGUgQ29udHJvbGxlcjogJHtlLm1lc3NhZ2V9YClcbiAgICB9XG4gIH1cblxuICAvKlxuICAgKiBSZXF1ZXN0IHRvIHN0b3AgdGhlIEFkYXB0aXZlIEJpdHJhdGUgQ29udHJvbGxlciBmcm9tIGF1dG9tYXRpY2FsbHkgZG93bmdyYWRpbmcgYW5kIHVwZ3JhZGluZyBzdHJlYW1zIGJhc2VkIG9uIE5ldFN0YXR1cyBhbmQgYmFuZHdpZHRoLlxuICAgKlxuICAgKiBOT1RFOiBBZGFwdGl2ZSBCaXRyYXRlIENvbnRyb2xsZXIgQVBJIGlzIG9ubHkgYXZhaWxhYmxlIHdoZW4gdXNpbmcgQXV0b3NjYWxlLUVuYWJsZWQgUmVkNSBQcm8gU2VydmVyLlxuICAgKi9cbiAgc3RvcEFCUkNvbnRyb2xsZXIgKCkge1xuICAgIHRyeSB7XG4gICAgICB0aGlzLmdldEVtYmVkZGVkVmlldygpLnN0b3BBQlJDb250cm9sbGVyKCk7XG4gICAgfVxuICAgIGNhdGNoIChlKSB7XG4gICAgICBkZWJ1ZyhOQU1FLCBgQ291bGQgbm90IHN0b3AgdGhlIEFkYXB0aXZlIEJpdHJhdGUgQ29udHJvbGxlcjogJHtlLm1lc3NhZ2V9YClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0byB1c2UgdGhlIHByb3ZpZGUgQUJSIFZhcmlhbnRzIHdoZW4gcGVyZm9ybWluZyBBZGFwdGl2ZSBCaXRyYXRlIENvbnRyb2wuXG4gICAqIFJlcXVpcmVzIHRoZSBgdXNlQWRhcHRpdmVCaXRyYXRlQ29udHJvbGxlcmAgaW50aXRpYWxpemF0aW9uIGNvbmZpZ3VyYXRpb24gcHJvcGVydHkgdG8gYmUgYHRydWVgLlxuICAgKiBOT1RFOiBBZGFwdGl2ZSBCaXRyYXRlIENvbnRyb2xsZXIgQVBJIGlzIG9ubHkgYXZhaWxhYmxlIHdoZW4gdXNpbmcgQXV0b3NjYWxlLUVuYWJsZWQgUmVkNSBQcm8gU2VydmVyLlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gYWJyU2V0dGluZ3NcbiAgICogICAgICAgIFRPRE86IFByb3ZpZGUgQUJSIFZhcmlhbnQgb2JqZWN0IHNjaGVtYSBleHBlY3RlZC5cbiAgICogQHBhcmFtIHtpbnR9IGxldmVsXG4gICAqICAgICAgICBUaGUgbGV2ZWwgdG8gc3RhcnQgb3V0IG9uIGZvciBBQlIuXG4gICAqL1xuICBzZXRBQlJWYXJpYW50cyAoYWJyVmFyaWFudHMsIGxldmVsKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHZhbHVlID0gdHlwZW9mIGFiclZhcmlhbnRzID09PSAnc3RyaW5nJyA/IGVuY29kZVVSSUNvbXBvbmVudChhYnJWYXJpYW50cykgOiBlbmNvZGVVUklDb21wb25lbnQoSlNPTi5zdHJpbmdpZnkoYWJyVmFyaWFudHMpKVxuICAgICAgdGhpcy5nZXRFbWJlZGRlZFZpZXcoKS5zZXRBQlJWYXJpYW50cyh2YWx1ZSwgbGV2ZWwgfHwgMSlcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBkZWJ1ZyhOQU1FLCBgQ291bGQgbm90IHNldCBBQlIgVmFyaWFudHM6ICR7ZS5tZXNzYWdlfWApXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdG8gc2V0IEFCUiBsZXZlbCBleHBsaWNpdGx5LiBUaGUgU0RLIGF0dGVtcHRzIHRvIHByb3Blcmx5IGNob29zZSB0aGUgY29ycmVjdCBsZXZlbCBiYXNlZCBvbiBiYW5kd2lkdGgsIGJ1dCB0aGlzIEFQSSBhbGxvd3MgZm9yIHRoZSBsZXZlbCB0byBiZSBzZXQgZXhwbGljaXRseS5cbiAgICpcbiAgICogTk9URTogQWRhcHRpdmUgQml0cmF0ZSBDb250cm9sbGVyIEFQSSBpcyBvbmx5IGF2YWlsYWJsZSB3aGVuIHVzaW5nIEF1dG9zY2FsZS1FbmFibGVkIFJlZDUgUHJvIFNlcnZlci5cbiAgICpcbiAgICogQHBhcmFtIHtpbnR9IGxldmVsXG4gICAqICAgICAgICBUaGUgbGV2ZWwgdG8gc2V0IHRoZSBBQlIgYmFzZWQgb24gdGhlIHZhcmlhbnRzIHByb3ZpZGVkIGluIGBzZXRBQlJWYXJpYW50c2AuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gZmlybVxuICAgKiAgICAgICAgRmxhZyB0byBzZXQgbGV2ZWwgZmlybWx5LCBkaXNhYmxpbmcgdGhlIGF1dG9tYXRpYyBzd2l0Y2hpbmcgb2YgdGhlIEFkYXB0aXZlIEJpdHJhdGUgQ29udHJvbGxlci5cbiAgICovXG4gIHNldEFCUkxldmVsIChsZXZlbCwgZmlybSkge1xuICAgIHRyeSB7XG4gICAgICB0aGlzLmdldEVtYmVkZGVkVmlldygpLnNldEFCUkxldmVsKGxldmVsLCAhIWZpcm0pXG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgZGVidWcoTkFNRSwgYENvdWxkIG5vdCBzZXQgQUJSIGxldmVsOiAke2UubWVzc2FnZX1gKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQcm92aWRlcyB0aGUgdXBncmFkZSBzZXR0aW5ncyB0byB1c2UgYnkgdGhlIEFkYXB0aXZlIEJpdHJhdGUgQ29udHJvbCBpbiB1cGdyYWRpbmcgcHJldmlvdXNseSBkb3duZ3JhZGVkIHN0cmVhbXMuXG4gICAqXG4gICAqIE5PVEU6IEFkYXB0aXZlIEJpdHJhdGUgQ29udHJvbGxlciBBUEkgaXMgb25seSBhdmFpbGFibGUgd2hlbiB1c2luZyBBdXRvc2NhbGUtRW5hYmxlZCBSZWQ1IFBybyBTZXJ2ZXIuXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBhYnJWYXJpYW50VXBncmFkZXNcbiAgICogICAgICAgIEEgY29uZmlndXJhdGlvbiBvYmplY3QgdGhhdCBkZWZpbmVzIHRoZSBhc3NvY2lhdGVkIHJldHJ5IGxpbWl0cyBiYXNlZCBvbiBsZXZlbHMgb2YgdGhlIFByb3Zpc2lvbiBWYXJpYW50cy5cbiAgICogQGV4YW1wbGVcbiAgICoge1xuICAgKiAgbWluaW11bURvd25ncmFkZVBsYXliYWNrU3BhbjogMjAwMCxcbiAgICogIHVwZ3JhZGU6IFtcbiAgICogICAge1xuICAgKiAgICAgIGxldmVsOiAxLFxuICAgKiAgICAgIHJldHJ5VGltZW91dDogMFxuICAgKiAgICB9LFxuICAgKiAgICB7XG4gICAqICAgICAgbGV2ZWw6IDIsXG4gICAqICAgICAgcmV0cnlUaW1lb3V0OiAyMDAwXG4gICAqICAgIH0sXG4gICAqICAgIHtcbiAgICogICAgICBsZXZlbDogMyxcbiAgICogICAgICByZXRyeVRpbWVvdXQ6IDQwMDBcbiAgICogICAgfVxuICAgKiAgXVxuICAgKiB9XG4gICAqL1xuICBzZXRBQlJWYXJpYW50VXBncmFkZVNldHRpbmdzIChhYnJWYXJpYW50VXBncmFkZXMpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgdmFsdWUgPSB0eXBlb2YgYWJyVmFyaWFudHMgPT09ICdzdHJpbmcnID8gZW5jb2RlVVJJQ29tcG9uZW50KGFiclZhcmlhbnRVcGdyYWRlcykgOiBlbmNvZGVVUklDb21wb25lbnQoSlNPTi5zdHJpbmdpZnkoYWJyVmFyaWFudFVwZ3JhZGVzKSlcbiAgICAgIHRoaXMuZ2V0RW1iZWRkZWRWaWV3KCkuc2V0QUJSVmFyaWFudFVwZ3JhZGVTZXR0aW5ncyh2YWx1ZSlcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBkZWJ1ZyhOQU1FLCBgQ291bGQgbm90IHNldCBBQlIgVmFyaWFudHM6ICR7ZS5tZXNzYWdlfWApXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGVtYmVkZGVkIEZsYXNoIG9iamVjdCBpZiBhdmFpbGFibGUuXG4gICAqXG4gICAqIEByZXR1cm5zIHtFbGVtZW50fVxuICAgKi9cbiAgZ2V0RW1iZWRkZWRWaWV3ICgpIHtcbiAgICByZXR1cm4gZW52aXJvbm1lbnQuZ2V0RW1iZWRPYmplY3QodGhpcy5fc3dmSWQpXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBwbGF5YmFjayBjb250cm9scyBpZiBhdmFpbGFibGUuXG4gICAqXG4gICAqIEByZXR1cm5zIHtQbGF5YmFja0NvbnRyb2xzfVxuICAgKi9cbiAgZ2V0Q29udHJvbHMgKCkge1xuICAgIHJldHVybiB0aGlzLl9jb250cm9sc1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHN1YnNjcmliZXIgdHlwZSBhc3NvY2lhdGVkIHdpdGggdGhpcyBjb250cm9sbGVyLlxuICAgKlxuICAgKiBAcmV0dXJucyB7U3RyaW5nfVxuICAgKi9cbiAgZ2V0VHlwZSAoKSB7XG4gICAgcmV0dXJuIHRoaXMucGxheWVyVHlwZVxuICB9XG5cbn1cblxuZXhwb3J0IGRlZmF1bHQgUlRNUFNvdXJjZUhhbmRsZXJcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9qcy9zdWJzY3JpYmVyL3JlZDVwcm8tc291cmNlLWhhbmRsZXItcnRtcC5qcyIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9hcnJheS9mcm9tXCIpLCBfX2VzTW9kdWxlOiB0cnVlIH07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9hcnJheS9mcm9tLmpzXG4vLyBtb2R1bGUgaWQgPSAxMzJcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSB7IFwiZGVmYXVsdFwiOiByZXF1aXJlKFwiY29yZS1qcy9saWJyYXJ5L2ZuL2dldC1pdGVyYXRvclwiKSwgX19lc01vZHVsZTogdHJ1ZSB9O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9iYWJlbC1ydW50aW1lL2NvcmUtanMvZ2V0LWl0ZXJhdG9yLmpzXG4vLyBtb2R1bGUgaWQgPSAxMzNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSB7IFwiZGVmYXVsdFwiOiByZXF1aXJlKFwiY29yZS1qcy9saWJyYXJ5L2ZuL2lzLWl0ZXJhYmxlXCIpLCBfX2VzTW9kdWxlOiB0cnVlIH07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9pcy1pdGVyYWJsZS5qc1xuLy8gbW9kdWxlIGlkID0gMTM0XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9udW1iZXIvaXMtbmFuXCIpLCBfX2VzTW9kdWxlOiB0cnVlIH07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9udW1iZXIvaXMtbmFuLmpzXG4vLyBtb2R1bGUgaWQgPSAxMzVcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSB7IFwiZGVmYXVsdFwiOiByZXF1aXJlKFwiY29yZS1qcy9saWJyYXJ5L2ZuL29iamVjdC9hc3NpZ25cIiksIF9fZXNNb2R1bGU6IHRydWUgfTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vYmFiZWwtcnVudGltZS9jb3JlLWpzL29iamVjdC9hc3NpZ24uanNcbi8vIG1vZHVsZSBpZCA9IDEzNlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IHsgXCJkZWZhdWx0XCI6IHJlcXVpcmUoXCJjb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2NyZWF0ZVwiKSwgX19lc01vZHVsZTogdHJ1ZSB9O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9iYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L2NyZWF0ZS5qc1xuLy8gbW9kdWxlIGlkID0gMTM3XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9vYmplY3QvZ2V0LW93bi1wcm9wZXJ0eS1kZXNjcmlwdG9yXCIpLCBfX2VzTW9kdWxlOiB0cnVlIH07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9vYmplY3QvZ2V0LW93bi1wcm9wZXJ0eS1kZXNjcmlwdG9yLmpzXG4vLyBtb2R1bGUgaWQgPSAxMzhcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSB7IFwiZGVmYXVsdFwiOiByZXF1aXJlKFwiY29yZS1qcy9saWJyYXJ5L2ZuL29iamVjdC9zZXQtcHJvdG90eXBlLW9mXCIpLCBfX2VzTW9kdWxlOiB0cnVlIH07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9vYmplY3Qvc2V0LXByb3RvdHlwZS1vZi5qc1xuLy8gbW9kdWxlIGlkID0gMTM5XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9zeW1ib2xcIiksIF9fZXNNb2R1bGU6IHRydWUgfTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vYmFiZWwtcnVudGltZS9jb3JlLWpzL3N5bWJvbC5qc1xuLy8gbW9kdWxlIGlkID0gMTQwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9zeW1ib2wvaXRlcmF0b3JcIiksIF9fZXNNb2R1bGU6IHRydWUgfTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vYmFiZWwtcnVudGltZS9jb3JlLWpzL3N5bWJvbC9pdGVyYXRvci5qc1xuLy8gbW9kdWxlIGlkID0gMTQxXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi93ZWFrLW1hcFwiKSwgX19lc01vZHVsZTogdHJ1ZSB9O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9iYWJlbC1ydW50aW1lL2NvcmUtanMvd2Vhay1tYXAuanNcbi8vIG1vZHVsZSBpZCA9IDE0MlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJcInVzZSBzdHJpY3RcIjtcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxudmFyIF9pc0l0ZXJhYmxlMiA9IHJlcXVpcmUoXCIuLi9jb3JlLWpzL2lzLWl0ZXJhYmxlXCIpO1xuXG52YXIgX2lzSXRlcmFibGUzID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfaXNJdGVyYWJsZTIpO1xuXG52YXIgX2dldEl0ZXJhdG9yMiA9IHJlcXVpcmUoXCIuLi9jb3JlLWpzL2dldC1pdGVyYXRvclwiKTtcblxudmFyIF9nZXRJdGVyYXRvcjMgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9nZXRJdGVyYXRvcjIpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG5leHBvcnRzLmRlZmF1bHQgPSBmdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIHNsaWNlSXRlcmF0b3IoYXJyLCBpKSB7XG4gICAgdmFyIF9hcnIgPSBbXTtcbiAgICB2YXIgX24gPSB0cnVlO1xuICAgIHZhciBfZCA9IGZhbHNlO1xuICAgIHZhciBfZSA9IHVuZGVmaW5lZDtcblxuICAgIHRyeSB7XG4gICAgICBmb3IgKHZhciBfaSA9ICgwLCBfZ2V0SXRlcmF0b3IzLmRlZmF1bHQpKGFyciksIF9zOyAhKF9uID0gKF9zID0gX2kubmV4dCgpKS5kb25lKTsgX24gPSB0cnVlKSB7XG4gICAgICAgIF9hcnIucHVzaChfcy52YWx1ZSk7XG5cbiAgICAgICAgaWYgKGkgJiYgX2Fyci5sZW5ndGggPT09IGkpIGJyZWFrO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgX2QgPSB0cnVlO1xuICAgICAgX2UgPSBlcnI7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGlmICghX24gJiYgX2lbXCJyZXR1cm5cIl0pIF9pW1wicmV0dXJuXCJdKCk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBpZiAoX2QpIHRocm93IF9lO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBfYXJyO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChhcnIsIGkpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShhcnIpKSB7XG4gICAgICByZXR1cm4gYXJyO1xuICAgIH0gZWxzZSBpZiAoKDAsIF9pc0l0ZXJhYmxlMy5kZWZhdWx0KShPYmplY3QoYXJyKSkpIHtcbiAgICAgIHJldHVybiBzbGljZUl0ZXJhdG9yKGFyciwgaSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIGF0dGVtcHQgdG8gZGVzdHJ1Y3R1cmUgbm9uLWl0ZXJhYmxlIGluc3RhbmNlXCIpO1xuICAgIH1cbiAgfTtcbn0oKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vYmFiZWwtcnVudGltZS9oZWxwZXJzL3NsaWNlZFRvQXJyYXkuanNcbi8vIG1vZHVsZSBpZCA9IDE0M1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJyZWdlbmVyYXRvci1ydW50aW1lXCIpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2JhYmVsLXJ1bnRpbWUvcmVnZW5lcmF0b3IvaW5kZXguanNcbi8vIG1vZHVsZSBpZCA9IDE0NFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJyZXF1aXJlKCcuLi8uLi9tb2R1bGVzL2VzNi5zdHJpbmcuaXRlcmF0b3InKTtcbnJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2LmFycmF5LmZyb20nKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9fY29yZScpLkFycmF5LmZyb207XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9mbi9hcnJheS9mcm9tLmpzXG4vLyBtb2R1bGUgaWQgPSAxNDVcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwicmVxdWlyZSgnLi4vbW9kdWxlcy93ZWIuZG9tLml0ZXJhYmxlJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL2VzNi5zdHJpbmcuaXRlcmF0b3InKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vbW9kdWxlcy9jb3JlLmdldC1pdGVyYXRvcicpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vZ2V0LWl0ZXJhdG9yLmpzXG4vLyBtb2R1bGUgaWQgPSAxNDZcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwicmVxdWlyZSgnLi4vbW9kdWxlcy93ZWIuZG9tLml0ZXJhYmxlJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL2VzNi5zdHJpbmcuaXRlcmF0b3InKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vbW9kdWxlcy9jb3JlLmlzLWl0ZXJhYmxlJyk7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9mbi9pcy1pdGVyYWJsZS5qc1xuLy8gbW9kdWxlIGlkID0gMTQ3XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsInZhciBjb3JlICA9IHJlcXVpcmUoJy4uLy4uL21vZHVsZXMvX2NvcmUnKVxuICAsICRKU09OID0gY29yZS5KU09OIHx8IChjb3JlLkpTT04gPSB7c3RyaW5naWZ5OiBKU09OLnN0cmluZ2lmeX0pO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdHJpbmdpZnkoaXQpeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gIHJldHVybiAkSlNPTi5zdHJpbmdpZnkuYXBwbHkoJEpTT04sIGFyZ3VtZW50cyk7XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vanNvbi9zdHJpbmdpZnkuanNcbi8vIG1vZHVsZSBpZCA9IDE0OFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJyZXF1aXJlKCcuLi9tb2R1bGVzL2VzNi5vYmplY3QudG8tc3RyaW5nJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL2VzNi5zdHJpbmcuaXRlcmF0b3InKTtcbnJlcXVpcmUoJy4uL21vZHVsZXMvd2ViLmRvbS5pdGVyYWJsZScpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczYubWFwJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL2VzNy5tYXAudG8tanNvbicpO1xubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi9tb2R1bGVzL19jb3JlJykuTWFwO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vbWFwLmpzXG4vLyBtb2R1bGUgaWQgPSAxNDlcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwicmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9lczYubnVtYmVyLmlzLWZpbml0ZScpO1xubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi8uLi9tb2R1bGVzL19jb3JlJykuTnVtYmVyLmlzRmluaXRlO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vbnVtYmVyL2lzLWZpbml0ZS5qc1xuLy8gbW9kdWxlIGlkID0gMTUwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsInJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2Lm51bWJlci5pcy1uYW4nKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9fY29yZScpLk51bWJlci5pc05hTjtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L2ZuL251bWJlci9pcy1uYW4uanNcbi8vIG1vZHVsZSBpZCA9IDE1MVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJyZXF1aXJlKCcuLi8uLi9tb2R1bGVzL2VzNi5vYmplY3QuYXNzaWduJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uLy4uL21vZHVsZXMvX2NvcmUnKS5PYmplY3QuYXNzaWduO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2Fzc2lnbi5qc1xuLy8gbW9kdWxlIGlkID0gMTUyXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsInJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2Lm9iamVjdC5jcmVhdGUnKTtcbnZhciAkT2JqZWN0ID0gcmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9fY29yZScpLk9iamVjdDtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY3JlYXRlKFAsIEQpe1xuICByZXR1cm4gJE9iamVjdC5jcmVhdGUoUCwgRCk7XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2NyZWF0ZS5qc1xuLy8gbW9kdWxlIGlkID0gMTUzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsInJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2Lm9iamVjdC5kZWZpbmUtcHJvcGVydHknKTtcbnZhciAkT2JqZWN0ID0gcmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9fY29yZScpLk9iamVjdDtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZGVmaW5lUHJvcGVydHkoaXQsIGtleSwgZGVzYyl7XG4gIHJldHVybiAkT2JqZWN0LmRlZmluZVByb3BlcnR5KGl0LCBrZXksIGRlc2MpO1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L2ZuL29iamVjdC9kZWZpbmUtcHJvcGVydHkuanNcbi8vIG1vZHVsZSBpZCA9IDE1NFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJyZXF1aXJlKCcuLi8uLi9tb2R1bGVzL2VzNi5vYmplY3QuZnJlZXplJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uLy4uL21vZHVsZXMvX2NvcmUnKS5PYmplY3QuZnJlZXplO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2ZyZWV6ZS5qc1xuLy8gbW9kdWxlIGlkID0gMTU1XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsInJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2Lm9iamVjdC5nZXQtb3duLXByb3BlcnR5LWRlc2NyaXB0b3InKTtcbnZhciAkT2JqZWN0ID0gcmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9fY29yZScpLk9iamVjdDtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKGl0LCBrZXkpe1xuICByZXR1cm4gJE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoaXQsIGtleSk7XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2dldC1vd24tcHJvcGVydHktZGVzY3JpcHRvci5qc1xuLy8gbW9kdWxlIGlkID0gMTU2XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsInJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2Lm9iamVjdC5nZXQtcHJvdG90eXBlLW9mJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uLy4uL21vZHVsZXMvX2NvcmUnKS5PYmplY3QuZ2V0UHJvdG90eXBlT2Y7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9mbi9vYmplY3QvZ2V0LXByb3RvdHlwZS1vZi5qc1xuLy8gbW9kdWxlIGlkID0gMTU3XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsInJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2Lm9iamVjdC5rZXlzJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uLy4uL21vZHVsZXMvX2NvcmUnKS5PYmplY3Qua2V5cztcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L2ZuL29iamVjdC9rZXlzLmpzXG4vLyBtb2R1bGUgaWQgPSAxNThcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwicmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9lczYub2JqZWN0LnNldC1wcm90b3R5cGUtb2YnKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9fY29yZScpLk9iamVjdC5zZXRQcm90b3R5cGVPZjtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L2ZuL29iamVjdC9zZXQtcHJvdG90eXBlLW9mLmpzXG4vLyBtb2R1bGUgaWQgPSAxNTlcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwicmVxdWlyZSgnLi4vbW9kdWxlcy9lczYub2JqZWN0LnRvLXN0cmluZycpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczYuc3RyaW5nLml0ZXJhdG9yJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL3dlYi5kb20uaXRlcmFibGUnKTtcbnJlcXVpcmUoJy4uL21vZHVsZXMvZXM2LnByb21pc2UnKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vbW9kdWxlcy9fY29yZScpLlByb21pc2U7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9mbi9wcm9taXNlLmpzXG4vLyBtb2R1bGUgaWQgPSAxNjBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwicmVxdWlyZSgnLi4vbW9kdWxlcy9lczYub2JqZWN0LnRvLXN0cmluZycpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczYuc3RyaW5nLml0ZXJhdG9yJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL3dlYi5kb20uaXRlcmFibGUnKTtcbnJlcXVpcmUoJy4uL21vZHVsZXMvZXM2LnNldCcpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczcuc2V0LnRvLWpzb24nKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vbW9kdWxlcy9fY29yZScpLlNldDtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L2ZuL3NldC5qc1xuLy8gbW9kdWxlIGlkID0gMTYxXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsInJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2LnN5bWJvbCcpO1xucmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9lczYub2JqZWN0LnRvLXN0cmluZycpO1xucmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9lczcuc3ltYm9sLmFzeW5jLWl0ZXJhdG9yJyk7XG5yZXF1aXJlKCcuLi8uLi9tb2R1bGVzL2VzNy5zeW1ib2wub2JzZXJ2YWJsZScpO1xubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi8uLi9tb2R1bGVzL19jb3JlJykuU3ltYm9sO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vc3ltYm9sL2luZGV4LmpzXG4vLyBtb2R1bGUgaWQgPSAxNjJcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwicmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9lczYuc3RyaW5nLml0ZXJhdG9yJyk7XG5yZXF1aXJlKCcuLi8uLi9tb2R1bGVzL3dlYi5kb20uaXRlcmFibGUnKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9fd2tzLWV4dCcpLmYoJ2l0ZXJhdG9yJyk7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9mbi9zeW1ib2wvaXRlcmF0b3IuanNcbi8vIG1vZHVsZSBpZCA9IDE2M1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJyZXF1aXJlKCcuLi9tb2R1bGVzL2VzNi5vYmplY3QudG8tc3RyaW5nJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL3dlYi5kb20uaXRlcmFibGUnKTtcbnJlcXVpcmUoJy4uL21vZHVsZXMvZXM2LndlYWstbWFwJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uL21vZHVsZXMvX2NvcmUnKS5XZWFrTWFwO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvZm4vd2Vhay1tYXAuanNcbi8vIG1vZHVsZSBpZCA9IDE2NFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKCl7IC8qIGVtcHR5ICovIH07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19hZGQtdG8tdW5zY29wYWJsZXMuanNcbi8vIG1vZHVsZSBpZCA9IDE2NVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJ2YXIgZm9yT2YgPSByZXF1aXJlKCcuL19mb3Itb2YnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpdGVyLCBJVEVSQVRPUil7XG4gIHZhciByZXN1bHQgPSBbXTtcbiAgZm9yT2YoaXRlciwgZmFsc2UsIHJlc3VsdC5wdXNoLCByZXN1bHQsIElURVJBVE9SKTtcbiAgcmV0dXJuIHJlc3VsdDtcbn07XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2FycmF5LWZyb20taXRlcmFibGUuanNcbi8vIG1vZHVsZSBpZCA9IDE2NlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyBmYWxzZSAtPiBBcnJheSNpbmRleE9mXG4vLyB0cnVlICAtPiBBcnJheSNpbmNsdWRlc1xudmFyIHRvSU9iamVjdCA9IHJlcXVpcmUoJy4vX3RvLWlvYmplY3QnKVxuICAsIHRvTGVuZ3RoICA9IHJlcXVpcmUoJy4vX3RvLWxlbmd0aCcpXG4gICwgdG9JbmRleCAgID0gcmVxdWlyZSgnLi9fdG8taW5kZXgnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oSVNfSU5DTFVERVMpe1xuICByZXR1cm4gZnVuY3Rpb24oJHRoaXMsIGVsLCBmcm9tSW5kZXgpe1xuICAgIHZhciBPICAgICAgPSB0b0lPYmplY3QoJHRoaXMpXG4gICAgICAsIGxlbmd0aCA9IHRvTGVuZ3RoKE8ubGVuZ3RoKVxuICAgICAgLCBpbmRleCAgPSB0b0luZGV4KGZyb21JbmRleCwgbGVuZ3RoKVxuICAgICAgLCB2YWx1ZTtcbiAgICAvLyBBcnJheSNpbmNsdWRlcyB1c2VzIFNhbWVWYWx1ZVplcm8gZXF1YWxpdHkgYWxnb3JpdGhtXG4gICAgaWYoSVNfSU5DTFVERVMgJiYgZWwgIT0gZWwpd2hpbGUobGVuZ3RoID4gaW5kZXgpe1xuICAgICAgdmFsdWUgPSBPW2luZGV4KytdO1xuICAgICAgaWYodmFsdWUgIT0gdmFsdWUpcmV0dXJuIHRydWU7XG4gICAgLy8gQXJyYXkjdG9JbmRleCBpZ25vcmVzIGhvbGVzLCBBcnJheSNpbmNsdWRlcyAtIG5vdFxuICAgIH0gZWxzZSBmb3IoO2xlbmd0aCA+IGluZGV4OyBpbmRleCsrKWlmKElTX0lOQ0xVREVTIHx8IGluZGV4IGluIE8pe1xuICAgICAgaWYoT1tpbmRleF0gPT09IGVsKXJldHVybiBJU19JTkNMVURFUyB8fCBpbmRleCB8fCAwO1xuICAgIH0gcmV0dXJuICFJU19JTkNMVURFUyAmJiAtMTtcbiAgfTtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19hcnJheS1pbmNsdWRlcy5qc1xuLy8gbW9kdWxlIGlkID0gMTY3XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsInZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpXG4gICwgaXNBcnJheSAgPSByZXF1aXJlKCcuL19pcy1hcnJheScpXG4gICwgU1BFQ0lFUyAgPSByZXF1aXJlKCcuL193a3MnKSgnc3BlY2llcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKG9yaWdpbmFsKXtcbiAgdmFyIEM7XG4gIGlmKGlzQXJyYXkob3JpZ2luYWwpKXtcbiAgICBDID0gb3JpZ2luYWwuY29uc3RydWN0b3I7XG4gICAgLy8gY3Jvc3MtcmVhbG0gZmFsbGJhY2tcbiAgICBpZih0eXBlb2YgQyA9PSAnZnVuY3Rpb24nICYmIChDID09PSBBcnJheSB8fCBpc0FycmF5KEMucHJvdG90eXBlKSkpQyA9IHVuZGVmaW5lZDtcbiAgICBpZihpc09iamVjdChDKSl7XG4gICAgICBDID0gQ1tTUEVDSUVTXTtcbiAgICAgIGlmKEMgPT09IG51bGwpQyA9IHVuZGVmaW5lZDtcbiAgICB9XG4gIH0gcmV0dXJuIEMgPT09IHVuZGVmaW5lZCA/IEFycmF5IDogQztcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19hcnJheS1zcGVjaWVzLWNvbnN0cnVjdG9yLmpzXG4vLyBtb2R1bGUgaWQgPSAxNjhcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8gOS40LjIuMyBBcnJheVNwZWNpZXNDcmVhdGUob3JpZ2luYWxBcnJheSwgbGVuZ3RoKVxudmFyIHNwZWNpZXNDb25zdHJ1Y3RvciA9IHJlcXVpcmUoJy4vX2FycmF5LXNwZWNpZXMtY29uc3RydWN0b3InKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihvcmlnaW5hbCwgbGVuZ3RoKXtcbiAgcmV0dXJuIG5ldyAoc3BlY2llc0NvbnN0cnVjdG9yKG9yaWdpbmFsKSkobGVuZ3RoKTtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19hcnJheS1zcGVjaWVzLWNyZWF0ZS5qc1xuLy8gbW9kdWxlIGlkID0gMTY5XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIid1c2Ugc3RyaWN0JztcbnZhciByZWRlZmluZUFsbCAgICAgICA9IHJlcXVpcmUoJy4vX3JlZGVmaW5lLWFsbCcpXG4gICwgZ2V0V2VhayAgICAgICAgICAgPSByZXF1aXJlKCcuL19tZXRhJykuZ2V0V2Vha1xuICAsIGFuT2JqZWN0ICAgICAgICAgID0gcmVxdWlyZSgnLi9fYW4tb2JqZWN0JylcbiAgLCBpc09iamVjdCAgICAgICAgICA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpXG4gICwgYW5JbnN0YW5jZSAgICAgICAgPSByZXF1aXJlKCcuL19hbi1pbnN0YW5jZScpXG4gICwgZm9yT2YgICAgICAgICAgICAgPSByZXF1aXJlKCcuL19mb3Itb2YnKVxuICAsIGNyZWF0ZUFycmF5TWV0aG9kID0gcmVxdWlyZSgnLi9fYXJyYXktbWV0aG9kcycpXG4gICwgJGhhcyAgICAgICAgICAgICAgPSByZXF1aXJlKCcuL19oYXMnKVxuICAsIGFycmF5RmluZCAgICAgICAgID0gY3JlYXRlQXJyYXlNZXRob2QoNSlcbiAgLCBhcnJheUZpbmRJbmRleCAgICA9IGNyZWF0ZUFycmF5TWV0aG9kKDYpXG4gICwgaWQgICAgICAgICAgICAgICAgPSAwO1xuXG4vLyBmYWxsYmFjayBmb3IgdW5jYXVnaHQgZnJvemVuIGtleXNcbnZhciB1bmNhdWdodEZyb3plblN0b3JlID0gZnVuY3Rpb24odGhhdCl7XG4gIHJldHVybiB0aGF0Ll9sIHx8ICh0aGF0Ll9sID0gbmV3IFVuY2F1Z2h0RnJvemVuU3RvcmUpO1xufTtcbnZhciBVbmNhdWdodEZyb3plblN0b3JlID0gZnVuY3Rpb24oKXtcbiAgdGhpcy5hID0gW107XG59O1xudmFyIGZpbmRVbmNhdWdodEZyb3plbiA9IGZ1bmN0aW9uKHN0b3JlLCBrZXkpe1xuICByZXR1cm4gYXJyYXlGaW5kKHN0b3JlLmEsIGZ1bmN0aW9uKGl0KXtcbiAgICByZXR1cm4gaXRbMF0gPT09IGtleTtcbiAgfSk7XG59O1xuVW5jYXVnaHRGcm96ZW5TdG9yZS5wcm90b3R5cGUgPSB7XG4gIGdldDogZnVuY3Rpb24oa2V5KXtcbiAgICB2YXIgZW50cnkgPSBmaW5kVW5jYXVnaHRGcm96ZW4odGhpcywga2V5KTtcbiAgICBpZihlbnRyeSlyZXR1cm4gZW50cnlbMV07XG4gIH0sXG4gIGhhczogZnVuY3Rpb24oa2V5KXtcbiAgICByZXR1cm4gISFmaW5kVW5jYXVnaHRGcm96ZW4odGhpcywga2V5KTtcbiAgfSxcbiAgc2V0OiBmdW5jdGlvbihrZXksIHZhbHVlKXtcbiAgICB2YXIgZW50cnkgPSBmaW5kVW5jYXVnaHRGcm96ZW4odGhpcywga2V5KTtcbiAgICBpZihlbnRyeSllbnRyeVsxXSA9IHZhbHVlO1xuICAgIGVsc2UgdGhpcy5hLnB1c2goW2tleSwgdmFsdWVdKTtcbiAgfSxcbiAgJ2RlbGV0ZSc6IGZ1bmN0aW9uKGtleSl7XG4gICAgdmFyIGluZGV4ID0gYXJyYXlGaW5kSW5kZXgodGhpcy5hLCBmdW5jdGlvbihpdCl7XG4gICAgICByZXR1cm4gaXRbMF0gPT09IGtleTtcbiAgICB9KTtcbiAgICBpZih+aW5kZXgpdGhpcy5hLnNwbGljZShpbmRleCwgMSk7XG4gICAgcmV0dXJuICEhfmluZGV4O1xuICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgZ2V0Q29uc3RydWN0b3I6IGZ1bmN0aW9uKHdyYXBwZXIsIE5BTUUsIElTX01BUCwgQURERVIpe1xuICAgIHZhciBDID0gd3JhcHBlcihmdW5jdGlvbih0aGF0LCBpdGVyYWJsZSl7XG4gICAgICBhbkluc3RhbmNlKHRoYXQsIEMsIE5BTUUsICdfaScpO1xuICAgICAgdGhhdC5faSA9IGlkKys7ICAgICAgLy8gY29sbGVjdGlvbiBpZFxuICAgICAgdGhhdC5fbCA9IHVuZGVmaW5lZDsgLy8gbGVhayBzdG9yZSBmb3IgdW5jYXVnaHQgZnJvemVuIG9iamVjdHNcbiAgICAgIGlmKGl0ZXJhYmxlICE9IHVuZGVmaW5lZClmb3JPZihpdGVyYWJsZSwgSVNfTUFQLCB0aGF0W0FEREVSXSwgdGhhdCk7XG4gICAgfSk7XG4gICAgcmVkZWZpbmVBbGwoQy5wcm90b3R5cGUsIHtcbiAgICAgIC8vIDIzLjMuMy4yIFdlYWtNYXAucHJvdG90eXBlLmRlbGV0ZShrZXkpXG4gICAgICAvLyAyMy40LjMuMyBXZWFrU2V0LnByb3RvdHlwZS5kZWxldGUodmFsdWUpXG4gICAgICAnZGVsZXRlJzogZnVuY3Rpb24oa2V5KXtcbiAgICAgICAgaWYoIWlzT2JqZWN0KGtleSkpcmV0dXJuIGZhbHNlO1xuICAgICAgICB2YXIgZGF0YSA9IGdldFdlYWsoa2V5KTtcbiAgICAgICAgaWYoZGF0YSA9PT0gdHJ1ZSlyZXR1cm4gdW5jYXVnaHRGcm96ZW5TdG9yZSh0aGlzKVsnZGVsZXRlJ10oa2V5KTtcbiAgICAgICAgcmV0dXJuIGRhdGEgJiYgJGhhcyhkYXRhLCB0aGlzLl9pKSAmJiBkZWxldGUgZGF0YVt0aGlzLl9pXTtcbiAgICAgIH0sXG4gICAgICAvLyAyMy4zLjMuNCBXZWFrTWFwLnByb3RvdHlwZS5oYXMoa2V5KVxuICAgICAgLy8gMjMuNC4zLjQgV2Vha1NldC5wcm90b3R5cGUuaGFzKHZhbHVlKVxuICAgICAgaGFzOiBmdW5jdGlvbiBoYXMoa2V5KXtcbiAgICAgICAgaWYoIWlzT2JqZWN0KGtleSkpcmV0dXJuIGZhbHNlO1xuICAgICAgICB2YXIgZGF0YSA9IGdldFdlYWsoa2V5KTtcbiAgICAgICAgaWYoZGF0YSA9PT0gdHJ1ZSlyZXR1cm4gdW5jYXVnaHRGcm96ZW5TdG9yZSh0aGlzKS5oYXMoa2V5KTtcbiAgICAgICAgcmV0dXJuIGRhdGEgJiYgJGhhcyhkYXRhLCB0aGlzLl9pKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gQztcbiAgfSxcbiAgZGVmOiBmdW5jdGlvbih0aGF0LCBrZXksIHZhbHVlKXtcbiAgICB2YXIgZGF0YSA9IGdldFdlYWsoYW5PYmplY3Qoa2V5KSwgdHJ1ZSk7XG4gICAgaWYoZGF0YSA9PT0gdHJ1ZSl1bmNhdWdodEZyb3plblN0b3JlKHRoYXQpLnNldChrZXksIHZhbHVlKTtcbiAgICBlbHNlIGRhdGFbdGhhdC5faV0gPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhhdDtcbiAgfSxcbiAgdWZzdG9yZTogdW5jYXVnaHRGcm96ZW5TdG9yZVxufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2NvbGxlY3Rpb24td2Vhay5qc1xuLy8gbW9kdWxlIGlkID0gMTcwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIid1c2Ugc3RyaWN0JztcbnZhciAkZGVmaW5lUHJvcGVydHkgPSByZXF1aXJlKCcuL19vYmplY3QtZHAnKVxuICAsIGNyZWF0ZURlc2MgICAgICA9IHJlcXVpcmUoJy4vX3Byb3BlcnR5LWRlc2MnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihvYmplY3QsIGluZGV4LCB2YWx1ZSl7XG4gIGlmKGluZGV4IGluIG9iamVjdCkkZGVmaW5lUHJvcGVydHkuZihvYmplY3QsIGluZGV4LCBjcmVhdGVEZXNjKDAsIHZhbHVlKSk7XG4gIGVsc2Ugb2JqZWN0W2luZGV4XSA9IHZhbHVlO1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2NyZWF0ZS1wcm9wZXJ0eS5qc1xuLy8gbW9kdWxlIGlkID0gMTcxXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIGFsbCBlbnVtZXJhYmxlIG9iamVjdCBrZXlzLCBpbmNsdWRlcyBzeW1ib2xzXG52YXIgZ2V0S2V5cyA9IHJlcXVpcmUoJy4vX29iamVjdC1rZXlzJylcbiAgLCBnT1BTICAgID0gcmVxdWlyZSgnLi9fb2JqZWN0LWdvcHMnKVxuICAsIHBJRSAgICAgPSByZXF1aXJlKCcuL19vYmplY3QtcGllJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGl0KXtcbiAgdmFyIHJlc3VsdCAgICAgPSBnZXRLZXlzKGl0KVxuICAgICwgZ2V0U3ltYm9scyA9IGdPUFMuZjtcbiAgaWYoZ2V0U3ltYm9scyl7XG4gICAgdmFyIHN5bWJvbHMgPSBnZXRTeW1ib2xzKGl0KVxuICAgICAgLCBpc0VudW0gID0gcElFLmZcbiAgICAgICwgaSAgICAgICA9IDBcbiAgICAgICwga2V5O1xuICAgIHdoaWxlKHN5bWJvbHMubGVuZ3RoID4gaSlpZihpc0VudW0uY2FsbChpdCwga2V5ID0gc3ltYm9sc1tpKytdKSlyZXN1bHQucHVzaChrZXkpO1xuICB9IHJldHVybiByZXN1bHQ7XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fZW51bS1rZXlzLmpzXG4vLyBtb2R1bGUgaWQgPSAxNzJcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8gZmFzdCBhcHBseSwgaHR0cDovL2pzcGVyZi5sbmtpdC5jb20vZmFzdC1hcHBseS81XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGZuLCBhcmdzLCB0aGF0KXtcbiAgdmFyIHVuID0gdGhhdCA9PT0gdW5kZWZpbmVkO1xuICBzd2l0Y2goYXJncy5sZW5ndGgpe1xuICAgIGNhc2UgMDogcmV0dXJuIHVuID8gZm4oKVxuICAgICAgICAgICAgICAgICAgICAgIDogZm4uY2FsbCh0aGF0KTtcbiAgICBjYXNlIDE6IHJldHVybiB1biA/IGZuKGFyZ3NbMF0pXG4gICAgICAgICAgICAgICAgICAgICAgOiBmbi5jYWxsKHRoYXQsIGFyZ3NbMF0pO1xuICAgIGNhc2UgMjogcmV0dXJuIHVuID8gZm4oYXJnc1swXSwgYXJnc1sxXSlcbiAgICAgICAgICAgICAgICAgICAgICA6IGZuLmNhbGwodGhhdCwgYXJnc1swXSwgYXJnc1sxXSk7XG4gICAgY2FzZSAzOiByZXR1cm4gdW4gPyBmbihhcmdzWzBdLCBhcmdzWzFdLCBhcmdzWzJdKVxuICAgICAgICAgICAgICAgICAgICAgIDogZm4uY2FsbCh0aGF0LCBhcmdzWzBdLCBhcmdzWzFdLCBhcmdzWzJdKTtcbiAgICBjYXNlIDQ6IHJldHVybiB1biA/IGZuKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0sIGFyZ3NbM10pXG4gICAgICAgICAgICAgICAgICAgICAgOiBmbi5jYWxsKHRoYXQsIGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0sIGFyZ3NbM10pO1xuICB9IHJldHVybiAgICAgICAgICAgICAgZm4uYXBwbHkodGhhdCwgYXJncyk7XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9faW52b2tlLmpzXG4vLyBtb2R1bGUgaWQgPSAxNzNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiJ3VzZSBzdHJpY3QnO1xudmFyIGNyZWF0ZSAgICAgICAgID0gcmVxdWlyZSgnLi9fb2JqZWN0LWNyZWF0ZScpXG4gICwgZGVzY3JpcHRvciAgICAgPSByZXF1aXJlKCcuL19wcm9wZXJ0eS1kZXNjJylcbiAgLCBzZXRUb1N0cmluZ1RhZyA9IHJlcXVpcmUoJy4vX3NldC10by1zdHJpbmctdGFnJylcbiAgLCBJdGVyYXRvclByb3RvdHlwZSA9IHt9O1xuXG4vLyAyNS4xLjIuMS4xICVJdGVyYXRvclByb3RvdHlwZSVbQEBpdGVyYXRvcl0oKVxucmVxdWlyZSgnLi9faGlkZScpKEl0ZXJhdG9yUHJvdG90eXBlLCByZXF1aXJlKCcuL193a3MnKSgnaXRlcmF0b3InKSwgZnVuY3Rpb24oKXsgcmV0dXJuIHRoaXM7IH0pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKENvbnN0cnVjdG9yLCBOQU1FLCBuZXh0KXtcbiAgQ29uc3RydWN0b3IucHJvdG90eXBlID0gY3JlYXRlKEl0ZXJhdG9yUHJvdG90eXBlLCB7bmV4dDogZGVzY3JpcHRvcigxLCBuZXh0KX0pO1xuICBzZXRUb1N0cmluZ1RhZyhDb25zdHJ1Y3RvciwgTkFNRSArICcgSXRlcmF0b3InKTtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pdGVyLWNyZWF0ZS5qc1xuLy8gbW9kdWxlIGlkID0gMTc0XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsInZhciBnZXRLZXlzICAgPSByZXF1aXJlKCcuL19vYmplY3Qta2V5cycpXG4gICwgdG9JT2JqZWN0ID0gcmVxdWlyZSgnLi9fdG8taW9iamVjdCcpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihvYmplY3QsIGVsKXtcbiAgdmFyIE8gICAgICA9IHRvSU9iamVjdChvYmplY3QpXG4gICAgLCBrZXlzICAgPSBnZXRLZXlzKE8pXG4gICAgLCBsZW5ndGggPSBrZXlzLmxlbmd0aFxuICAgICwgaW5kZXggID0gMFxuICAgICwga2V5O1xuICB3aGlsZShsZW5ndGggPiBpbmRleClpZihPW2tleSA9IGtleXNbaW5kZXgrK11dID09PSBlbClyZXR1cm4ga2V5O1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2tleW9mLmpzXG4vLyBtb2R1bGUgaWQgPSAxNzVcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwidmFyIGdsb2JhbCAgICA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpXG4gICwgbWFjcm90YXNrID0gcmVxdWlyZSgnLi9fdGFzaycpLnNldFxuICAsIE9ic2VydmVyICA9IGdsb2JhbC5NdXRhdGlvbk9ic2VydmVyIHx8IGdsb2JhbC5XZWJLaXRNdXRhdGlvbk9ic2VydmVyXG4gICwgcHJvY2VzcyAgID0gZ2xvYmFsLnByb2Nlc3NcbiAgLCBQcm9taXNlICAgPSBnbG9iYWwuUHJvbWlzZVxuICAsIGlzTm9kZSAgICA9IHJlcXVpcmUoJy4vX2NvZicpKHByb2Nlc3MpID09ICdwcm9jZXNzJztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbigpe1xuICB2YXIgaGVhZCwgbGFzdCwgbm90aWZ5O1xuXG4gIHZhciBmbHVzaCA9IGZ1bmN0aW9uKCl7XG4gICAgdmFyIHBhcmVudCwgZm47XG4gICAgaWYoaXNOb2RlICYmIChwYXJlbnQgPSBwcm9jZXNzLmRvbWFpbikpcGFyZW50LmV4aXQoKTtcbiAgICB3aGlsZShoZWFkKXtcbiAgICAgIGZuICAgPSBoZWFkLmZuO1xuICAgICAgaGVhZCA9IGhlYWQubmV4dDtcbiAgICAgIHRyeSB7XG4gICAgICAgIGZuKCk7XG4gICAgICB9IGNhdGNoKGUpe1xuICAgICAgICBpZihoZWFkKW5vdGlmeSgpO1xuICAgICAgICBlbHNlIGxhc3QgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfSBsYXN0ID0gdW5kZWZpbmVkO1xuICAgIGlmKHBhcmVudClwYXJlbnQuZW50ZXIoKTtcbiAgfTtcblxuICAvLyBOb2RlLmpzXG4gIGlmKGlzTm9kZSl7XG4gICAgbm90aWZ5ID0gZnVuY3Rpb24oKXtcbiAgICAgIHByb2Nlc3MubmV4dFRpY2soZmx1c2gpO1xuICAgIH07XG4gIC8vIGJyb3dzZXJzIHdpdGggTXV0YXRpb25PYnNlcnZlclxuICB9IGVsc2UgaWYoT2JzZXJ2ZXIpe1xuICAgIHZhciB0b2dnbGUgPSB0cnVlXG4gICAgICAsIG5vZGUgICA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKCcnKTtcbiAgICBuZXcgT2JzZXJ2ZXIoZmx1c2gpLm9ic2VydmUobm9kZSwge2NoYXJhY3RlckRhdGE6IHRydWV9KTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1uZXdcbiAgICBub3RpZnkgPSBmdW5jdGlvbigpe1xuICAgICAgbm9kZS5kYXRhID0gdG9nZ2xlID0gIXRvZ2dsZTtcbiAgICB9O1xuICAvLyBlbnZpcm9ubWVudHMgd2l0aCBtYXliZSBub24tY29tcGxldGVseSBjb3JyZWN0LCBidXQgZXhpc3RlbnQgUHJvbWlzZVxuICB9IGVsc2UgaWYoUHJvbWlzZSAmJiBQcm9taXNlLnJlc29sdmUpe1xuICAgIHZhciBwcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgbm90aWZ5ID0gZnVuY3Rpb24oKXtcbiAgICAgIHByb21pc2UudGhlbihmbHVzaCk7XG4gICAgfTtcbiAgLy8gZm9yIG90aGVyIGVudmlyb25tZW50cyAtIG1hY3JvdGFzayBiYXNlZCBvbjpcbiAgLy8gLSBzZXRJbW1lZGlhdGVcbiAgLy8gLSBNZXNzYWdlQ2hhbm5lbFxuICAvLyAtIHdpbmRvdy5wb3N0TWVzc2FnXG4gIC8vIC0gb25yZWFkeXN0YXRlY2hhbmdlXG4gIC8vIC0gc2V0VGltZW91dFxuICB9IGVsc2Uge1xuICAgIG5vdGlmeSA9IGZ1bmN0aW9uKCl7XG4gICAgICAvLyBzdHJhbmdlIElFICsgd2VicGFjayBkZXYgc2VydmVyIGJ1ZyAtIHVzZSAuY2FsbChnbG9iYWwpXG4gICAgICBtYWNyb3Rhc2suY2FsbChnbG9iYWwsIGZsdXNoKTtcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uKGZuKXtcbiAgICB2YXIgdGFzayA9IHtmbjogZm4sIG5leHQ6IHVuZGVmaW5lZH07XG4gICAgaWYobGFzdClsYXN0Lm5leHQgPSB0YXNrO1xuICAgIGlmKCFoZWFkKXtcbiAgICAgIGhlYWQgPSB0YXNrO1xuICAgICAgbm90aWZ5KCk7XG4gICAgfSBsYXN0ID0gdGFzaztcbiAgfTtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19taWNyb3Rhc2suanNcbi8vIG1vZHVsZSBpZCA9IDE3NlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJ2YXIgZFAgICAgICAgPSByZXF1aXJlKCcuL19vYmplY3QtZHAnKVxuICAsIGFuT2JqZWN0ID0gcmVxdWlyZSgnLi9fYW4tb2JqZWN0JylcbiAgLCBnZXRLZXlzICA9IHJlcXVpcmUoJy4vX29iamVjdC1rZXlzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9fZGVzY3JpcHRvcnMnKSA/IE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzIDogZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyhPLCBQcm9wZXJ0aWVzKXtcbiAgYW5PYmplY3QoTyk7XG4gIHZhciBrZXlzICAgPSBnZXRLZXlzKFByb3BlcnRpZXMpXG4gICAgLCBsZW5ndGggPSBrZXlzLmxlbmd0aFxuICAgICwgaSA9IDBcbiAgICAsIFA7XG4gIHdoaWxlKGxlbmd0aCA+IGkpZFAuZihPLCBQID0ga2V5c1tpKytdLCBQcm9wZXJ0aWVzW1BdKTtcbiAgcmV0dXJuIE87XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LWRwcy5qc1xuLy8gbW9kdWxlIGlkID0gMTc3XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIGZhbGxiYWNrIGZvciBJRTExIGJ1Z2d5IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzIHdpdGggaWZyYW1lIGFuZCB3aW5kb3dcbnZhciB0b0lPYmplY3QgPSByZXF1aXJlKCcuL190by1pb2JqZWN0JylcbiAgLCBnT1BOICAgICAgPSByZXF1aXJlKCcuL19vYmplY3QtZ29wbicpLmZcbiAgLCB0b1N0cmluZyAgPSB7fS50b1N0cmluZztcblxudmFyIHdpbmRvd05hbWVzID0gdHlwZW9mIHdpbmRvdyA9PSAnb2JqZWN0JyAmJiB3aW5kb3cgJiYgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXNcbiAgPyBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh3aW5kb3cpIDogW107XG5cbnZhciBnZXRXaW5kb3dOYW1lcyA9IGZ1bmN0aW9uKGl0KXtcbiAgdHJ5IHtcbiAgICByZXR1cm4gZ09QTihpdCk7XG4gIH0gY2F0Y2goZSl7XG4gICAgcmV0dXJuIHdpbmRvd05hbWVzLnNsaWNlKCk7XG4gIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzLmYgPSBmdW5jdGlvbiBnZXRPd25Qcm9wZXJ0eU5hbWVzKGl0KXtcbiAgcmV0dXJuIHdpbmRvd05hbWVzICYmIHRvU3RyaW5nLmNhbGwoaXQpID09ICdbb2JqZWN0IFdpbmRvd10nID8gZ2V0V2luZG93TmFtZXMoaXQpIDogZ09QTih0b0lPYmplY3QoaXQpKTtcbn07XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX29iamVjdC1nb3BuLWV4dC5qc1xuLy8gbW9kdWxlIGlkID0gMTc4XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIFdvcmtzIHdpdGggX19wcm90b19fIG9ubHkuIE9sZCB2OCBjYW4ndCB3b3JrIHdpdGggbnVsbCBwcm90byBvYmplY3RzLlxuLyogZXNsaW50LWRpc2FibGUgbm8tcHJvdG8gKi9cbnZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpXG4gICwgYW5PYmplY3QgPSByZXF1aXJlKCcuL19hbi1vYmplY3QnKTtcbnZhciBjaGVjayA9IGZ1bmN0aW9uKE8sIHByb3RvKXtcbiAgYW5PYmplY3QoTyk7XG4gIGlmKCFpc09iamVjdChwcm90bykgJiYgcHJvdG8gIT09IG51bGwpdGhyb3cgVHlwZUVycm9yKHByb3RvICsgXCI6IGNhbid0IHNldCBhcyBwcm90b3R5cGUhXCIpO1xufTtcbm1vZHVsZS5leHBvcnRzID0ge1xuICBzZXQ6IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCAoJ19fcHJvdG9fXycgaW4ge30gPyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG4gICAgZnVuY3Rpb24odGVzdCwgYnVnZ3ksIHNldCl7XG4gICAgICB0cnkge1xuICAgICAgICBzZXQgPSByZXF1aXJlKCcuL19jdHgnKShGdW5jdGlvbi5jYWxsLCByZXF1aXJlKCcuL19vYmplY3QtZ29wZCcpLmYoT2JqZWN0LnByb3RvdHlwZSwgJ19fcHJvdG9fXycpLnNldCwgMik7XG4gICAgICAgIHNldCh0ZXN0LCBbXSk7XG4gICAgICAgIGJ1Z2d5ID0gISh0ZXN0IGluc3RhbmNlb2YgQXJyYXkpO1xuICAgICAgfSBjYXRjaChlKXsgYnVnZ3kgPSB0cnVlOyB9XG4gICAgICByZXR1cm4gZnVuY3Rpb24gc2V0UHJvdG90eXBlT2YoTywgcHJvdG8pe1xuICAgICAgICBjaGVjayhPLCBwcm90byk7XG4gICAgICAgIGlmKGJ1Z2d5KU8uX19wcm90b19fID0gcHJvdG87XG4gICAgICAgIGVsc2Ugc2V0KE8sIHByb3RvKTtcbiAgICAgICAgcmV0dXJuIE87XG4gICAgICB9O1xuICAgIH0oe30sIGZhbHNlKSA6IHVuZGVmaW5lZCksXG4gIGNoZWNrOiBjaGVja1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3NldC1wcm90by5qc1xuLy8gbW9kdWxlIGlkID0gMTc5XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIDcuMy4yMCBTcGVjaWVzQ29uc3RydWN0b3IoTywgZGVmYXVsdENvbnN0cnVjdG9yKVxudmFyIGFuT2JqZWN0ICA9IHJlcXVpcmUoJy4vX2FuLW9iamVjdCcpXG4gICwgYUZ1bmN0aW9uID0gcmVxdWlyZSgnLi9fYS1mdW5jdGlvbicpXG4gICwgU1BFQ0lFUyAgID0gcmVxdWlyZSgnLi9fd2tzJykoJ3NwZWNpZXMnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oTywgRCl7XG4gIHZhciBDID0gYW5PYmplY3QoTykuY29uc3RydWN0b3IsIFM7XG4gIHJldHVybiBDID09PSB1bmRlZmluZWQgfHwgKFMgPSBhbk9iamVjdChDKVtTUEVDSUVTXSkgPT0gdW5kZWZpbmVkID8gRCA6IGFGdW5jdGlvbihTKTtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19zcGVjaWVzLWNvbnN0cnVjdG9yLmpzXG4vLyBtb2R1bGUgaWQgPSAxODBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwidmFyIHRvSW50ZWdlciA9IHJlcXVpcmUoJy4vX3RvLWludGVnZXInKVxuICAsIGRlZmluZWQgICA9IHJlcXVpcmUoJy4vX2RlZmluZWQnKTtcbi8vIHRydWUgIC0+IFN0cmluZyNhdFxuLy8gZmFsc2UgLT4gU3RyaW5nI2NvZGVQb2ludEF0XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKFRPX1NUUklORyl7XG4gIHJldHVybiBmdW5jdGlvbih0aGF0LCBwb3Mpe1xuICAgIHZhciBzID0gU3RyaW5nKGRlZmluZWQodGhhdCkpXG4gICAgICAsIGkgPSB0b0ludGVnZXIocG9zKVxuICAgICAgLCBsID0gcy5sZW5ndGhcbiAgICAgICwgYSwgYjtcbiAgICBpZihpIDwgMCB8fCBpID49IGwpcmV0dXJuIFRPX1NUUklORyA/ICcnIDogdW5kZWZpbmVkO1xuICAgIGEgPSBzLmNoYXJDb2RlQXQoaSk7XG4gICAgcmV0dXJuIGEgPCAweGQ4MDAgfHwgYSA+IDB4ZGJmZiB8fCBpICsgMSA9PT0gbCB8fCAoYiA9IHMuY2hhckNvZGVBdChpICsgMSkpIDwgMHhkYzAwIHx8IGIgPiAweGRmZmZcbiAgICAgID8gVE9fU1RSSU5HID8gcy5jaGFyQXQoaSkgOiBhXG4gICAgICA6IFRPX1NUUklORyA/IHMuc2xpY2UoaSwgaSArIDIpIDogKGEgLSAweGQ4MDAgPDwgMTApICsgKGIgLSAweGRjMDApICsgMHgxMDAwMDtcbiAgfTtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19zdHJpbmctYXQuanNcbi8vIG1vZHVsZSBpZCA9IDE4MVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJ2YXIgdG9JbnRlZ2VyID0gcmVxdWlyZSgnLi9fdG8taW50ZWdlcicpXG4gICwgbWF4ICAgICAgID0gTWF0aC5tYXhcbiAgLCBtaW4gICAgICAgPSBNYXRoLm1pbjtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaW5kZXgsIGxlbmd0aCl7XG4gIGluZGV4ID0gdG9JbnRlZ2VyKGluZGV4KTtcbiAgcmV0dXJuIGluZGV4IDwgMCA/IG1heChpbmRleCArIGxlbmd0aCwgMCkgOiBtaW4oaW5kZXgsIGxlbmd0aCk7XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fdG8taW5kZXguanNcbi8vIG1vZHVsZSBpZCA9IDE4MlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJ2YXIgYW5PYmplY3QgPSByZXF1aXJlKCcuL19hbi1vYmplY3QnKVxuICAsIGdldCAgICAgID0gcmVxdWlyZSgnLi9jb3JlLmdldC1pdGVyYXRvci1tZXRob2QnKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9fY29yZScpLmdldEl0ZXJhdG9yID0gZnVuY3Rpb24oaXQpe1xuICB2YXIgaXRlckZuID0gZ2V0KGl0KTtcbiAgaWYodHlwZW9mIGl0ZXJGbiAhPSAnZnVuY3Rpb24nKXRocm93IFR5cGVFcnJvcihpdCArICcgaXMgbm90IGl0ZXJhYmxlIScpO1xuICByZXR1cm4gYW5PYmplY3QoaXRlckZuLmNhbGwoaXQpKTtcbn07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2NvcmUuZ2V0LWl0ZXJhdG9yLmpzXG4vLyBtb2R1bGUgaWQgPSAxODNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwidmFyIGNsYXNzb2YgICA9IHJlcXVpcmUoJy4vX2NsYXNzb2YnKVxuICAsIElURVJBVE9SICA9IHJlcXVpcmUoJy4vX3drcycpKCdpdGVyYXRvcicpXG4gICwgSXRlcmF0b3JzID0gcmVxdWlyZSgnLi9faXRlcmF0b3JzJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vX2NvcmUnKS5pc0l0ZXJhYmxlID0gZnVuY3Rpb24oaXQpe1xuICB2YXIgTyA9IE9iamVjdChpdCk7XG4gIHJldHVybiBPW0lURVJBVE9SXSAhPT0gdW5kZWZpbmVkXG4gICAgfHwgJ0BAaXRlcmF0b3InIGluIE9cbiAgICB8fCBJdGVyYXRvcnMuaGFzT3duUHJvcGVydHkoY2xhc3NvZihPKSk7XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9jb3JlLmlzLWl0ZXJhYmxlLmpzXG4vLyBtb2R1bGUgaWQgPSAxODRcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiJ3VzZSBzdHJpY3QnO1xudmFyIGN0eCAgICAgICAgICAgID0gcmVxdWlyZSgnLi9fY3R4JylcbiAgLCAkZXhwb3J0ICAgICAgICA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpXG4gICwgdG9PYmplY3QgICAgICAgPSByZXF1aXJlKCcuL190by1vYmplY3QnKVxuICAsIGNhbGwgICAgICAgICAgID0gcmVxdWlyZSgnLi9faXRlci1jYWxsJylcbiAgLCBpc0FycmF5SXRlciAgICA9IHJlcXVpcmUoJy4vX2lzLWFycmF5LWl0ZXInKVxuICAsIHRvTGVuZ3RoICAgICAgID0gcmVxdWlyZSgnLi9fdG8tbGVuZ3RoJylcbiAgLCBjcmVhdGVQcm9wZXJ0eSA9IHJlcXVpcmUoJy4vX2NyZWF0ZS1wcm9wZXJ0eScpXG4gICwgZ2V0SXRlckZuICAgICAgPSByZXF1aXJlKCcuL2NvcmUuZ2V0LWl0ZXJhdG9yLW1ldGhvZCcpO1xuXG4kZXhwb3J0KCRleHBvcnQuUyArICRleHBvcnQuRiAqICFyZXF1aXJlKCcuL19pdGVyLWRldGVjdCcpKGZ1bmN0aW9uKGl0ZXIpeyBBcnJheS5mcm9tKGl0ZXIpOyB9KSwgJ0FycmF5Jywge1xuICAvLyAyMi4xLjIuMSBBcnJheS5mcm9tKGFycmF5TGlrZSwgbWFwZm4gPSB1bmRlZmluZWQsIHRoaXNBcmcgPSB1bmRlZmluZWQpXG4gIGZyb206IGZ1bmN0aW9uIGZyb20oYXJyYXlMaWtlLyosIG1hcGZuID0gdW5kZWZpbmVkLCB0aGlzQXJnID0gdW5kZWZpbmVkKi8pe1xuICAgIHZhciBPICAgICAgID0gdG9PYmplY3QoYXJyYXlMaWtlKVxuICAgICAgLCBDICAgICAgID0gdHlwZW9mIHRoaXMgPT0gJ2Z1bmN0aW9uJyA/IHRoaXMgOiBBcnJheVxuICAgICAgLCBhTGVuICAgID0gYXJndW1lbnRzLmxlbmd0aFxuICAgICAgLCBtYXBmbiAgID0gYUxlbiA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWRcbiAgICAgICwgbWFwcGluZyA9IG1hcGZuICE9PSB1bmRlZmluZWRcbiAgICAgICwgaW5kZXggICA9IDBcbiAgICAgICwgaXRlckZuICA9IGdldEl0ZXJGbihPKVxuICAgICAgLCBsZW5ndGgsIHJlc3VsdCwgc3RlcCwgaXRlcmF0b3I7XG4gICAgaWYobWFwcGluZyltYXBmbiA9IGN0eChtYXBmbiwgYUxlbiA+IDIgPyBhcmd1bWVudHNbMl0gOiB1bmRlZmluZWQsIDIpO1xuICAgIC8vIGlmIG9iamVjdCBpc24ndCBpdGVyYWJsZSBvciBpdCdzIGFycmF5IHdpdGggZGVmYXVsdCBpdGVyYXRvciAtIHVzZSBzaW1wbGUgY2FzZVxuICAgIGlmKGl0ZXJGbiAhPSB1bmRlZmluZWQgJiYgIShDID09IEFycmF5ICYmIGlzQXJyYXlJdGVyKGl0ZXJGbikpKXtcbiAgICAgIGZvcihpdGVyYXRvciA9IGl0ZXJGbi5jYWxsKE8pLCByZXN1bHQgPSBuZXcgQzsgIShzdGVwID0gaXRlcmF0b3IubmV4dCgpKS5kb25lOyBpbmRleCsrKXtcbiAgICAgICAgY3JlYXRlUHJvcGVydHkocmVzdWx0LCBpbmRleCwgbWFwcGluZyA/IGNhbGwoaXRlcmF0b3IsIG1hcGZuLCBbc3RlcC52YWx1ZSwgaW5kZXhdLCB0cnVlKSA6IHN0ZXAudmFsdWUpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBsZW5ndGggPSB0b0xlbmd0aChPLmxlbmd0aCk7XG4gICAgICBmb3IocmVzdWx0ID0gbmV3IEMobGVuZ3RoKTsgbGVuZ3RoID4gaW5kZXg7IGluZGV4Kyspe1xuICAgICAgICBjcmVhdGVQcm9wZXJ0eShyZXN1bHQsIGluZGV4LCBtYXBwaW5nID8gbWFwZm4oT1tpbmRleF0sIGluZGV4KSA6IE9baW5kZXhdKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmVzdWx0Lmxlbmd0aCA9IGluZGV4O1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn0pO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5hcnJheS5mcm9tLmpzXG4vLyBtb2R1bGUgaWQgPSAxODVcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiJ3VzZSBzdHJpY3QnO1xudmFyIGFkZFRvVW5zY29wYWJsZXMgPSByZXF1aXJlKCcuL19hZGQtdG8tdW5zY29wYWJsZXMnKVxuICAsIHN0ZXAgICAgICAgICAgICAgPSByZXF1aXJlKCcuL19pdGVyLXN0ZXAnKVxuICAsIEl0ZXJhdG9ycyAgICAgICAgPSByZXF1aXJlKCcuL19pdGVyYXRvcnMnKVxuICAsIHRvSU9iamVjdCAgICAgICAgPSByZXF1aXJlKCcuL190by1pb2JqZWN0Jyk7XG5cbi8vIDIyLjEuMy40IEFycmF5LnByb3RvdHlwZS5lbnRyaWVzKClcbi8vIDIyLjEuMy4xMyBBcnJheS5wcm90b3R5cGUua2V5cygpXG4vLyAyMi4xLjMuMjkgQXJyYXkucHJvdG90eXBlLnZhbHVlcygpXG4vLyAyMi4xLjMuMzAgQXJyYXkucHJvdG90eXBlW0BAaXRlcmF0b3JdKClcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9faXRlci1kZWZpbmUnKShBcnJheSwgJ0FycmF5JywgZnVuY3Rpb24oaXRlcmF0ZWQsIGtpbmQpe1xuICB0aGlzLl90ID0gdG9JT2JqZWN0KGl0ZXJhdGVkKTsgLy8gdGFyZ2V0XG4gIHRoaXMuX2kgPSAwOyAgICAgICAgICAgICAgICAgICAvLyBuZXh0IGluZGV4XG4gIHRoaXMuX2sgPSBraW5kOyAgICAgICAgICAgICAgICAvLyBraW5kXG4vLyAyMi4xLjUuMi4xICVBcnJheUl0ZXJhdG9yUHJvdG90eXBlJS5uZXh0KClcbn0sIGZ1bmN0aW9uKCl7XG4gIHZhciBPICAgICA9IHRoaXMuX3RcbiAgICAsIGtpbmQgID0gdGhpcy5fa1xuICAgICwgaW5kZXggPSB0aGlzLl9pKys7XG4gIGlmKCFPIHx8IGluZGV4ID49IE8ubGVuZ3RoKXtcbiAgICB0aGlzLl90ID0gdW5kZWZpbmVkO1xuICAgIHJldHVybiBzdGVwKDEpO1xuICB9XG4gIGlmKGtpbmQgPT0gJ2tleXMnICApcmV0dXJuIHN0ZXAoMCwgaW5kZXgpO1xuICBpZihraW5kID09ICd2YWx1ZXMnKXJldHVybiBzdGVwKDAsIE9baW5kZXhdKTtcbiAgcmV0dXJuIHN0ZXAoMCwgW2luZGV4LCBPW2luZGV4XV0pO1xufSwgJ3ZhbHVlcycpO1xuXG4vLyBhcmd1bWVudHNMaXN0W0BAaXRlcmF0b3JdIGlzICVBcnJheVByb3RvX3ZhbHVlcyUgKDkuNC40LjYsIDkuNC40LjcpXG5JdGVyYXRvcnMuQXJndW1lbnRzID0gSXRlcmF0b3JzLkFycmF5O1xuXG5hZGRUb1Vuc2NvcGFibGVzKCdrZXlzJyk7XG5hZGRUb1Vuc2NvcGFibGVzKCd2YWx1ZXMnKTtcbmFkZFRvVW5zY29wYWJsZXMoJ2VudHJpZXMnKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2LmFycmF5Lml0ZXJhdG9yLmpzXG4vLyBtb2R1bGUgaWQgPSAxODZcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiJ3VzZSBzdHJpY3QnO1xudmFyIHN0cm9uZyA9IHJlcXVpcmUoJy4vX2NvbGxlY3Rpb24tc3Ryb25nJyk7XG5cbi8vIDIzLjEgTWFwIE9iamVjdHNcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9fY29sbGVjdGlvbicpKCdNYXAnLCBmdW5jdGlvbihnZXQpe1xuICByZXR1cm4gZnVuY3Rpb24gTWFwKCl7IHJldHVybiBnZXQodGhpcywgYXJndW1lbnRzLmxlbmd0aCA+IDAgPyBhcmd1bWVudHNbMF0gOiB1bmRlZmluZWQpOyB9O1xufSwge1xuICAvLyAyMy4xLjMuNiBNYXAucHJvdG90eXBlLmdldChrZXkpXG4gIGdldDogZnVuY3Rpb24gZ2V0KGtleSl7XG4gICAgdmFyIGVudHJ5ID0gc3Ryb25nLmdldEVudHJ5KHRoaXMsIGtleSk7XG4gICAgcmV0dXJuIGVudHJ5ICYmIGVudHJ5LnY7XG4gIH0sXG4gIC8vIDIzLjEuMy45IE1hcC5wcm90b3R5cGUuc2V0KGtleSwgdmFsdWUpXG4gIHNldDogZnVuY3Rpb24gc2V0KGtleSwgdmFsdWUpe1xuICAgIHJldHVybiBzdHJvbmcuZGVmKHRoaXMsIGtleSA9PT0gMCA/IDAgOiBrZXksIHZhbHVlKTtcbiAgfVxufSwgc3Ryb25nLCB0cnVlKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2Lm1hcC5qc1xuLy8gbW9kdWxlIGlkID0gMTg3XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIDIwLjEuMi4yIE51bWJlci5pc0Zpbml0ZShudW1iZXIpXG52YXIgJGV4cG9ydCAgID0gcmVxdWlyZSgnLi9fZXhwb3J0JylcbiAgLCBfaXNGaW5pdGUgPSByZXF1aXJlKCcuL19nbG9iYWwnKS5pc0Zpbml0ZTtcblxuJGV4cG9ydCgkZXhwb3J0LlMsICdOdW1iZXInLCB7XG4gIGlzRmluaXRlOiBmdW5jdGlvbiBpc0Zpbml0ZShpdCl7XG4gICAgcmV0dXJuIHR5cGVvZiBpdCA9PSAnbnVtYmVyJyAmJiBfaXNGaW5pdGUoaXQpO1xuICB9XG59KTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2Lm51bWJlci5pcy1maW5pdGUuanNcbi8vIG1vZHVsZSBpZCA9IDE4OFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyAyMC4xLjIuNCBOdW1iZXIuaXNOYU4obnVtYmVyKVxudmFyICRleHBvcnQgPSByZXF1aXJlKCcuL19leHBvcnQnKTtcblxuJGV4cG9ydCgkZXhwb3J0LlMsICdOdW1iZXInLCB7XG4gIGlzTmFOOiBmdW5jdGlvbiBpc05hTihudW1iZXIpe1xuICAgIHJldHVybiBudW1iZXIgIT0gbnVtYmVyO1xuICB9XG59KTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2Lm51bWJlci5pcy1uYW4uanNcbi8vIG1vZHVsZSBpZCA9IDE4OVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyAxOS4xLjMuMSBPYmplY3QuYXNzaWduKHRhcmdldCwgc291cmNlKVxudmFyICRleHBvcnQgPSByZXF1aXJlKCcuL19leHBvcnQnKTtcblxuJGV4cG9ydCgkZXhwb3J0LlMgKyAkZXhwb3J0LkYsICdPYmplY3QnLCB7YXNzaWduOiByZXF1aXJlKCcuL19vYmplY3QtYXNzaWduJyl9KTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2Lm9iamVjdC5hc3NpZ24uanNcbi8vIG1vZHVsZSBpZCA9IDE5MFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJ2YXIgJGV4cG9ydCA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpXG4vLyAxOS4xLjIuMiAvIDE1LjIuMy41IE9iamVjdC5jcmVhdGUoTyBbLCBQcm9wZXJ0aWVzXSlcbiRleHBvcnQoJGV4cG9ydC5TLCAnT2JqZWN0Jywge2NyZWF0ZTogcmVxdWlyZSgnLi9fb2JqZWN0LWNyZWF0ZScpfSk7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5vYmplY3QuY3JlYXRlLmpzXG4vLyBtb2R1bGUgaWQgPSAxOTFcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwidmFyICRleHBvcnQgPSByZXF1aXJlKCcuL19leHBvcnQnKTtcbi8vIDE5LjEuMi40IC8gMTUuMi4zLjYgT2JqZWN0LmRlZmluZVByb3BlcnR5KE8sIFAsIEF0dHJpYnV0ZXMpXG4kZXhwb3J0KCRleHBvcnQuUyArICRleHBvcnQuRiAqICFyZXF1aXJlKCcuL19kZXNjcmlwdG9ycycpLCAnT2JqZWN0Jywge2RlZmluZVByb3BlcnR5OiByZXF1aXJlKCcuL19vYmplY3QtZHAnKS5mfSk7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5vYmplY3QuZGVmaW5lLXByb3BlcnR5LmpzXG4vLyBtb2R1bGUgaWQgPSAxOTJcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8gMTkuMS4yLjUgT2JqZWN0LmZyZWV6ZShPKVxudmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9faXMtb2JqZWN0JylcbiAgLCBtZXRhICAgICA9IHJlcXVpcmUoJy4vX21ldGEnKS5vbkZyZWV6ZTtcblxucmVxdWlyZSgnLi9fb2JqZWN0LXNhcCcpKCdmcmVlemUnLCBmdW5jdGlvbigkZnJlZXplKXtcbiAgcmV0dXJuIGZ1bmN0aW9uIGZyZWV6ZShpdCl7XG4gICAgcmV0dXJuICRmcmVlemUgJiYgaXNPYmplY3QoaXQpID8gJGZyZWV6ZShtZXRhKGl0KSkgOiBpdDtcbiAgfTtcbn0pO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYub2JqZWN0LmZyZWV6ZS5qc1xuLy8gbW9kdWxlIGlkID0gMTkzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIDE5LjEuMi42IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoTywgUClcbnZhciB0b0lPYmplY3QgICAgICAgICAgICAgICAgID0gcmVxdWlyZSgnLi9fdG8taW9iamVjdCcpXG4gICwgJGdldE93blByb3BlcnR5RGVzY3JpcHRvciA9IHJlcXVpcmUoJy4vX29iamVjdC1nb3BkJykuZjtcblxucmVxdWlyZSgnLi9fb2JqZWN0LXNhcCcpKCdnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3InLCBmdW5jdGlvbigpe1xuICByZXR1cm4gZnVuY3Rpb24gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKGl0LCBrZXkpe1xuICAgIHJldHVybiAkZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRvSU9iamVjdChpdCksIGtleSk7XG4gIH07XG59KTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2Lm9iamVjdC5nZXQtb3duLXByb3BlcnR5LWRlc2NyaXB0b3IuanNcbi8vIG1vZHVsZSBpZCA9IDE5NFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyAxOS4xLjIuOSBPYmplY3QuZ2V0UHJvdG90eXBlT2YoTylcbnZhciB0b09iamVjdCAgICAgICAgPSByZXF1aXJlKCcuL190by1vYmplY3QnKVxuICAsICRnZXRQcm90b3R5cGVPZiA9IHJlcXVpcmUoJy4vX29iamVjdC1ncG8nKTtcblxucmVxdWlyZSgnLi9fb2JqZWN0LXNhcCcpKCdnZXRQcm90b3R5cGVPZicsIGZ1bmN0aW9uKCl7XG4gIHJldHVybiBmdW5jdGlvbiBnZXRQcm90b3R5cGVPZihpdCl7XG4gICAgcmV0dXJuICRnZXRQcm90b3R5cGVPZih0b09iamVjdChpdCkpO1xuICB9O1xufSk7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5vYmplY3QuZ2V0LXByb3RvdHlwZS1vZi5qc1xuLy8gbW9kdWxlIGlkID0gMTk1XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIDE5LjEuMi4xNCBPYmplY3Qua2V5cyhPKVxudmFyIHRvT2JqZWN0ID0gcmVxdWlyZSgnLi9fdG8tb2JqZWN0JylcbiAgLCAka2V5cyAgICA9IHJlcXVpcmUoJy4vX29iamVjdC1rZXlzJyk7XG5cbnJlcXVpcmUoJy4vX29iamVjdC1zYXAnKSgna2V5cycsIGZ1bmN0aW9uKCl7XG4gIHJldHVybiBmdW5jdGlvbiBrZXlzKGl0KXtcbiAgICByZXR1cm4gJGtleXModG9PYmplY3QoaXQpKTtcbiAgfTtcbn0pO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYub2JqZWN0LmtleXMuanNcbi8vIG1vZHVsZSBpZCA9IDE5NlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyAxOS4xLjMuMTkgT2JqZWN0LnNldFByb3RvdHlwZU9mKE8sIHByb3RvKVxudmFyICRleHBvcnQgPSByZXF1aXJlKCcuL19leHBvcnQnKTtcbiRleHBvcnQoJGV4cG9ydC5TLCAnT2JqZWN0Jywge3NldFByb3RvdHlwZU9mOiByZXF1aXJlKCcuL19zZXQtcHJvdG8nKS5zZXR9KTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2Lm9iamVjdC5zZXQtcHJvdG90eXBlLW9mLmpzXG4vLyBtb2R1bGUgaWQgPSAxOTdcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiJ3VzZSBzdHJpY3QnO1xudmFyIExJQlJBUlkgICAgICAgICAgICA9IHJlcXVpcmUoJy4vX2xpYnJhcnknKVxuICAsIGdsb2JhbCAgICAgICAgICAgICA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpXG4gICwgY3R4ICAgICAgICAgICAgICAgID0gcmVxdWlyZSgnLi9fY3R4JylcbiAgLCBjbGFzc29mICAgICAgICAgICAgPSByZXF1aXJlKCcuL19jbGFzc29mJylcbiAgLCAkZXhwb3J0ICAgICAgICAgICAgPSByZXF1aXJlKCcuL19leHBvcnQnKVxuICAsIGlzT2JqZWN0ICAgICAgICAgICA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpXG4gICwgYUZ1bmN0aW9uICAgICAgICAgID0gcmVxdWlyZSgnLi9fYS1mdW5jdGlvbicpXG4gICwgYW5JbnN0YW5jZSAgICAgICAgID0gcmVxdWlyZSgnLi9fYW4taW5zdGFuY2UnKVxuICAsIGZvck9mICAgICAgICAgICAgICA9IHJlcXVpcmUoJy4vX2Zvci1vZicpXG4gICwgc3BlY2llc0NvbnN0cnVjdG9yID0gcmVxdWlyZSgnLi9fc3BlY2llcy1jb25zdHJ1Y3RvcicpXG4gICwgdGFzayAgICAgICAgICAgICAgID0gcmVxdWlyZSgnLi9fdGFzaycpLnNldFxuICAsIG1pY3JvdGFzayAgICAgICAgICA9IHJlcXVpcmUoJy4vX21pY3JvdGFzaycpKClcbiAgLCBQUk9NSVNFICAgICAgICAgICAgPSAnUHJvbWlzZSdcbiAgLCBUeXBlRXJyb3IgICAgICAgICAgPSBnbG9iYWwuVHlwZUVycm9yXG4gICwgcHJvY2VzcyAgICAgICAgICAgID0gZ2xvYmFsLnByb2Nlc3NcbiAgLCAkUHJvbWlzZSAgICAgICAgICAgPSBnbG9iYWxbUFJPTUlTRV1cbiAgLCBwcm9jZXNzICAgICAgICAgICAgPSBnbG9iYWwucHJvY2Vzc1xuICAsIGlzTm9kZSAgICAgICAgICAgICA9IGNsYXNzb2YocHJvY2VzcykgPT0gJ3Byb2Nlc3MnXG4gICwgZW1wdHkgICAgICAgICAgICAgID0gZnVuY3Rpb24oKXsgLyogZW1wdHkgKi8gfVxuICAsIEludGVybmFsLCBHZW5lcmljUHJvbWlzZUNhcGFiaWxpdHksIFdyYXBwZXI7XG5cbnZhciBVU0VfTkFUSVZFID0gISFmdW5jdGlvbigpe1xuICB0cnkge1xuICAgIC8vIGNvcnJlY3Qgc3ViY2xhc3Npbmcgd2l0aCBAQHNwZWNpZXMgc3VwcG9ydFxuICAgIHZhciBwcm9taXNlICAgICA9ICRQcm9taXNlLnJlc29sdmUoMSlcbiAgICAgICwgRmFrZVByb21pc2UgPSAocHJvbWlzZS5jb25zdHJ1Y3RvciA9IHt9KVtyZXF1aXJlKCcuL193a3MnKSgnc3BlY2llcycpXSA9IGZ1bmN0aW9uKGV4ZWMpeyBleGVjKGVtcHR5LCBlbXB0eSk7IH07XG4gICAgLy8gdW5oYW5kbGVkIHJlamVjdGlvbnMgdHJhY2tpbmcgc3VwcG9ydCwgTm9kZUpTIFByb21pc2Ugd2l0aG91dCBpdCBmYWlscyBAQHNwZWNpZXMgdGVzdFxuICAgIHJldHVybiAoaXNOb2RlIHx8IHR5cGVvZiBQcm9taXNlUmVqZWN0aW9uRXZlbnQgPT0gJ2Z1bmN0aW9uJykgJiYgcHJvbWlzZS50aGVuKGVtcHR5KSBpbnN0YW5jZW9mIEZha2VQcm9taXNlO1xuICB9IGNhdGNoKGUpeyAvKiBlbXB0eSAqLyB9XG59KCk7XG5cbi8vIGhlbHBlcnNcbnZhciBzYW1lQ29uc3RydWN0b3IgPSBmdW5jdGlvbihhLCBiKXtcbiAgLy8gd2l0aCBsaWJyYXJ5IHdyYXBwZXIgc3BlY2lhbCBjYXNlXG4gIHJldHVybiBhID09PSBiIHx8IGEgPT09ICRQcm9taXNlICYmIGIgPT09IFdyYXBwZXI7XG59O1xudmFyIGlzVGhlbmFibGUgPSBmdW5jdGlvbihpdCl7XG4gIHZhciB0aGVuO1xuICByZXR1cm4gaXNPYmplY3QoaXQpICYmIHR5cGVvZiAodGhlbiA9IGl0LnRoZW4pID09ICdmdW5jdGlvbicgPyB0aGVuIDogZmFsc2U7XG59O1xudmFyIG5ld1Byb21pc2VDYXBhYmlsaXR5ID0gZnVuY3Rpb24oQyl7XG4gIHJldHVybiBzYW1lQ29uc3RydWN0b3IoJFByb21pc2UsIEMpXG4gICAgPyBuZXcgUHJvbWlzZUNhcGFiaWxpdHkoQylcbiAgICA6IG5ldyBHZW5lcmljUHJvbWlzZUNhcGFiaWxpdHkoQyk7XG59O1xudmFyIFByb21pc2VDYXBhYmlsaXR5ID0gR2VuZXJpY1Byb21pc2VDYXBhYmlsaXR5ID0gZnVuY3Rpb24oQyl7XG4gIHZhciByZXNvbHZlLCByZWplY3Q7XG4gIHRoaXMucHJvbWlzZSA9IG5ldyBDKGZ1bmN0aW9uKCQkcmVzb2x2ZSwgJCRyZWplY3Qpe1xuICAgIGlmKHJlc29sdmUgIT09IHVuZGVmaW5lZCB8fCByZWplY3QgIT09IHVuZGVmaW5lZCl0aHJvdyBUeXBlRXJyb3IoJ0JhZCBQcm9taXNlIGNvbnN0cnVjdG9yJyk7XG4gICAgcmVzb2x2ZSA9ICQkcmVzb2x2ZTtcbiAgICByZWplY3QgID0gJCRyZWplY3Q7XG4gIH0pO1xuICB0aGlzLnJlc29sdmUgPSBhRnVuY3Rpb24ocmVzb2x2ZSk7XG4gIHRoaXMucmVqZWN0ICA9IGFGdW5jdGlvbihyZWplY3QpO1xufTtcbnZhciBwZXJmb3JtID0gZnVuY3Rpb24oZXhlYyl7XG4gIHRyeSB7XG4gICAgZXhlYygpO1xuICB9IGNhdGNoKGUpe1xuICAgIHJldHVybiB7ZXJyb3I6IGV9O1xuICB9XG59O1xudmFyIG5vdGlmeSA9IGZ1bmN0aW9uKHByb21pc2UsIGlzUmVqZWN0KXtcbiAgaWYocHJvbWlzZS5fbilyZXR1cm47XG4gIHByb21pc2UuX24gPSB0cnVlO1xuICB2YXIgY2hhaW4gPSBwcm9taXNlLl9jO1xuICBtaWNyb3Rhc2soZnVuY3Rpb24oKXtcbiAgICB2YXIgdmFsdWUgPSBwcm9taXNlLl92XG4gICAgICAsIG9rICAgID0gcHJvbWlzZS5fcyA9PSAxXG4gICAgICAsIGkgICAgID0gMDtcbiAgICB2YXIgcnVuID0gZnVuY3Rpb24ocmVhY3Rpb24pe1xuICAgICAgdmFyIGhhbmRsZXIgPSBvayA/IHJlYWN0aW9uLm9rIDogcmVhY3Rpb24uZmFpbFxuICAgICAgICAsIHJlc29sdmUgPSByZWFjdGlvbi5yZXNvbHZlXG4gICAgICAgICwgcmVqZWN0ICA9IHJlYWN0aW9uLnJlamVjdFxuICAgICAgICAsIGRvbWFpbiAgPSByZWFjdGlvbi5kb21haW5cbiAgICAgICAgLCByZXN1bHQsIHRoZW47XG4gICAgICB0cnkge1xuICAgICAgICBpZihoYW5kbGVyKXtcbiAgICAgICAgICBpZighb2spe1xuICAgICAgICAgICAgaWYocHJvbWlzZS5faCA9PSAyKW9uSGFuZGxlVW5oYW5kbGVkKHByb21pc2UpO1xuICAgICAgICAgICAgcHJvbWlzZS5faCA9IDE7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmKGhhbmRsZXIgPT09IHRydWUpcmVzdWx0ID0gdmFsdWU7XG4gICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZihkb21haW4pZG9tYWluLmVudGVyKCk7XG4gICAgICAgICAgICByZXN1bHQgPSBoYW5kbGVyKHZhbHVlKTtcbiAgICAgICAgICAgIGlmKGRvbWFpbilkb21haW4uZXhpdCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZihyZXN1bHQgPT09IHJlYWN0aW9uLnByb21pc2Upe1xuICAgICAgICAgICAgcmVqZWN0KFR5cGVFcnJvcignUHJvbWlzZS1jaGFpbiBjeWNsZScpKTtcbiAgICAgICAgICB9IGVsc2UgaWYodGhlbiA9IGlzVGhlbmFibGUocmVzdWx0KSl7XG4gICAgICAgICAgICB0aGVuLmNhbGwocmVzdWx0LCByZXNvbHZlLCByZWplY3QpO1xuICAgICAgICAgIH0gZWxzZSByZXNvbHZlKHJlc3VsdCk7XG4gICAgICAgIH0gZWxzZSByZWplY3QodmFsdWUpO1xuICAgICAgfSBjYXRjaChlKXtcbiAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgfVxuICAgIH07XG4gICAgd2hpbGUoY2hhaW4ubGVuZ3RoID4gaSlydW4oY2hhaW5baSsrXSk7IC8vIHZhcmlhYmxlIGxlbmd0aCAtIGNhbid0IHVzZSBmb3JFYWNoXG4gICAgcHJvbWlzZS5fYyA9IFtdO1xuICAgIHByb21pc2UuX24gPSBmYWxzZTtcbiAgICBpZihpc1JlamVjdCAmJiAhcHJvbWlzZS5faClvblVuaGFuZGxlZChwcm9taXNlKTtcbiAgfSk7XG59O1xudmFyIG9uVW5oYW5kbGVkID0gZnVuY3Rpb24ocHJvbWlzZSl7XG4gIHRhc2suY2FsbChnbG9iYWwsIGZ1bmN0aW9uKCl7XG4gICAgdmFyIHZhbHVlID0gcHJvbWlzZS5fdlxuICAgICAgLCBhYnJ1cHQsIGhhbmRsZXIsIGNvbnNvbGU7XG4gICAgaWYoaXNVbmhhbmRsZWQocHJvbWlzZSkpe1xuICAgICAgYWJydXB0ID0gcGVyZm9ybShmdW5jdGlvbigpe1xuICAgICAgICBpZihpc05vZGUpe1xuICAgICAgICAgIHByb2Nlc3MuZW1pdCgndW5oYW5kbGVkUmVqZWN0aW9uJywgdmFsdWUsIHByb21pc2UpO1xuICAgICAgICB9IGVsc2UgaWYoaGFuZGxlciA9IGdsb2JhbC5vbnVuaGFuZGxlZHJlamVjdGlvbil7XG4gICAgICAgICAgaGFuZGxlcih7cHJvbWlzZTogcHJvbWlzZSwgcmVhc29uOiB2YWx1ZX0pO1xuICAgICAgICB9IGVsc2UgaWYoKGNvbnNvbGUgPSBnbG9iYWwuY29uc29sZSkgJiYgY29uc29sZS5lcnJvcil7XG4gICAgICAgICAgY29uc29sZS5lcnJvcignVW5oYW5kbGVkIHByb21pc2UgcmVqZWN0aW9uJywgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIC8vIEJyb3dzZXJzIHNob3VsZCBub3QgdHJpZ2dlciBgcmVqZWN0aW9uSGFuZGxlZGAgZXZlbnQgaWYgaXQgd2FzIGhhbmRsZWQgaGVyZSwgTm9kZUpTIC0gc2hvdWxkXG4gICAgICBwcm9taXNlLl9oID0gaXNOb2RlIHx8IGlzVW5oYW5kbGVkKHByb21pc2UpID8gMiA6IDE7XG4gICAgfSBwcm9taXNlLl9hID0gdW5kZWZpbmVkO1xuICAgIGlmKGFicnVwdCl0aHJvdyBhYnJ1cHQuZXJyb3I7XG4gIH0pO1xufTtcbnZhciBpc1VuaGFuZGxlZCA9IGZ1bmN0aW9uKHByb21pc2Upe1xuICBpZihwcm9taXNlLl9oID09IDEpcmV0dXJuIGZhbHNlO1xuICB2YXIgY2hhaW4gPSBwcm9taXNlLl9hIHx8IHByb21pc2UuX2NcbiAgICAsIGkgICAgID0gMFxuICAgICwgcmVhY3Rpb247XG4gIHdoaWxlKGNoYWluLmxlbmd0aCA+IGkpe1xuICAgIHJlYWN0aW9uID0gY2hhaW5baSsrXTtcbiAgICBpZihyZWFjdGlvbi5mYWlsIHx8ICFpc1VuaGFuZGxlZChyZWFjdGlvbi5wcm9taXNlKSlyZXR1cm4gZmFsc2U7XG4gIH0gcmV0dXJuIHRydWU7XG59O1xudmFyIG9uSGFuZGxlVW5oYW5kbGVkID0gZnVuY3Rpb24ocHJvbWlzZSl7XG4gIHRhc2suY2FsbChnbG9iYWwsIGZ1bmN0aW9uKCl7XG4gICAgdmFyIGhhbmRsZXI7XG4gICAgaWYoaXNOb2RlKXtcbiAgICAgIHByb2Nlc3MuZW1pdCgncmVqZWN0aW9uSGFuZGxlZCcsIHByb21pc2UpO1xuICAgIH0gZWxzZSBpZihoYW5kbGVyID0gZ2xvYmFsLm9ucmVqZWN0aW9uaGFuZGxlZCl7XG4gICAgICBoYW5kbGVyKHtwcm9taXNlOiBwcm9taXNlLCByZWFzb246IHByb21pc2UuX3Z9KTtcbiAgICB9XG4gIH0pO1xufTtcbnZhciAkcmVqZWN0ID0gZnVuY3Rpb24odmFsdWUpe1xuICB2YXIgcHJvbWlzZSA9IHRoaXM7XG4gIGlmKHByb21pc2UuX2QpcmV0dXJuO1xuICBwcm9taXNlLl9kID0gdHJ1ZTtcbiAgcHJvbWlzZSA9IHByb21pc2UuX3cgfHwgcHJvbWlzZTsgLy8gdW53cmFwXG4gIHByb21pc2UuX3YgPSB2YWx1ZTtcbiAgcHJvbWlzZS5fcyA9IDI7XG4gIGlmKCFwcm9taXNlLl9hKXByb21pc2UuX2EgPSBwcm9taXNlLl9jLnNsaWNlKCk7XG4gIG5vdGlmeShwcm9taXNlLCB0cnVlKTtcbn07XG52YXIgJHJlc29sdmUgPSBmdW5jdGlvbih2YWx1ZSl7XG4gIHZhciBwcm9taXNlID0gdGhpc1xuICAgICwgdGhlbjtcbiAgaWYocHJvbWlzZS5fZClyZXR1cm47XG4gIHByb21pc2UuX2QgPSB0cnVlO1xuICBwcm9taXNlID0gcHJvbWlzZS5fdyB8fCBwcm9taXNlOyAvLyB1bndyYXBcbiAgdHJ5IHtcbiAgICBpZihwcm9taXNlID09PSB2YWx1ZSl0aHJvdyBUeXBlRXJyb3IoXCJQcm9taXNlIGNhbid0IGJlIHJlc29sdmVkIGl0c2VsZlwiKTtcbiAgICBpZih0aGVuID0gaXNUaGVuYWJsZSh2YWx1ZSkpe1xuICAgICAgbWljcm90YXNrKGZ1bmN0aW9uKCl7XG4gICAgICAgIHZhciB3cmFwcGVyID0ge193OiBwcm9taXNlLCBfZDogZmFsc2V9OyAvLyB3cmFwXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgdGhlbi5jYWxsKHZhbHVlLCBjdHgoJHJlc29sdmUsIHdyYXBwZXIsIDEpLCBjdHgoJHJlamVjdCwgd3JhcHBlciwgMSkpO1xuICAgICAgICB9IGNhdGNoKGUpe1xuICAgICAgICAgICRyZWplY3QuY2FsbCh3cmFwcGVyLCBlKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHByb21pc2UuX3YgPSB2YWx1ZTtcbiAgICAgIHByb21pc2UuX3MgPSAxO1xuICAgICAgbm90aWZ5KHByb21pc2UsIGZhbHNlKTtcbiAgICB9XG4gIH0gY2F0Y2goZSl7XG4gICAgJHJlamVjdC5jYWxsKHtfdzogcHJvbWlzZSwgX2Q6IGZhbHNlfSwgZSk7IC8vIHdyYXBcbiAgfVxufTtcblxuLy8gY29uc3RydWN0b3IgcG9seWZpbGxcbmlmKCFVU0VfTkFUSVZFKXtcbiAgLy8gMjUuNC4zLjEgUHJvbWlzZShleGVjdXRvcilcbiAgJFByb21pc2UgPSBmdW5jdGlvbiBQcm9taXNlKGV4ZWN1dG9yKXtcbiAgICBhbkluc3RhbmNlKHRoaXMsICRQcm9taXNlLCBQUk9NSVNFLCAnX2gnKTtcbiAgICBhRnVuY3Rpb24oZXhlY3V0b3IpO1xuICAgIEludGVybmFsLmNhbGwodGhpcyk7XG4gICAgdHJ5IHtcbiAgICAgIGV4ZWN1dG9yKGN0eCgkcmVzb2x2ZSwgdGhpcywgMSksIGN0eCgkcmVqZWN0LCB0aGlzLCAxKSk7XG4gICAgfSBjYXRjaChlcnIpe1xuICAgICAgJHJlamVjdC5jYWxsKHRoaXMsIGVycik7XG4gICAgfVxuICB9O1xuICBJbnRlcm5hbCA9IGZ1bmN0aW9uIFByb21pc2UoZXhlY3V0b3Ipe1xuICAgIHRoaXMuX2MgPSBbXTsgICAgICAgICAgICAgLy8gPC0gYXdhaXRpbmcgcmVhY3Rpb25zXG4gICAgdGhpcy5fYSA9IHVuZGVmaW5lZDsgICAgICAvLyA8LSBjaGVja2VkIGluIGlzVW5oYW5kbGVkIHJlYWN0aW9uc1xuICAgIHRoaXMuX3MgPSAwOyAgICAgICAgICAgICAgLy8gPC0gc3RhdGVcbiAgICB0aGlzLl9kID0gZmFsc2U7ICAgICAgICAgIC8vIDwtIGRvbmVcbiAgICB0aGlzLl92ID0gdW5kZWZpbmVkOyAgICAgIC8vIDwtIHZhbHVlXG4gICAgdGhpcy5faCA9IDA7ICAgICAgICAgICAgICAvLyA8LSByZWplY3Rpb24gc3RhdGUsIDAgLSBkZWZhdWx0LCAxIC0gaGFuZGxlZCwgMiAtIHVuaGFuZGxlZFxuICAgIHRoaXMuX24gPSBmYWxzZTsgICAgICAgICAgLy8gPC0gbm90aWZ5XG4gIH07XG4gIEludGVybmFsLnByb3RvdHlwZSA9IHJlcXVpcmUoJy4vX3JlZGVmaW5lLWFsbCcpKCRQcm9taXNlLnByb3RvdHlwZSwge1xuICAgIC8vIDI1LjQuNS4zIFByb21pc2UucHJvdG90eXBlLnRoZW4ob25GdWxmaWxsZWQsIG9uUmVqZWN0ZWQpXG4gICAgdGhlbjogZnVuY3Rpb24gdGhlbihvbkZ1bGZpbGxlZCwgb25SZWplY3RlZCl7XG4gICAgICB2YXIgcmVhY3Rpb24gICAgPSBuZXdQcm9taXNlQ2FwYWJpbGl0eShzcGVjaWVzQ29uc3RydWN0b3IodGhpcywgJFByb21pc2UpKTtcbiAgICAgIHJlYWN0aW9uLm9rICAgICA9IHR5cGVvZiBvbkZ1bGZpbGxlZCA9PSAnZnVuY3Rpb24nID8gb25GdWxmaWxsZWQgOiB0cnVlO1xuICAgICAgcmVhY3Rpb24uZmFpbCAgID0gdHlwZW9mIG9uUmVqZWN0ZWQgPT0gJ2Z1bmN0aW9uJyAmJiBvblJlamVjdGVkO1xuICAgICAgcmVhY3Rpb24uZG9tYWluID0gaXNOb2RlID8gcHJvY2Vzcy5kb21haW4gOiB1bmRlZmluZWQ7XG4gICAgICB0aGlzLl9jLnB1c2gocmVhY3Rpb24pO1xuICAgICAgaWYodGhpcy5fYSl0aGlzLl9hLnB1c2gocmVhY3Rpb24pO1xuICAgICAgaWYodGhpcy5fcylub3RpZnkodGhpcywgZmFsc2UpO1xuICAgICAgcmV0dXJuIHJlYWN0aW9uLnByb21pc2U7XG4gICAgfSxcbiAgICAvLyAyNS40LjUuMSBQcm9taXNlLnByb3RvdHlwZS5jYXRjaChvblJlamVjdGVkKVxuICAgICdjYXRjaCc6IGZ1bmN0aW9uKG9uUmVqZWN0ZWQpe1xuICAgICAgcmV0dXJuIHRoaXMudGhlbih1bmRlZmluZWQsIG9uUmVqZWN0ZWQpO1xuICAgIH1cbiAgfSk7XG4gIFByb21pc2VDYXBhYmlsaXR5ID0gZnVuY3Rpb24oKXtcbiAgICB2YXIgcHJvbWlzZSAgPSBuZXcgSW50ZXJuYWw7XG4gICAgdGhpcy5wcm9taXNlID0gcHJvbWlzZTtcbiAgICB0aGlzLnJlc29sdmUgPSBjdHgoJHJlc29sdmUsIHByb21pc2UsIDEpO1xuICAgIHRoaXMucmVqZWN0ICA9IGN0eCgkcmVqZWN0LCBwcm9taXNlLCAxKTtcbiAgfTtcbn1cblxuJGV4cG9ydCgkZXhwb3J0LkcgKyAkZXhwb3J0LlcgKyAkZXhwb3J0LkYgKiAhVVNFX05BVElWRSwge1Byb21pc2U6ICRQcm9taXNlfSk7XG5yZXF1aXJlKCcuL19zZXQtdG8tc3RyaW5nLXRhZycpKCRQcm9taXNlLCBQUk9NSVNFKTtcbnJlcXVpcmUoJy4vX3NldC1zcGVjaWVzJykoUFJPTUlTRSk7XG5XcmFwcGVyID0gcmVxdWlyZSgnLi9fY29yZScpW1BST01JU0VdO1xuXG4vLyBzdGF0aWNzXG4kZXhwb3J0KCRleHBvcnQuUyArICRleHBvcnQuRiAqICFVU0VfTkFUSVZFLCBQUk9NSVNFLCB7XG4gIC8vIDI1LjQuNC41IFByb21pc2UucmVqZWN0KHIpXG4gIHJlamVjdDogZnVuY3Rpb24gcmVqZWN0KHIpe1xuICAgIHZhciBjYXBhYmlsaXR5ID0gbmV3UHJvbWlzZUNhcGFiaWxpdHkodGhpcylcbiAgICAgICwgJCRyZWplY3QgICA9IGNhcGFiaWxpdHkucmVqZWN0O1xuICAgICQkcmVqZWN0KHIpO1xuICAgIHJldHVybiBjYXBhYmlsaXR5LnByb21pc2U7XG4gIH1cbn0pO1xuJGV4cG9ydCgkZXhwb3J0LlMgKyAkZXhwb3J0LkYgKiAoTElCUkFSWSB8fCAhVVNFX05BVElWRSksIFBST01JU0UsIHtcbiAgLy8gMjUuNC40LjYgUHJvbWlzZS5yZXNvbHZlKHgpXG4gIHJlc29sdmU6IGZ1bmN0aW9uIHJlc29sdmUoeCl7XG4gICAgLy8gaW5zdGFuY2VvZiBpbnN0ZWFkIG9mIGludGVybmFsIHNsb3QgY2hlY2sgYmVjYXVzZSB3ZSBzaG91bGQgZml4IGl0IHdpdGhvdXQgcmVwbGFjZW1lbnQgbmF0aXZlIFByb21pc2UgY29yZVxuICAgIGlmKHggaW5zdGFuY2VvZiAkUHJvbWlzZSAmJiBzYW1lQ29uc3RydWN0b3IoeC5jb25zdHJ1Y3RvciwgdGhpcykpcmV0dXJuIHg7XG4gICAgdmFyIGNhcGFiaWxpdHkgPSBuZXdQcm9taXNlQ2FwYWJpbGl0eSh0aGlzKVxuICAgICAgLCAkJHJlc29sdmUgID0gY2FwYWJpbGl0eS5yZXNvbHZlO1xuICAgICQkcmVzb2x2ZSh4KTtcbiAgICByZXR1cm4gY2FwYWJpbGl0eS5wcm9taXNlO1xuICB9XG59KTtcbiRleHBvcnQoJGV4cG9ydC5TICsgJGV4cG9ydC5GICogIShVU0VfTkFUSVZFICYmIHJlcXVpcmUoJy4vX2l0ZXItZGV0ZWN0JykoZnVuY3Rpb24oaXRlcil7XG4gICRQcm9taXNlLmFsbChpdGVyKVsnY2F0Y2gnXShlbXB0eSk7XG59KSksIFBST01JU0UsIHtcbiAgLy8gMjUuNC40LjEgUHJvbWlzZS5hbGwoaXRlcmFibGUpXG4gIGFsbDogZnVuY3Rpb24gYWxsKGl0ZXJhYmxlKXtcbiAgICB2YXIgQyAgICAgICAgICA9IHRoaXNcbiAgICAgICwgY2FwYWJpbGl0eSA9IG5ld1Byb21pc2VDYXBhYmlsaXR5KEMpXG4gICAgICAsIHJlc29sdmUgICAgPSBjYXBhYmlsaXR5LnJlc29sdmVcbiAgICAgICwgcmVqZWN0ICAgICA9IGNhcGFiaWxpdHkucmVqZWN0O1xuICAgIHZhciBhYnJ1cHQgPSBwZXJmb3JtKGZ1bmN0aW9uKCl7XG4gICAgICB2YXIgdmFsdWVzICAgID0gW11cbiAgICAgICAgLCBpbmRleCAgICAgPSAwXG4gICAgICAgICwgcmVtYWluaW5nID0gMTtcbiAgICAgIGZvck9mKGl0ZXJhYmxlLCBmYWxzZSwgZnVuY3Rpb24ocHJvbWlzZSl7XG4gICAgICAgIHZhciAkaW5kZXggICAgICAgID0gaW5kZXgrK1xuICAgICAgICAgICwgYWxyZWFkeUNhbGxlZCA9IGZhbHNlO1xuICAgICAgICB2YWx1ZXMucHVzaCh1bmRlZmluZWQpO1xuICAgICAgICByZW1haW5pbmcrKztcbiAgICAgICAgQy5yZXNvbHZlKHByb21pc2UpLnRoZW4oZnVuY3Rpb24odmFsdWUpe1xuICAgICAgICAgIGlmKGFscmVhZHlDYWxsZWQpcmV0dXJuO1xuICAgICAgICAgIGFscmVhZHlDYWxsZWQgID0gdHJ1ZTtcbiAgICAgICAgICB2YWx1ZXNbJGluZGV4XSA9IHZhbHVlO1xuICAgICAgICAgIC0tcmVtYWluaW5nIHx8IHJlc29sdmUodmFsdWVzKTtcbiAgICAgICAgfSwgcmVqZWN0KTtcbiAgICAgIH0pO1xuICAgICAgLS1yZW1haW5pbmcgfHwgcmVzb2x2ZSh2YWx1ZXMpO1xuICAgIH0pO1xuICAgIGlmKGFicnVwdClyZWplY3QoYWJydXB0LmVycm9yKTtcbiAgICByZXR1cm4gY2FwYWJpbGl0eS5wcm9taXNlO1xuICB9LFxuICAvLyAyNS40LjQuNCBQcm9taXNlLnJhY2UoaXRlcmFibGUpXG4gIHJhY2U6IGZ1bmN0aW9uIHJhY2UoaXRlcmFibGUpe1xuICAgIHZhciBDICAgICAgICAgID0gdGhpc1xuICAgICAgLCBjYXBhYmlsaXR5ID0gbmV3UHJvbWlzZUNhcGFiaWxpdHkoQylcbiAgICAgICwgcmVqZWN0ICAgICA9IGNhcGFiaWxpdHkucmVqZWN0O1xuICAgIHZhciBhYnJ1cHQgPSBwZXJmb3JtKGZ1bmN0aW9uKCl7XG4gICAgICBmb3JPZihpdGVyYWJsZSwgZmFsc2UsIGZ1bmN0aW9uKHByb21pc2Upe1xuICAgICAgICBDLnJlc29sdmUocHJvbWlzZSkudGhlbihjYXBhYmlsaXR5LnJlc29sdmUsIHJlamVjdCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICBpZihhYnJ1cHQpcmVqZWN0KGFicnVwdC5lcnJvcik7XG4gICAgcmV0dXJuIGNhcGFiaWxpdHkucHJvbWlzZTtcbiAgfVxufSk7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5wcm9taXNlLmpzXG4vLyBtb2R1bGUgaWQgPSAxOThcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiJ3VzZSBzdHJpY3QnO1xudmFyIHN0cm9uZyA9IHJlcXVpcmUoJy4vX2NvbGxlY3Rpb24tc3Ryb25nJyk7XG5cbi8vIDIzLjIgU2V0IE9iamVjdHNcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9fY29sbGVjdGlvbicpKCdTZXQnLCBmdW5jdGlvbihnZXQpe1xuICByZXR1cm4gZnVuY3Rpb24gU2V0KCl7IHJldHVybiBnZXQodGhpcywgYXJndW1lbnRzLmxlbmd0aCA+IDAgPyBhcmd1bWVudHNbMF0gOiB1bmRlZmluZWQpOyB9O1xufSwge1xuICAvLyAyMy4yLjMuMSBTZXQucHJvdG90eXBlLmFkZCh2YWx1ZSlcbiAgYWRkOiBmdW5jdGlvbiBhZGQodmFsdWUpe1xuICAgIHJldHVybiBzdHJvbmcuZGVmKHRoaXMsIHZhbHVlID0gdmFsdWUgPT09IDAgPyAwIDogdmFsdWUsIHZhbHVlKTtcbiAgfVxufSwgc3Ryb25nKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2LnNldC5qc1xuLy8gbW9kdWxlIGlkID0gMTk5XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIid1c2Ugc3RyaWN0Jztcbi8vIEVDTUFTY3JpcHQgNiBzeW1ib2xzIHNoaW1cbnZhciBnbG9iYWwgICAgICAgICA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpXG4gICwgaGFzICAgICAgICAgICAgPSByZXF1aXJlKCcuL19oYXMnKVxuICAsIERFU0NSSVBUT1JTICAgID0gcmVxdWlyZSgnLi9fZGVzY3JpcHRvcnMnKVxuICAsICRleHBvcnQgICAgICAgID0gcmVxdWlyZSgnLi9fZXhwb3J0JylcbiAgLCByZWRlZmluZSAgICAgICA9IHJlcXVpcmUoJy4vX3JlZGVmaW5lJylcbiAgLCBNRVRBICAgICAgICAgICA9IHJlcXVpcmUoJy4vX21ldGEnKS5LRVlcbiAgLCAkZmFpbHMgICAgICAgICA9IHJlcXVpcmUoJy4vX2ZhaWxzJylcbiAgLCBzaGFyZWQgICAgICAgICA9IHJlcXVpcmUoJy4vX3NoYXJlZCcpXG4gICwgc2V0VG9TdHJpbmdUYWcgPSByZXF1aXJlKCcuL19zZXQtdG8tc3RyaW5nLXRhZycpXG4gICwgdWlkICAgICAgICAgICAgPSByZXF1aXJlKCcuL191aWQnKVxuICAsIHdrcyAgICAgICAgICAgID0gcmVxdWlyZSgnLi9fd2tzJylcbiAgLCB3a3NFeHQgICAgICAgICA9IHJlcXVpcmUoJy4vX3drcy1leHQnKVxuICAsIHdrc0RlZmluZSAgICAgID0gcmVxdWlyZSgnLi9fd2tzLWRlZmluZScpXG4gICwga2V5T2YgICAgICAgICAgPSByZXF1aXJlKCcuL19rZXlvZicpXG4gICwgZW51bUtleXMgICAgICAgPSByZXF1aXJlKCcuL19lbnVtLWtleXMnKVxuICAsIGlzQXJyYXkgICAgICAgID0gcmVxdWlyZSgnLi9faXMtYXJyYXknKVxuICAsIGFuT2JqZWN0ICAgICAgID0gcmVxdWlyZSgnLi9fYW4tb2JqZWN0JylcbiAgLCB0b0lPYmplY3QgICAgICA9IHJlcXVpcmUoJy4vX3RvLWlvYmplY3QnKVxuICAsIHRvUHJpbWl0aXZlICAgID0gcmVxdWlyZSgnLi9fdG8tcHJpbWl0aXZlJylcbiAgLCBjcmVhdGVEZXNjICAgICA9IHJlcXVpcmUoJy4vX3Byb3BlcnR5LWRlc2MnKVxuICAsIF9jcmVhdGUgICAgICAgID0gcmVxdWlyZSgnLi9fb2JqZWN0LWNyZWF0ZScpXG4gICwgZ09QTkV4dCAgICAgICAgPSByZXF1aXJlKCcuL19vYmplY3QtZ29wbi1leHQnKVxuICAsICRHT1BEICAgICAgICAgID0gcmVxdWlyZSgnLi9fb2JqZWN0LWdvcGQnKVxuICAsICREUCAgICAgICAgICAgID0gcmVxdWlyZSgnLi9fb2JqZWN0LWRwJylcbiAgLCAka2V5cyAgICAgICAgICA9IHJlcXVpcmUoJy4vX29iamVjdC1rZXlzJylcbiAgLCBnT1BEICAgICAgICAgICA9ICRHT1BELmZcbiAgLCBkUCAgICAgICAgICAgICA9ICREUC5mXG4gICwgZ09QTiAgICAgICAgICAgPSBnT1BORXh0LmZcbiAgLCAkU3ltYm9sICAgICAgICA9IGdsb2JhbC5TeW1ib2xcbiAgLCAkSlNPTiAgICAgICAgICA9IGdsb2JhbC5KU09OXG4gICwgX3N0cmluZ2lmeSAgICAgPSAkSlNPTiAmJiAkSlNPTi5zdHJpbmdpZnlcbiAgLCBQUk9UT1RZUEUgICAgICA9ICdwcm90b3R5cGUnXG4gICwgSElEREVOICAgICAgICAgPSB3a3MoJ19oaWRkZW4nKVxuICAsIFRPX1BSSU1JVElWRSAgID0gd2tzKCd0b1ByaW1pdGl2ZScpXG4gICwgaXNFbnVtICAgICAgICAgPSB7fS5wcm9wZXJ0eUlzRW51bWVyYWJsZVxuICAsIFN5bWJvbFJlZ2lzdHJ5ID0gc2hhcmVkKCdzeW1ib2wtcmVnaXN0cnknKVxuICAsIEFsbFN5bWJvbHMgICAgID0gc2hhcmVkKCdzeW1ib2xzJylcbiAgLCBPUFN5bWJvbHMgICAgICA9IHNoYXJlZCgnb3Atc3ltYm9scycpXG4gICwgT2JqZWN0UHJvdG8gICAgPSBPYmplY3RbUFJPVE9UWVBFXVxuICAsIFVTRV9OQVRJVkUgICAgID0gdHlwZW9mICRTeW1ib2wgPT0gJ2Z1bmN0aW9uJ1xuICAsIFFPYmplY3QgICAgICAgID0gZ2xvYmFsLlFPYmplY3Q7XG4vLyBEb24ndCB1c2Ugc2V0dGVycyBpbiBRdCBTY3JpcHQsIGh0dHBzOi8vZ2l0aHViLmNvbS96bG9pcm9jay9jb3JlLWpzL2lzc3Vlcy8xNzNcbnZhciBzZXR0ZXIgPSAhUU9iamVjdCB8fCAhUU9iamVjdFtQUk9UT1RZUEVdIHx8ICFRT2JqZWN0W1BST1RPVFlQRV0uZmluZENoaWxkO1xuXG4vLyBmYWxsYmFjayBmb3Igb2xkIEFuZHJvaWQsIGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvdjgvaXNzdWVzL2RldGFpbD9pZD02ODdcbnZhciBzZXRTeW1ib2xEZXNjID0gREVTQ1JJUFRPUlMgJiYgJGZhaWxzKGZ1bmN0aW9uKCl7XG4gIHJldHVybiBfY3JlYXRlKGRQKHt9LCAnYScsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCl7IHJldHVybiBkUCh0aGlzLCAnYScsIHt2YWx1ZTogN30pLmE7IH1cbiAgfSkpLmEgIT0gNztcbn0pID8gZnVuY3Rpb24oaXQsIGtleSwgRCl7XG4gIHZhciBwcm90b0Rlc2MgPSBnT1BEKE9iamVjdFByb3RvLCBrZXkpO1xuICBpZihwcm90b0Rlc2MpZGVsZXRlIE9iamVjdFByb3RvW2tleV07XG4gIGRQKGl0LCBrZXksIEQpO1xuICBpZihwcm90b0Rlc2MgJiYgaXQgIT09IE9iamVjdFByb3RvKWRQKE9iamVjdFByb3RvLCBrZXksIHByb3RvRGVzYyk7XG59IDogZFA7XG5cbnZhciB3cmFwID0gZnVuY3Rpb24odGFnKXtcbiAgdmFyIHN5bSA9IEFsbFN5bWJvbHNbdGFnXSA9IF9jcmVhdGUoJFN5bWJvbFtQUk9UT1RZUEVdKTtcbiAgc3ltLl9rID0gdGFnO1xuICByZXR1cm4gc3ltO1xufTtcblxudmFyIGlzU3ltYm9sID0gVVNFX05BVElWRSAmJiB0eXBlb2YgJFN5bWJvbC5pdGVyYXRvciA9PSAnc3ltYm9sJyA/IGZ1bmN0aW9uKGl0KXtcbiAgcmV0dXJuIHR5cGVvZiBpdCA9PSAnc3ltYm9sJztcbn0gOiBmdW5jdGlvbihpdCl7XG4gIHJldHVybiBpdCBpbnN0YW5jZW9mICRTeW1ib2w7XG59O1xuXG52YXIgJGRlZmluZVByb3BlcnR5ID0gZnVuY3Rpb24gZGVmaW5lUHJvcGVydHkoaXQsIGtleSwgRCl7XG4gIGlmKGl0ID09PSBPYmplY3RQcm90bykkZGVmaW5lUHJvcGVydHkoT1BTeW1ib2xzLCBrZXksIEQpO1xuICBhbk9iamVjdChpdCk7XG4gIGtleSA9IHRvUHJpbWl0aXZlKGtleSwgdHJ1ZSk7XG4gIGFuT2JqZWN0KEQpO1xuICBpZihoYXMoQWxsU3ltYm9scywga2V5KSl7XG4gICAgaWYoIUQuZW51bWVyYWJsZSl7XG4gICAgICBpZighaGFzKGl0LCBISURERU4pKWRQKGl0LCBISURERU4sIGNyZWF0ZURlc2MoMSwge30pKTtcbiAgICAgIGl0W0hJRERFTl1ba2V5XSA9IHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmKGhhcyhpdCwgSElEREVOKSAmJiBpdFtISURERU5dW2tleV0paXRbSElEREVOXVtrZXldID0gZmFsc2U7XG4gICAgICBEID0gX2NyZWF0ZShELCB7ZW51bWVyYWJsZTogY3JlYXRlRGVzYygwLCBmYWxzZSl9KTtcbiAgICB9IHJldHVybiBzZXRTeW1ib2xEZXNjKGl0LCBrZXksIEQpO1xuICB9IHJldHVybiBkUChpdCwga2V5LCBEKTtcbn07XG52YXIgJGRlZmluZVByb3BlcnRpZXMgPSBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKGl0LCBQKXtcbiAgYW5PYmplY3QoaXQpO1xuICB2YXIga2V5cyA9IGVudW1LZXlzKFAgPSB0b0lPYmplY3QoUCkpXG4gICAgLCBpICAgID0gMFxuICAgICwgbCA9IGtleXMubGVuZ3RoXG4gICAgLCBrZXk7XG4gIHdoaWxlKGwgPiBpKSRkZWZpbmVQcm9wZXJ0eShpdCwga2V5ID0ga2V5c1tpKytdLCBQW2tleV0pO1xuICByZXR1cm4gaXQ7XG59O1xudmFyICRjcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoaXQsIFApe1xuICByZXR1cm4gUCA9PT0gdW5kZWZpbmVkID8gX2NyZWF0ZShpdCkgOiAkZGVmaW5lUHJvcGVydGllcyhfY3JlYXRlKGl0KSwgUCk7XG59O1xudmFyICRwcm9wZXJ0eUlzRW51bWVyYWJsZSA9IGZ1bmN0aW9uIHByb3BlcnR5SXNFbnVtZXJhYmxlKGtleSl7XG4gIHZhciBFID0gaXNFbnVtLmNhbGwodGhpcywga2V5ID0gdG9QcmltaXRpdmUoa2V5LCB0cnVlKSk7XG4gIGlmKHRoaXMgPT09IE9iamVjdFByb3RvICYmIGhhcyhBbGxTeW1ib2xzLCBrZXkpICYmICFoYXMoT1BTeW1ib2xzLCBrZXkpKXJldHVybiBmYWxzZTtcbiAgcmV0dXJuIEUgfHwgIWhhcyh0aGlzLCBrZXkpIHx8ICFoYXMoQWxsU3ltYm9scywga2V5KSB8fCBoYXModGhpcywgSElEREVOKSAmJiB0aGlzW0hJRERFTl1ba2V5XSA/IEUgOiB0cnVlO1xufTtcbnZhciAkZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yID0gZnVuY3Rpb24gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKGl0LCBrZXkpe1xuICBpdCAgPSB0b0lPYmplY3QoaXQpO1xuICBrZXkgPSB0b1ByaW1pdGl2ZShrZXksIHRydWUpO1xuICBpZihpdCA9PT0gT2JqZWN0UHJvdG8gJiYgaGFzKEFsbFN5bWJvbHMsIGtleSkgJiYgIWhhcyhPUFN5bWJvbHMsIGtleSkpcmV0dXJuO1xuICB2YXIgRCA9IGdPUEQoaXQsIGtleSk7XG4gIGlmKEQgJiYgaGFzKEFsbFN5bWJvbHMsIGtleSkgJiYgIShoYXMoaXQsIEhJRERFTikgJiYgaXRbSElEREVOXVtrZXldKSlELmVudW1lcmFibGUgPSB0cnVlO1xuICByZXR1cm4gRDtcbn07XG52YXIgJGdldE93blByb3BlcnR5TmFtZXMgPSBmdW5jdGlvbiBnZXRPd25Qcm9wZXJ0eU5hbWVzKGl0KXtcbiAgdmFyIG5hbWVzICA9IGdPUE4odG9JT2JqZWN0KGl0KSlcbiAgICAsIHJlc3VsdCA9IFtdXG4gICAgLCBpICAgICAgPSAwXG4gICAgLCBrZXk7XG4gIHdoaWxlKG5hbWVzLmxlbmd0aCA+IGkpe1xuICAgIGlmKCFoYXMoQWxsU3ltYm9scywga2V5ID0gbmFtZXNbaSsrXSkgJiYga2V5ICE9IEhJRERFTiAmJiBrZXkgIT0gTUVUQSlyZXN1bHQucHVzaChrZXkpO1xuICB9IHJldHVybiByZXN1bHQ7XG59O1xudmFyICRnZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPSBmdW5jdGlvbiBnZXRPd25Qcm9wZXJ0eVN5bWJvbHMoaXQpe1xuICB2YXIgSVNfT1AgID0gaXQgPT09IE9iamVjdFByb3RvXG4gICAgLCBuYW1lcyAgPSBnT1BOKElTX09QID8gT1BTeW1ib2xzIDogdG9JT2JqZWN0KGl0KSlcbiAgICAsIHJlc3VsdCA9IFtdXG4gICAgLCBpICAgICAgPSAwXG4gICAgLCBrZXk7XG4gIHdoaWxlKG5hbWVzLmxlbmd0aCA+IGkpe1xuICAgIGlmKGhhcyhBbGxTeW1ib2xzLCBrZXkgPSBuYW1lc1tpKytdKSAmJiAoSVNfT1AgPyBoYXMoT2JqZWN0UHJvdG8sIGtleSkgOiB0cnVlKSlyZXN1bHQucHVzaChBbGxTeW1ib2xzW2tleV0pO1xuICB9IHJldHVybiByZXN1bHQ7XG59O1xuXG4vLyAxOS40LjEuMSBTeW1ib2woW2Rlc2NyaXB0aW9uXSlcbmlmKCFVU0VfTkFUSVZFKXtcbiAgJFN5bWJvbCA9IGZ1bmN0aW9uIFN5bWJvbCgpe1xuICAgIGlmKHRoaXMgaW5zdGFuY2VvZiAkU3ltYm9sKXRocm93IFR5cGVFcnJvcignU3ltYm9sIGlzIG5vdCBhIGNvbnN0cnVjdG9yIScpO1xuICAgIHZhciB0YWcgPSB1aWQoYXJndW1lbnRzLmxlbmd0aCA+IDAgPyBhcmd1bWVudHNbMF0gOiB1bmRlZmluZWQpO1xuICAgIHZhciAkc2V0ID0gZnVuY3Rpb24odmFsdWUpe1xuICAgICAgaWYodGhpcyA9PT0gT2JqZWN0UHJvdG8pJHNldC5jYWxsKE9QU3ltYm9scywgdmFsdWUpO1xuICAgICAgaWYoaGFzKHRoaXMsIEhJRERFTikgJiYgaGFzKHRoaXNbSElEREVOXSwgdGFnKSl0aGlzW0hJRERFTl1bdGFnXSA9IGZhbHNlO1xuICAgICAgc2V0U3ltYm9sRGVzYyh0aGlzLCB0YWcsIGNyZWF0ZURlc2MoMSwgdmFsdWUpKTtcbiAgICB9O1xuICAgIGlmKERFU0NSSVBUT1JTICYmIHNldHRlcilzZXRTeW1ib2xEZXNjKE9iamVjdFByb3RvLCB0YWcsIHtjb25maWd1cmFibGU6IHRydWUsIHNldDogJHNldH0pO1xuICAgIHJldHVybiB3cmFwKHRhZyk7XG4gIH07XG4gIHJlZGVmaW5lKCRTeW1ib2xbUFJPVE9UWVBFXSwgJ3RvU3RyaW5nJywgZnVuY3Rpb24gdG9TdHJpbmcoKXtcbiAgICByZXR1cm4gdGhpcy5faztcbiAgfSk7XG5cbiAgJEdPUEQuZiA9ICRnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3I7XG4gICREUC5mICAgPSAkZGVmaW5lUHJvcGVydHk7XG4gIHJlcXVpcmUoJy4vX29iamVjdC1nb3BuJykuZiA9IGdPUE5FeHQuZiA9ICRnZXRPd25Qcm9wZXJ0eU5hbWVzO1xuICByZXF1aXJlKCcuL19vYmplY3QtcGllJykuZiAgPSAkcHJvcGVydHlJc0VudW1lcmFibGU7XG4gIHJlcXVpcmUoJy4vX29iamVjdC1nb3BzJykuZiA9ICRnZXRPd25Qcm9wZXJ0eVN5bWJvbHM7XG5cbiAgaWYoREVTQ1JJUFRPUlMgJiYgIXJlcXVpcmUoJy4vX2xpYnJhcnknKSl7XG4gICAgcmVkZWZpbmUoT2JqZWN0UHJvdG8sICdwcm9wZXJ0eUlzRW51bWVyYWJsZScsICRwcm9wZXJ0eUlzRW51bWVyYWJsZSwgdHJ1ZSk7XG4gIH1cblxuICB3a3NFeHQuZiA9IGZ1bmN0aW9uKG5hbWUpe1xuICAgIHJldHVybiB3cmFwKHdrcyhuYW1lKSk7XG4gIH1cbn1cblxuJGV4cG9ydCgkZXhwb3J0LkcgKyAkZXhwb3J0LlcgKyAkZXhwb3J0LkYgKiAhVVNFX05BVElWRSwge1N5bWJvbDogJFN5bWJvbH0pO1xuXG5mb3IodmFyIHN5bWJvbHMgPSAoXG4gIC8vIDE5LjQuMi4yLCAxOS40LjIuMywgMTkuNC4yLjQsIDE5LjQuMi42LCAxOS40LjIuOCwgMTkuNC4yLjksIDE5LjQuMi4xMCwgMTkuNC4yLjExLCAxOS40LjIuMTIsIDE5LjQuMi4xMywgMTkuNC4yLjE0XG4gICdoYXNJbnN0YW5jZSxpc0NvbmNhdFNwcmVhZGFibGUsaXRlcmF0b3IsbWF0Y2gscmVwbGFjZSxzZWFyY2gsc3BlY2llcyxzcGxpdCx0b1ByaW1pdGl2ZSx0b1N0cmluZ1RhZyx1bnNjb3BhYmxlcydcbikuc3BsaXQoJywnKSwgaSA9IDA7IHN5bWJvbHMubGVuZ3RoID4gaTsgKXdrcyhzeW1ib2xzW2krK10pO1xuXG5mb3IodmFyIHN5bWJvbHMgPSAka2V5cyh3a3Muc3RvcmUpLCBpID0gMDsgc3ltYm9scy5sZW5ndGggPiBpOyApd2tzRGVmaW5lKHN5bWJvbHNbaSsrXSk7XG5cbiRleHBvcnQoJGV4cG9ydC5TICsgJGV4cG9ydC5GICogIVVTRV9OQVRJVkUsICdTeW1ib2wnLCB7XG4gIC8vIDE5LjQuMi4xIFN5bWJvbC5mb3Ioa2V5KVxuICAnZm9yJzogZnVuY3Rpb24oa2V5KXtcbiAgICByZXR1cm4gaGFzKFN5bWJvbFJlZ2lzdHJ5LCBrZXkgKz0gJycpXG4gICAgICA/IFN5bWJvbFJlZ2lzdHJ5W2tleV1cbiAgICAgIDogU3ltYm9sUmVnaXN0cnlba2V5XSA9ICRTeW1ib2woa2V5KTtcbiAgfSxcbiAgLy8gMTkuNC4yLjUgU3ltYm9sLmtleUZvcihzeW0pXG4gIGtleUZvcjogZnVuY3Rpb24ga2V5Rm9yKGtleSl7XG4gICAgaWYoaXNTeW1ib2woa2V5KSlyZXR1cm4ga2V5T2YoU3ltYm9sUmVnaXN0cnksIGtleSk7XG4gICAgdGhyb3cgVHlwZUVycm9yKGtleSArICcgaXMgbm90IGEgc3ltYm9sIScpO1xuICB9LFxuICB1c2VTZXR0ZXI6IGZ1bmN0aW9uKCl7IHNldHRlciA9IHRydWU7IH0sXG4gIHVzZVNpbXBsZTogZnVuY3Rpb24oKXsgc2V0dGVyID0gZmFsc2U7IH1cbn0pO1xuXG4kZXhwb3J0KCRleHBvcnQuUyArICRleHBvcnQuRiAqICFVU0VfTkFUSVZFLCAnT2JqZWN0Jywge1xuICAvLyAxOS4xLjIuMiBPYmplY3QuY3JlYXRlKE8gWywgUHJvcGVydGllc10pXG4gIGNyZWF0ZTogJGNyZWF0ZSxcbiAgLy8gMTkuMS4yLjQgT2JqZWN0LmRlZmluZVByb3BlcnR5KE8sIFAsIEF0dHJpYnV0ZXMpXG4gIGRlZmluZVByb3BlcnR5OiAkZGVmaW5lUHJvcGVydHksXG4gIC8vIDE5LjEuMi4zIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKE8sIFByb3BlcnRpZXMpXG4gIGRlZmluZVByb3BlcnRpZXM6ICRkZWZpbmVQcm9wZXJ0aWVzLFxuICAvLyAxOS4xLjIuNiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKE8sIFApXG4gIGdldE93blByb3BlcnR5RGVzY3JpcHRvcjogJGdldE93blByb3BlcnR5RGVzY3JpcHRvcixcbiAgLy8gMTkuMS4yLjcgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoTylcbiAgZ2V0T3duUHJvcGVydHlOYW1lczogJGdldE93blByb3BlcnR5TmFtZXMsXG4gIC8vIDE5LjEuMi44IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMoTylcbiAgZ2V0T3duUHJvcGVydHlTeW1ib2xzOiAkZ2V0T3duUHJvcGVydHlTeW1ib2xzXG59KTtcblxuLy8gMjQuMy4yIEpTT04uc3RyaW5naWZ5KHZhbHVlIFssIHJlcGxhY2VyIFssIHNwYWNlXV0pXG4kSlNPTiAmJiAkZXhwb3J0KCRleHBvcnQuUyArICRleHBvcnQuRiAqICghVVNFX05BVElWRSB8fCAkZmFpbHMoZnVuY3Rpb24oKXtcbiAgdmFyIFMgPSAkU3ltYm9sKCk7XG4gIC8vIE1TIEVkZ2UgY29udmVydHMgc3ltYm9sIHZhbHVlcyB0byBKU09OIGFzIHt9XG4gIC8vIFdlYktpdCBjb252ZXJ0cyBzeW1ib2wgdmFsdWVzIHRvIEpTT04gYXMgbnVsbFxuICAvLyBWOCB0aHJvd3Mgb24gYm94ZWQgc3ltYm9sc1xuICByZXR1cm4gX3N0cmluZ2lmeShbU10pICE9ICdbbnVsbF0nIHx8IF9zdHJpbmdpZnkoe2E6IFN9KSAhPSAne30nIHx8IF9zdHJpbmdpZnkoT2JqZWN0KFMpKSAhPSAne30nO1xufSkpLCAnSlNPTicsIHtcbiAgc3RyaW5naWZ5OiBmdW5jdGlvbiBzdHJpbmdpZnkoaXQpe1xuICAgIGlmKGl0ID09PSB1bmRlZmluZWQgfHwgaXNTeW1ib2woaXQpKXJldHVybjsgLy8gSUU4IHJldHVybnMgc3RyaW5nIG9uIHVuZGVmaW5lZFxuICAgIHZhciBhcmdzID0gW2l0XVxuICAgICAgLCBpICAgID0gMVxuICAgICAgLCByZXBsYWNlciwgJHJlcGxhY2VyO1xuICAgIHdoaWxlKGFyZ3VtZW50cy5sZW5ndGggPiBpKWFyZ3MucHVzaChhcmd1bWVudHNbaSsrXSk7XG4gICAgcmVwbGFjZXIgPSBhcmdzWzFdO1xuICAgIGlmKHR5cGVvZiByZXBsYWNlciA9PSAnZnVuY3Rpb24nKSRyZXBsYWNlciA9IHJlcGxhY2VyO1xuICAgIGlmKCRyZXBsYWNlciB8fCAhaXNBcnJheShyZXBsYWNlcikpcmVwbGFjZXIgPSBmdW5jdGlvbihrZXksIHZhbHVlKXtcbiAgICAgIGlmKCRyZXBsYWNlcil2YWx1ZSA9ICRyZXBsYWNlci5jYWxsKHRoaXMsIGtleSwgdmFsdWUpO1xuICAgICAgaWYoIWlzU3ltYm9sKHZhbHVlKSlyZXR1cm4gdmFsdWU7XG4gICAgfTtcbiAgICBhcmdzWzFdID0gcmVwbGFjZXI7XG4gICAgcmV0dXJuIF9zdHJpbmdpZnkuYXBwbHkoJEpTT04sIGFyZ3MpO1xuICB9XG59KTtcblxuLy8gMTkuNC4zLjQgU3ltYm9sLnByb3RvdHlwZVtAQHRvUHJpbWl0aXZlXShoaW50KVxuJFN5bWJvbFtQUk9UT1RZUEVdW1RPX1BSSU1JVElWRV0gfHwgcmVxdWlyZSgnLi9faGlkZScpKCRTeW1ib2xbUFJPVE9UWVBFXSwgVE9fUFJJTUlUSVZFLCAkU3ltYm9sW1BST1RPVFlQRV0udmFsdWVPZik7XG4vLyAxOS40LjMuNSBTeW1ib2wucHJvdG90eXBlW0BAdG9TdHJpbmdUYWddXG5zZXRUb1N0cmluZ1RhZygkU3ltYm9sLCAnU3ltYm9sJyk7XG4vLyAyMC4yLjEuOSBNYXRoW0BAdG9TdHJpbmdUYWddXG5zZXRUb1N0cmluZ1RhZyhNYXRoLCAnTWF0aCcsIHRydWUpO1xuLy8gMjQuMy4zIEpTT05bQEB0b1N0cmluZ1RhZ11cbnNldFRvU3RyaW5nVGFnKGdsb2JhbC5KU09OLCAnSlNPTicsIHRydWUpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYuc3ltYm9sLmpzXG4vLyBtb2R1bGUgaWQgPSAyMDBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiJ3VzZSBzdHJpY3QnO1xudmFyIGVhY2ggICAgICAgICA9IHJlcXVpcmUoJy4vX2FycmF5LW1ldGhvZHMnKSgwKVxuICAsIHJlZGVmaW5lICAgICA9IHJlcXVpcmUoJy4vX3JlZGVmaW5lJylcbiAgLCBtZXRhICAgICAgICAgPSByZXF1aXJlKCcuL19tZXRhJylcbiAgLCBhc3NpZ24gICAgICAgPSByZXF1aXJlKCcuL19vYmplY3QtYXNzaWduJylcbiAgLCB3ZWFrICAgICAgICAgPSByZXF1aXJlKCcuL19jb2xsZWN0aW9uLXdlYWsnKVxuICAsIGlzT2JqZWN0ICAgICA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpXG4gICwgZ2V0V2VhayAgICAgID0gbWV0YS5nZXRXZWFrXG4gICwgaXNFeHRlbnNpYmxlID0gT2JqZWN0LmlzRXh0ZW5zaWJsZVxuICAsIHVuY2F1Z2h0RnJvemVuU3RvcmUgPSB3ZWFrLnVmc3RvcmVcbiAgLCB0bXAgICAgICAgICAgPSB7fVxuICAsIEludGVybmFsTWFwO1xuXG52YXIgd3JhcHBlciA9IGZ1bmN0aW9uKGdldCl7XG4gIHJldHVybiBmdW5jdGlvbiBXZWFrTWFwKCl7XG4gICAgcmV0dXJuIGdldCh0aGlzLCBhcmd1bWVudHMubGVuZ3RoID4gMCA/IGFyZ3VtZW50c1swXSA6IHVuZGVmaW5lZCk7XG4gIH07XG59O1xuXG52YXIgbWV0aG9kcyA9IHtcbiAgLy8gMjMuMy4zLjMgV2Vha01hcC5wcm90b3R5cGUuZ2V0KGtleSlcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoa2V5KXtcbiAgICBpZihpc09iamVjdChrZXkpKXtcbiAgICAgIHZhciBkYXRhID0gZ2V0V2VhayhrZXkpO1xuICAgICAgaWYoZGF0YSA9PT0gdHJ1ZSlyZXR1cm4gdW5jYXVnaHRGcm96ZW5TdG9yZSh0aGlzKS5nZXQoa2V5KTtcbiAgICAgIHJldHVybiBkYXRhID8gZGF0YVt0aGlzLl9pXSA6IHVuZGVmaW5lZDtcbiAgICB9XG4gIH0sXG4gIC8vIDIzLjMuMy41IFdlYWtNYXAucHJvdG90eXBlLnNldChrZXksIHZhbHVlKVxuICBzZXQ6IGZ1bmN0aW9uIHNldChrZXksIHZhbHVlKXtcbiAgICByZXR1cm4gd2Vhay5kZWYodGhpcywga2V5LCB2YWx1ZSk7XG4gIH1cbn07XG5cbi8vIDIzLjMgV2Vha01hcCBPYmplY3RzXG52YXIgJFdlYWtNYXAgPSBtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vX2NvbGxlY3Rpb24nKSgnV2Vha01hcCcsIHdyYXBwZXIsIG1ldGhvZHMsIHdlYWssIHRydWUsIHRydWUpO1xuXG4vLyBJRTExIFdlYWtNYXAgZnJvemVuIGtleXMgZml4XG5pZihuZXcgJFdlYWtNYXAoKS5zZXQoKE9iamVjdC5mcmVlemUgfHwgT2JqZWN0KSh0bXApLCA3KS5nZXQodG1wKSAhPSA3KXtcbiAgSW50ZXJuYWxNYXAgPSB3ZWFrLmdldENvbnN0cnVjdG9yKHdyYXBwZXIpO1xuICBhc3NpZ24oSW50ZXJuYWxNYXAucHJvdG90eXBlLCBtZXRob2RzKTtcbiAgbWV0YS5ORUVEID0gdHJ1ZTtcbiAgZWFjaChbJ2RlbGV0ZScsICdoYXMnLCAnZ2V0JywgJ3NldCddLCBmdW5jdGlvbihrZXkpe1xuICAgIHZhciBwcm90byAgPSAkV2Vha01hcC5wcm90b3R5cGVcbiAgICAgICwgbWV0aG9kID0gcHJvdG9ba2V5XTtcbiAgICByZWRlZmluZShwcm90bywga2V5LCBmdW5jdGlvbihhLCBiKXtcbiAgICAgIC8vIHN0b3JlIGZyb3plbiBvYmplY3RzIG9uIGludGVybmFsIHdlYWttYXAgc2hpbVxuICAgICAgaWYoaXNPYmplY3QoYSkgJiYgIWlzRXh0ZW5zaWJsZShhKSl7XG4gICAgICAgIGlmKCF0aGlzLl9mKXRoaXMuX2YgPSBuZXcgSW50ZXJuYWxNYXA7XG4gICAgICAgIHZhciByZXN1bHQgPSB0aGlzLl9mW2tleV0oYSwgYik7XG4gICAgICAgIHJldHVybiBrZXkgPT0gJ3NldCcgPyB0aGlzIDogcmVzdWx0O1xuICAgICAgLy8gc3RvcmUgYWxsIHRoZSByZXN0IG9uIG5hdGl2ZSB3ZWFrbWFwXG4gICAgICB9IHJldHVybiBtZXRob2QuY2FsbCh0aGlzLCBhLCBiKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi53ZWFrLW1hcC5qc1xuLy8gbW9kdWxlIGlkID0gMjAxXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9EYXZpZEJydWFudC9NYXAtU2V0LnByb3RvdHlwZS50b0pTT05cbnZhciAkZXhwb3J0ICA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpO1xuXG4kZXhwb3J0KCRleHBvcnQuUCArICRleHBvcnQuUiwgJ01hcCcsIHt0b0pTT046IHJlcXVpcmUoJy4vX2NvbGxlY3Rpb24tdG8tanNvbicpKCdNYXAnKX0pO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczcubWFwLnRvLWpzb24uanNcbi8vIG1vZHVsZSBpZCA9IDIwMlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyBodHRwczovL2dpdGh1Yi5jb20vRGF2aWRCcnVhbnQvTWFwLVNldC5wcm90b3R5cGUudG9KU09OXG52YXIgJGV4cG9ydCAgPSByZXF1aXJlKCcuL19leHBvcnQnKTtcblxuJGV4cG9ydCgkZXhwb3J0LlAgKyAkZXhwb3J0LlIsICdTZXQnLCB7dG9KU09OOiByZXF1aXJlKCcuL19jb2xsZWN0aW9uLXRvLWpzb24nKSgnU2V0Jyl9KTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM3LnNldC50by1qc29uLmpzXG4vLyBtb2R1bGUgaWQgPSAyMDNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwicmVxdWlyZSgnLi9fd2tzLWRlZmluZScpKCdhc3luY0l0ZXJhdG9yJyk7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNy5zeW1ib2wuYXN5bmMtaXRlcmF0b3IuanNcbi8vIG1vZHVsZSBpZCA9IDIwNFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJyZXF1aXJlKCcuL193a3MtZGVmaW5lJykoJ29ic2VydmFibGUnKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM3LnN5bWJvbC5vYnNlcnZhYmxlLmpzXG4vLyBtb2R1bGUgaWQgPSAyMDVcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8gVGhpcyBtZXRob2Qgb2Ygb2J0YWluaW5nIGEgcmVmZXJlbmNlIHRvIHRoZSBnbG9iYWwgb2JqZWN0IG5lZWRzIHRvIGJlXG4vLyBrZXB0IGlkZW50aWNhbCB0byB0aGUgd2F5IGl0IGlzIG9idGFpbmVkIGluIHJ1bnRpbWUuanNcbnZhciBnID0gKGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcyB9KSgpIHx8IEZ1bmN0aW9uKFwicmV0dXJuIHRoaXNcIikoKTtcblxuLy8gVXNlIGBnZXRPd25Qcm9wZXJ0eU5hbWVzYCBiZWNhdXNlIG5vdCBhbGwgYnJvd3NlcnMgc3VwcG9ydCBjYWxsaW5nXG4vLyBgaGFzT3duUHJvcGVydHlgIG9uIHRoZSBnbG9iYWwgYHNlbGZgIG9iamVjdCBpbiBhIHdvcmtlci4gU2VlICMxODMuXG52YXIgaGFkUnVudGltZSA9IGcucmVnZW5lcmF0b3JSdW50aW1lICYmXG4gIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKGcpLmluZGV4T2YoXCJyZWdlbmVyYXRvclJ1bnRpbWVcIikgPj0gMDtcblxuLy8gU2F2ZSB0aGUgb2xkIHJlZ2VuZXJhdG9yUnVudGltZSBpbiBjYXNlIGl0IG5lZWRzIHRvIGJlIHJlc3RvcmVkIGxhdGVyLlxudmFyIG9sZFJ1bnRpbWUgPSBoYWRSdW50aW1lICYmIGcucmVnZW5lcmF0b3JSdW50aW1lO1xuXG4vLyBGb3JjZSByZWV2YWx1dGF0aW9uIG9mIHJ1bnRpbWUuanMuXG5nLnJlZ2VuZXJhdG9yUnVudGltZSA9IHVuZGVmaW5lZDtcblxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwiLi9ydW50aW1lXCIpO1xuXG5pZiAoaGFkUnVudGltZSkge1xuICAvLyBSZXN0b3JlIHRoZSBvcmlnaW5hbCBydW50aW1lLlxuICBnLnJlZ2VuZXJhdG9yUnVudGltZSA9IG9sZFJ1bnRpbWU7XG59IGVsc2Uge1xuICAvLyBSZW1vdmUgdGhlIGdsb2JhbCBwcm9wZXJ0eSBhZGRlZCBieSBydW50aW1lLmpzLlxuICB0cnkge1xuICAgIGRlbGV0ZSBnLnJlZ2VuZXJhdG9yUnVudGltZTtcbiAgfSBjYXRjaChlKSB7XG4gICAgZy5yZWdlbmVyYXRvclJ1bnRpbWUgPSB1bmRlZmluZWQ7XG4gIH1cbn1cblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9yZWdlbmVyYXRvci1ydW50aW1lL3J1bnRpbWUtbW9kdWxlLmpzXG4vLyBtb2R1bGUgaWQgPSAyMDZcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTQsIEZhY2Vib29rLCBJbmMuXG4gKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIEJTRC1zdHlsZSBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogaHR0cHM6Ly9yYXcuZ2l0aHViLmNvbS9mYWNlYm9vay9yZWdlbmVyYXRvci9tYXN0ZXIvTElDRU5TRSBmaWxlLiBBblxuICogYWRkaXRpb25hbCBncmFudCBvZiBwYXRlbnQgcmlnaHRzIGNhbiBiZSBmb3VuZCBpbiB0aGUgUEFURU5UUyBmaWxlIGluXG4gKiB0aGUgc2FtZSBkaXJlY3RvcnkuXG4gKi9cblxuIShmdW5jdGlvbihnbG9iYWwpIHtcbiAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgdmFyIE9wID0gT2JqZWN0LnByb3RvdHlwZTtcbiAgdmFyIGhhc093biA9IE9wLmhhc093blByb3BlcnR5O1xuICB2YXIgdW5kZWZpbmVkOyAvLyBNb3JlIGNvbXByZXNzaWJsZSB0aGFuIHZvaWQgMC5cbiAgdmFyICRTeW1ib2wgPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgPyBTeW1ib2wgOiB7fTtcbiAgdmFyIGl0ZXJhdG9yU3ltYm9sID0gJFN5bWJvbC5pdGVyYXRvciB8fCBcIkBAaXRlcmF0b3JcIjtcbiAgdmFyIGFzeW5jSXRlcmF0b3JTeW1ib2wgPSAkU3ltYm9sLmFzeW5jSXRlcmF0b3IgfHwgXCJAQGFzeW5jSXRlcmF0b3JcIjtcbiAgdmFyIHRvU3RyaW5nVGFnU3ltYm9sID0gJFN5bWJvbC50b1N0cmluZ1RhZyB8fCBcIkBAdG9TdHJpbmdUYWdcIjtcblxuICB2YXIgaW5Nb2R1bGUgPSB0eXBlb2YgbW9kdWxlID09PSBcIm9iamVjdFwiO1xuICB2YXIgcnVudGltZSA9IGdsb2JhbC5yZWdlbmVyYXRvclJ1bnRpbWU7XG4gIGlmIChydW50aW1lKSB7XG4gICAgaWYgKGluTW9kdWxlKSB7XG4gICAgICAvLyBJZiByZWdlbmVyYXRvclJ1bnRpbWUgaXMgZGVmaW5lZCBnbG9iYWxseSBhbmQgd2UncmUgaW4gYSBtb2R1bGUsXG4gICAgICAvLyBtYWtlIHRoZSBleHBvcnRzIG9iamVjdCBpZGVudGljYWwgdG8gcmVnZW5lcmF0b3JSdW50aW1lLlxuICAgICAgbW9kdWxlLmV4cG9ydHMgPSBydW50aW1lO1xuICAgIH1cbiAgICAvLyBEb24ndCBib3RoZXIgZXZhbHVhdGluZyB0aGUgcmVzdCBvZiB0aGlzIGZpbGUgaWYgdGhlIHJ1bnRpbWUgd2FzXG4gICAgLy8gYWxyZWFkeSBkZWZpbmVkIGdsb2JhbGx5LlxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIERlZmluZSB0aGUgcnVudGltZSBnbG9iYWxseSAoYXMgZXhwZWN0ZWQgYnkgZ2VuZXJhdGVkIGNvZGUpIGFzIGVpdGhlclxuICAvLyBtb2R1bGUuZXhwb3J0cyAoaWYgd2UncmUgaW4gYSBtb2R1bGUpIG9yIGEgbmV3LCBlbXB0eSBvYmplY3QuXG4gIHJ1bnRpbWUgPSBnbG9iYWwucmVnZW5lcmF0b3JSdW50aW1lID0gaW5Nb2R1bGUgPyBtb2R1bGUuZXhwb3J0cyA6IHt9O1xuXG4gIGZ1bmN0aW9uIHdyYXAoaW5uZXJGbiwgb3V0ZXJGbiwgc2VsZiwgdHJ5TG9jc0xpc3QpIHtcbiAgICAvLyBJZiBvdXRlckZuIHByb3ZpZGVkIGFuZCBvdXRlckZuLnByb3RvdHlwZSBpcyBhIEdlbmVyYXRvciwgdGhlbiBvdXRlckZuLnByb3RvdHlwZSBpbnN0YW5jZW9mIEdlbmVyYXRvci5cbiAgICB2YXIgcHJvdG9HZW5lcmF0b3IgPSBvdXRlckZuICYmIG91dGVyRm4ucHJvdG90eXBlIGluc3RhbmNlb2YgR2VuZXJhdG9yID8gb3V0ZXJGbiA6IEdlbmVyYXRvcjtcbiAgICB2YXIgZ2VuZXJhdG9yID0gT2JqZWN0LmNyZWF0ZShwcm90b0dlbmVyYXRvci5wcm90b3R5cGUpO1xuICAgIHZhciBjb250ZXh0ID0gbmV3IENvbnRleHQodHJ5TG9jc0xpc3QgfHwgW10pO1xuXG4gICAgLy8gVGhlIC5faW52b2tlIG1ldGhvZCB1bmlmaWVzIHRoZSBpbXBsZW1lbnRhdGlvbnMgb2YgdGhlIC5uZXh0LFxuICAgIC8vIC50aHJvdywgYW5kIC5yZXR1cm4gbWV0aG9kcy5cbiAgICBnZW5lcmF0b3IuX2ludm9rZSA9IG1ha2VJbnZva2VNZXRob2QoaW5uZXJGbiwgc2VsZiwgY29udGV4dCk7XG5cbiAgICByZXR1cm4gZ2VuZXJhdG9yO1xuICB9XG4gIHJ1bnRpbWUud3JhcCA9IHdyYXA7XG5cbiAgLy8gVHJ5L2NhdGNoIGhlbHBlciB0byBtaW5pbWl6ZSBkZW9wdGltaXphdGlvbnMuIFJldHVybnMgYSBjb21wbGV0aW9uXG4gIC8vIHJlY29yZCBsaWtlIGNvbnRleHQudHJ5RW50cmllc1tpXS5jb21wbGV0aW9uLiBUaGlzIGludGVyZmFjZSBjb3VsZFxuICAvLyBoYXZlIGJlZW4gKGFuZCB3YXMgcHJldmlvdXNseSkgZGVzaWduZWQgdG8gdGFrZSBhIGNsb3N1cmUgdG8gYmVcbiAgLy8gaW52b2tlZCB3aXRob3V0IGFyZ3VtZW50cywgYnV0IGluIGFsbCB0aGUgY2FzZXMgd2UgY2FyZSBhYm91dCB3ZVxuICAvLyBhbHJlYWR5IGhhdmUgYW4gZXhpc3RpbmcgbWV0aG9kIHdlIHdhbnQgdG8gY2FsbCwgc28gdGhlcmUncyBubyBuZWVkXG4gIC8vIHRvIGNyZWF0ZSBhIG5ldyBmdW5jdGlvbiBvYmplY3QuIFdlIGNhbiBldmVuIGdldCBhd2F5IHdpdGggYXNzdW1pbmdcbiAgLy8gdGhlIG1ldGhvZCB0YWtlcyBleGFjdGx5IG9uZSBhcmd1bWVudCwgc2luY2UgdGhhdCBoYXBwZW5zIHRvIGJlIHRydWVcbiAgLy8gaW4gZXZlcnkgY2FzZSwgc28gd2UgZG9uJ3QgaGF2ZSB0byB0b3VjaCB0aGUgYXJndW1lbnRzIG9iamVjdC4gVGhlXG4gIC8vIG9ubHkgYWRkaXRpb25hbCBhbGxvY2F0aW9uIHJlcXVpcmVkIGlzIHRoZSBjb21wbGV0aW9uIHJlY29yZCwgd2hpY2hcbiAgLy8gaGFzIGEgc3RhYmxlIHNoYXBlIGFuZCBzbyBob3BlZnVsbHkgc2hvdWxkIGJlIGNoZWFwIHRvIGFsbG9jYXRlLlxuICBmdW5jdGlvbiB0cnlDYXRjaChmbiwgb2JqLCBhcmcpIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIHsgdHlwZTogXCJub3JtYWxcIiwgYXJnOiBmbi5jYWxsKG9iaiwgYXJnKSB9O1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgcmV0dXJuIHsgdHlwZTogXCJ0aHJvd1wiLCBhcmc6IGVyciB9O1xuICAgIH1cbiAgfVxuXG4gIHZhciBHZW5TdGF0ZVN1c3BlbmRlZFN0YXJ0ID0gXCJzdXNwZW5kZWRTdGFydFwiO1xuICB2YXIgR2VuU3RhdGVTdXNwZW5kZWRZaWVsZCA9IFwic3VzcGVuZGVkWWllbGRcIjtcbiAgdmFyIEdlblN0YXRlRXhlY3V0aW5nID0gXCJleGVjdXRpbmdcIjtcbiAgdmFyIEdlblN0YXRlQ29tcGxldGVkID0gXCJjb21wbGV0ZWRcIjtcblxuICAvLyBSZXR1cm5pbmcgdGhpcyBvYmplY3QgZnJvbSB0aGUgaW5uZXJGbiBoYXMgdGhlIHNhbWUgZWZmZWN0IGFzXG4gIC8vIGJyZWFraW5nIG91dCBvZiB0aGUgZGlzcGF0Y2ggc3dpdGNoIHN0YXRlbWVudC5cbiAgdmFyIENvbnRpbnVlU2VudGluZWwgPSB7fTtcblxuICAvLyBEdW1teSBjb25zdHJ1Y3RvciBmdW5jdGlvbnMgdGhhdCB3ZSB1c2UgYXMgdGhlIC5jb25zdHJ1Y3RvciBhbmRcbiAgLy8gLmNvbnN0cnVjdG9yLnByb3RvdHlwZSBwcm9wZXJ0aWVzIGZvciBmdW5jdGlvbnMgdGhhdCByZXR1cm4gR2VuZXJhdG9yXG4gIC8vIG9iamVjdHMuIEZvciBmdWxsIHNwZWMgY29tcGxpYW5jZSwgeW91IG1heSB3aXNoIHRvIGNvbmZpZ3VyZSB5b3VyXG4gIC8vIG1pbmlmaWVyIG5vdCB0byBtYW5nbGUgdGhlIG5hbWVzIG9mIHRoZXNlIHR3byBmdW5jdGlvbnMuXG4gIGZ1bmN0aW9uIEdlbmVyYXRvcigpIHt9XG4gIGZ1bmN0aW9uIEdlbmVyYXRvckZ1bmN0aW9uKCkge31cbiAgZnVuY3Rpb24gR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGUoKSB7fVxuXG4gIC8vIFRoaXMgaXMgYSBwb2x5ZmlsbCBmb3IgJUl0ZXJhdG9yUHJvdG90eXBlJSBmb3IgZW52aXJvbm1lbnRzIHRoYXRcbiAgLy8gZG9uJ3QgbmF0aXZlbHkgc3VwcG9ydCBpdC5cbiAgdmFyIEl0ZXJhdG9yUHJvdG90eXBlID0ge307XG4gIEl0ZXJhdG9yUHJvdG90eXBlW2l0ZXJhdG9yU3ltYm9sXSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcztcbiAgfTtcblxuICB2YXIgZ2V0UHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Y7XG4gIHZhciBOYXRpdmVJdGVyYXRvclByb3RvdHlwZSA9IGdldFByb3RvICYmIGdldFByb3RvKGdldFByb3RvKHZhbHVlcyhbXSkpKTtcbiAgaWYgKE5hdGl2ZUl0ZXJhdG9yUHJvdG90eXBlICYmXG4gICAgICBOYXRpdmVJdGVyYXRvclByb3RvdHlwZSAhPT0gT3AgJiZcbiAgICAgIGhhc093bi5jYWxsKE5hdGl2ZUl0ZXJhdG9yUHJvdG90eXBlLCBpdGVyYXRvclN5bWJvbCkpIHtcbiAgICAvLyBUaGlzIGVudmlyb25tZW50IGhhcyBhIG5hdGl2ZSAlSXRlcmF0b3JQcm90b3R5cGUlOyB1c2UgaXQgaW5zdGVhZFxuICAgIC8vIG9mIHRoZSBwb2x5ZmlsbC5cbiAgICBJdGVyYXRvclByb3RvdHlwZSA9IE5hdGl2ZUl0ZXJhdG9yUHJvdG90eXBlO1xuICB9XG5cbiAgdmFyIEdwID0gR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGUucHJvdG90eXBlID1cbiAgICBHZW5lcmF0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShJdGVyYXRvclByb3RvdHlwZSk7XG4gIEdlbmVyYXRvckZ1bmN0aW9uLnByb3RvdHlwZSA9IEdwLmNvbnN0cnVjdG9yID0gR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGU7XG4gIEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlLmNvbnN0cnVjdG9yID0gR2VuZXJhdG9yRnVuY3Rpb247XG4gIEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlW3RvU3RyaW5nVGFnU3ltYm9sXSA9XG4gICAgR2VuZXJhdG9yRnVuY3Rpb24uZGlzcGxheU5hbWUgPSBcIkdlbmVyYXRvckZ1bmN0aW9uXCI7XG5cbiAgLy8gSGVscGVyIGZvciBkZWZpbmluZyB0aGUgLm5leHQsIC50aHJvdywgYW5kIC5yZXR1cm4gbWV0aG9kcyBvZiB0aGVcbiAgLy8gSXRlcmF0b3IgaW50ZXJmYWNlIGluIHRlcm1zIG9mIGEgc2luZ2xlIC5faW52b2tlIG1ldGhvZC5cbiAgZnVuY3Rpb24gZGVmaW5lSXRlcmF0b3JNZXRob2RzKHByb3RvdHlwZSkge1xuICAgIFtcIm5leHRcIiwgXCJ0aHJvd1wiLCBcInJldHVyblwiXS5mb3JFYWNoKGZ1bmN0aW9uKG1ldGhvZCkge1xuICAgICAgcHJvdG90eXBlW21ldGhvZF0gPSBmdW5jdGlvbihhcmcpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2ludm9rZShtZXRob2QsIGFyZyk7XG4gICAgICB9O1xuICAgIH0pO1xuICB9XG5cbiAgcnVudGltZS5pc0dlbmVyYXRvckZ1bmN0aW9uID0gZnVuY3Rpb24oZ2VuRnVuKSB7XG4gICAgdmFyIGN0b3IgPSB0eXBlb2YgZ2VuRnVuID09PSBcImZ1bmN0aW9uXCIgJiYgZ2VuRnVuLmNvbnN0cnVjdG9yO1xuICAgIHJldHVybiBjdG9yXG4gICAgICA/IGN0b3IgPT09IEdlbmVyYXRvckZ1bmN0aW9uIHx8XG4gICAgICAgIC8vIEZvciB0aGUgbmF0aXZlIEdlbmVyYXRvckZ1bmN0aW9uIGNvbnN0cnVjdG9yLCB0aGUgYmVzdCB3ZSBjYW5cbiAgICAgICAgLy8gZG8gaXMgdG8gY2hlY2sgaXRzIC5uYW1lIHByb3BlcnR5LlxuICAgICAgICAoY3Rvci5kaXNwbGF5TmFtZSB8fCBjdG9yLm5hbWUpID09PSBcIkdlbmVyYXRvckZ1bmN0aW9uXCJcbiAgICAgIDogZmFsc2U7XG4gIH07XG5cbiAgcnVudGltZS5tYXJrID0gZnVuY3Rpb24oZ2VuRnVuKSB7XG4gICAgaWYgKE9iamVjdC5zZXRQcm90b3R5cGVPZikge1xuICAgICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKGdlbkZ1biwgR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBnZW5GdW4uX19wcm90b19fID0gR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGU7XG4gICAgICBpZiAoISh0b1N0cmluZ1RhZ1N5bWJvbCBpbiBnZW5GdW4pKSB7XG4gICAgICAgIGdlbkZ1blt0b1N0cmluZ1RhZ1N5bWJvbF0gPSBcIkdlbmVyYXRvckZ1bmN0aW9uXCI7XG4gICAgICB9XG4gICAgfVxuICAgIGdlbkZ1bi5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEdwKTtcbiAgICByZXR1cm4gZ2VuRnVuO1xuICB9O1xuXG4gIC8vIFdpdGhpbiB0aGUgYm9keSBvZiBhbnkgYXN5bmMgZnVuY3Rpb24sIGBhd2FpdCB4YCBpcyB0cmFuc2Zvcm1lZCB0b1xuICAvLyBgeWllbGQgcmVnZW5lcmF0b3JSdW50aW1lLmF3cmFwKHgpYCwgc28gdGhhdCB0aGUgcnVudGltZSBjYW4gdGVzdFxuICAvLyBgaGFzT3duLmNhbGwodmFsdWUsIFwiX19hd2FpdFwiKWAgdG8gZGV0ZXJtaW5lIGlmIHRoZSB5aWVsZGVkIHZhbHVlIGlzXG4gIC8vIG1lYW50IHRvIGJlIGF3YWl0ZWQuXG4gIHJ1bnRpbWUuYXdyYXAgPSBmdW5jdGlvbihhcmcpIHtcbiAgICByZXR1cm4geyBfX2F3YWl0OiBhcmcgfTtcbiAgfTtcblxuICBmdW5jdGlvbiBBc3luY0l0ZXJhdG9yKGdlbmVyYXRvcikge1xuICAgIGZ1bmN0aW9uIGludm9rZShtZXRob2QsIGFyZywgcmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICB2YXIgcmVjb3JkID0gdHJ5Q2F0Y2goZ2VuZXJhdG9yW21ldGhvZF0sIGdlbmVyYXRvciwgYXJnKTtcbiAgICAgIGlmIChyZWNvcmQudHlwZSA9PT0gXCJ0aHJvd1wiKSB7XG4gICAgICAgIHJlamVjdChyZWNvcmQuYXJnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciByZXN1bHQgPSByZWNvcmQuYXJnO1xuICAgICAgICB2YXIgdmFsdWUgPSByZXN1bHQudmFsdWU7XG4gICAgICAgIGlmICh2YWx1ZSAmJlxuICAgICAgICAgICAgdHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiICYmXG4gICAgICAgICAgICBoYXNPd24uY2FsbCh2YWx1ZSwgXCJfX2F3YWl0XCIpKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh2YWx1ZS5fX2F3YWl0KS50aGVuKGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgICAgICBpbnZva2UoXCJuZXh0XCIsIHZhbHVlLCByZXNvbHZlLCByZWplY3QpO1xuICAgICAgICAgIH0sIGZ1bmN0aW9uKGVycikge1xuICAgICAgICAgICAgaW52b2tlKFwidGhyb3dcIiwgZXJyLCByZXNvbHZlLCByZWplY3QpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh2YWx1ZSkudGhlbihmdW5jdGlvbih1bndyYXBwZWQpIHtcbiAgICAgICAgICAvLyBXaGVuIGEgeWllbGRlZCBQcm9taXNlIGlzIHJlc29sdmVkLCBpdHMgZmluYWwgdmFsdWUgYmVjb21lc1xuICAgICAgICAgIC8vIHRoZSAudmFsdWUgb2YgdGhlIFByb21pc2U8e3ZhbHVlLGRvbmV9PiByZXN1bHQgZm9yIHRoZVxuICAgICAgICAgIC8vIGN1cnJlbnQgaXRlcmF0aW9uLiBJZiB0aGUgUHJvbWlzZSBpcyByZWplY3RlZCwgaG93ZXZlciwgdGhlXG4gICAgICAgICAgLy8gcmVzdWx0IGZvciB0aGlzIGl0ZXJhdGlvbiB3aWxsIGJlIHJlamVjdGVkIHdpdGggdGhlIHNhbWVcbiAgICAgICAgICAvLyByZWFzb24uIE5vdGUgdGhhdCByZWplY3Rpb25zIG9mIHlpZWxkZWQgUHJvbWlzZXMgYXJlIG5vdFxuICAgICAgICAgIC8vIHRocm93biBiYWNrIGludG8gdGhlIGdlbmVyYXRvciBmdW5jdGlvbiwgYXMgaXMgdGhlIGNhc2VcbiAgICAgICAgICAvLyB3aGVuIGFuIGF3YWl0ZWQgUHJvbWlzZSBpcyByZWplY3RlZC4gVGhpcyBkaWZmZXJlbmNlIGluXG4gICAgICAgICAgLy8gYmVoYXZpb3IgYmV0d2VlbiB5aWVsZCBhbmQgYXdhaXQgaXMgaW1wb3J0YW50LCBiZWNhdXNlIGl0XG4gICAgICAgICAgLy8gYWxsb3dzIHRoZSBjb25zdW1lciB0byBkZWNpZGUgd2hhdCB0byBkbyB3aXRoIHRoZSB5aWVsZGVkXG4gICAgICAgICAgLy8gcmVqZWN0aW9uIChzd2FsbG93IGl0IGFuZCBjb250aW51ZSwgbWFudWFsbHkgLnRocm93IGl0IGJhY2tcbiAgICAgICAgICAvLyBpbnRvIHRoZSBnZW5lcmF0b3IsIGFiYW5kb24gaXRlcmF0aW9uLCB3aGF0ZXZlcikuIFdpdGhcbiAgICAgICAgICAvLyBhd2FpdCwgYnkgY29udHJhc3QsIHRoZXJlIGlzIG5vIG9wcG9ydHVuaXR5IHRvIGV4YW1pbmUgdGhlXG4gICAgICAgICAgLy8gcmVqZWN0aW9uIHJlYXNvbiBvdXRzaWRlIHRoZSBnZW5lcmF0b3IgZnVuY3Rpb24sIHNvIHRoZVxuICAgICAgICAgIC8vIG9ubHkgb3B0aW9uIGlzIHRvIHRocm93IGl0IGZyb20gdGhlIGF3YWl0IGV4cHJlc3Npb24sIGFuZFxuICAgICAgICAgIC8vIGxldCB0aGUgZ2VuZXJhdG9yIGZ1bmN0aW9uIGhhbmRsZSB0aGUgZXhjZXB0aW9uLlxuICAgICAgICAgIHJlc3VsdC52YWx1ZSA9IHVud3JhcHBlZDtcbiAgICAgICAgICByZXNvbHZlKHJlc3VsdCk7XG4gICAgICAgIH0sIHJlamVjdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHByZXZpb3VzUHJvbWlzZTtcblxuICAgIGZ1bmN0aW9uIGVucXVldWUobWV0aG9kLCBhcmcpIHtcbiAgICAgIGZ1bmN0aW9uIGNhbGxJbnZva2VXaXRoTWV0aG9kQW5kQXJnKCkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgICAgaW52b2tlKG1ldGhvZCwgYXJnLCByZXNvbHZlLCByZWplY3QpO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHByZXZpb3VzUHJvbWlzZSA9XG4gICAgICAgIC8vIElmIGVucXVldWUgaGFzIGJlZW4gY2FsbGVkIGJlZm9yZSwgdGhlbiB3ZSB3YW50IHRvIHdhaXQgdW50aWxcbiAgICAgICAgLy8gYWxsIHByZXZpb3VzIFByb21pc2VzIGhhdmUgYmVlbiByZXNvbHZlZCBiZWZvcmUgY2FsbGluZyBpbnZva2UsXG4gICAgICAgIC8vIHNvIHRoYXQgcmVzdWx0cyBhcmUgYWx3YXlzIGRlbGl2ZXJlZCBpbiB0aGUgY29ycmVjdCBvcmRlci4gSWZcbiAgICAgICAgLy8gZW5xdWV1ZSBoYXMgbm90IGJlZW4gY2FsbGVkIGJlZm9yZSwgdGhlbiBpdCBpcyBpbXBvcnRhbnQgdG9cbiAgICAgICAgLy8gY2FsbCBpbnZva2UgaW1tZWRpYXRlbHksIHdpdGhvdXQgd2FpdGluZyBvbiBhIGNhbGxiYWNrIHRvIGZpcmUsXG4gICAgICAgIC8vIHNvIHRoYXQgdGhlIGFzeW5jIGdlbmVyYXRvciBmdW5jdGlvbiBoYXMgdGhlIG9wcG9ydHVuaXR5IHRvIGRvXG4gICAgICAgIC8vIGFueSBuZWNlc3Nhcnkgc2V0dXAgaW4gYSBwcmVkaWN0YWJsZSB3YXkuIFRoaXMgcHJlZGljdGFiaWxpdHlcbiAgICAgICAgLy8gaXMgd2h5IHRoZSBQcm9taXNlIGNvbnN0cnVjdG9yIHN5bmNocm9ub3VzbHkgaW52b2tlcyBpdHNcbiAgICAgICAgLy8gZXhlY3V0b3IgY2FsbGJhY2ssIGFuZCB3aHkgYXN5bmMgZnVuY3Rpb25zIHN5bmNocm9ub3VzbHlcbiAgICAgICAgLy8gZXhlY3V0ZSBjb2RlIGJlZm9yZSB0aGUgZmlyc3QgYXdhaXQuIFNpbmNlIHdlIGltcGxlbWVudCBzaW1wbGVcbiAgICAgICAgLy8gYXN5bmMgZnVuY3Rpb25zIGluIHRlcm1zIG9mIGFzeW5jIGdlbmVyYXRvcnMsIGl0IGlzIGVzcGVjaWFsbHlcbiAgICAgICAgLy8gaW1wb3J0YW50IHRvIGdldCB0aGlzIHJpZ2h0LCBldmVuIHRob3VnaCBpdCByZXF1aXJlcyBjYXJlLlxuICAgICAgICBwcmV2aW91c1Byb21pc2UgPyBwcmV2aW91c1Byb21pc2UudGhlbihcbiAgICAgICAgICBjYWxsSW52b2tlV2l0aE1ldGhvZEFuZEFyZyxcbiAgICAgICAgICAvLyBBdm9pZCBwcm9wYWdhdGluZyBmYWlsdXJlcyB0byBQcm9taXNlcyByZXR1cm5lZCBieSBsYXRlclxuICAgICAgICAgIC8vIGludm9jYXRpb25zIG9mIHRoZSBpdGVyYXRvci5cbiAgICAgICAgICBjYWxsSW52b2tlV2l0aE1ldGhvZEFuZEFyZ1xuICAgICAgICApIDogY2FsbEludm9rZVdpdGhNZXRob2RBbmRBcmcoKTtcbiAgICB9XG5cbiAgICAvLyBEZWZpbmUgdGhlIHVuaWZpZWQgaGVscGVyIG1ldGhvZCB0aGF0IGlzIHVzZWQgdG8gaW1wbGVtZW50IC5uZXh0LFxuICAgIC8vIC50aHJvdywgYW5kIC5yZXR1cm4gKHNlZSBkZWZpbmVJdGVyYXRvck1ldGhvZHMpLlxuICAgIHRoaXMuX2ludm9rZSA9IGVucXVldWU7XG4gIH1cblxuICBkZWZpbmVJdGVyYXRvck1ldGhvZHMoQXN5bmNJdGVyYXRvci5wcm90b3R5cGUpO1xuICBBc3luY0l0ZXJhdG9yLnByb3RvdHlwZVthc3luY0l0ZXJhdG9yU3ltYm9sXSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcztcbiAgfTtcbiAgcnVudGltZS5Bc3luY0l0ZXJhdG9yID0gQXN5bmNJdGVyYXRvcjtcblxuICAvLyBOb3RlIHRoYXQgc2ltcGxlIGFzeW5jIGZ1bmN0aW9ucyBhcmUgaW1wbGVtZW50ZWQgb24gdG9wIG9mXG4gIC8vIEFzeW5jSXRlcmF0b3Igb2JqZWN0czsgdGhleSBqdXN0IHJldHVybiBhIFByb21pc2UgZm9yIHRoZSB2YWx1ZSBvZlxuICAvLyB0aGUgZmluYWwgcmVzdWx0IHByb2R1Y2VkIGJ5IHRoZSBpdGVyYXRvci5cbiAgcnVudGltZS5hc3luYyA9IGZ1bmN0aW9uKGlubmVyRm4sIG91dGVyRm4sIHNlbGYsIHRyeUxvY3NMaXN0KSB7XG4gICAgdmFyIGl0ZXIgPSBuZXcgQXN5bmNJdGVyYXRvcihcbiAgICAgIHdyYXAoaW5uZXJGbiwgb3V0ZXJGbiwgc2VsZiwgdHJ5TG9jc0xpc3QpXG4gICAgKTtcblxuICAgIHJldHVybiBydW50aW1lLmlzR2VuZXJhdG9yRnVuY3Rpb24ob3V0ZXJGbilcbiAgICAgID8gaXRlciAvLyBJZiBvdXRlckZuIGlzIGEgZ2VuZXJhdG9yLCByZXR1cm4gdGhlIGZ1bGwgaXRlcmF0b3IuXG4gICAgICA6IGl0ZXIubmV4dCgpLnRoZW4oZnVuY3Rpb24ocmVzdWx0KSB7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdC5kb25lID8gcmVzdWx0LnZhbHVlIDogaXRlci5uZXh0KCk7XG4gICAgICAgIH0pO1xuICB9O1xuXG4gIGZ1bmN0aW9uIG1ha2VJbnZva2VNZXRob2QoaW5uZXJGbiwgc2VsZiwgY29udGV4dCkge1xuICAgIHZhciBzdGF0ZSA9IEdlblN0YXRlU3VzcGVuZGVkU3RhcnQ7XG5cbiAgICByZXR1cm4gZnVuY3Rpb24gaW52b2tlKG1ldGhvZCwgYXJnKSB7XG4gICAgICBpZiAoc3RhdGUgPT09IEdlblN0YXRlRXhlY3V0aW5nKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IHJ1bm5pbmdcIik7XG4gICAgICB9XG5cbiAgICAgIGlmIChzdGF0ZSA9PT0gR2VuU3RhdGVDb21wbGV0ZWQpIHtcbiAgICAgICAgaWYgKG1ldGhvZCA9PT0gXCJ0aHJvd1wiKSB7XG4gICAgICAgICAgdGhyb3cgYXJnO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQmUgZm9yZ2l2aW5nLCBwZXIgMjUuMy4zLjMuMyBvZiB0aGUgc3BlYzpcbiAgICAgICAgLy8gaHR0cHM6Ly9wZW9wbGUubW96aWxsYS5vcmcvfmpvcmVuZG9yZmYvZXM2LWRyYWZ0Lmh0bWwjc2VjLWdlbmVyYXRvcnJlc3VtZVxuICAgICAgICByZXR1cm4gZG9uZVJlc3VsdCgpO1xuICAgICAgfVxuXG4gICAgICBjb250ZXh0Lm1ldGhvZCA9IG1ldGhvZDtcbiAgICAgIGNvbnRleHQuYXJnID0gYXJnO1xuXG4gICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICB2YXIgZGVsZWdhdGUgPSBjb250ZXh0LmRlbGVnYXRlO1xuICAgICAgICBpZiAoZGVsZWdhdGUpIHtcbiAgICAgICAgICB2YXIgZGVsZWdhdGVSZXN1bHQgPSBtYXliZUludm9rZURlbGVnYXRlKGRlbGVnYXRlLCBjb250ZXh0KTtcbiAgICAgICAgICBpZiAoZGVsZWdhdGVSZXN1bHQpIHtcbiAgICAgICAgICAgIGlmIChkZWxlZ2F0ZVJlc3VsdCA9PT0gQ29udGludWVTZW50aW5lbCkgY29udGludWU7XG4gICAgICAgICAgICByZXR1cm4gZGVsZWdhdGVSZXN1bHQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNvbnRleHQubWV0aG9kID09PSBcIm5leHRcIikge1xuICAgICAgICAgIC8vIFNldHRpbmcgY29udGV4dC5fc2VudCBmb3IgbGVnYWN5IHN1cHBvcnQgb2YgQmFiZWwnc1xuICAgICAgICAgIC8vIGZ1bmN0aW9uLnNlbnQgaW1wbGVtZW50YXRpb24uXG4gICAgICAgICAgY29udGV4dC5zZW50ID0gY29udGV4dC5fc2VudCA9IGNvbnRleHQuYXJnO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoY29udGV4dC5tZXRob2QgPT09IFwidGhyb3dcIikge1xuICAgICAgICAgIGlmIChzdGF0ZSA9PT0gR2VuU3RhdGVTdXNwZW5kZWRTdGFydCkge1xuICAgICAgICAgICAgc3RhdGUgPSBHZW5TdGF0ZUNvbXBsZXRlZDtcbiAgICAgICAgICAgIHRocm93IGNvbnRleHQuYXJnO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnRleHQuZGlzcGF0Y2hFeGNlcHRpb24oY29udGV4dC5hcmcpO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoY29udGV4dC5tZXRob2QgPT09IFwicmV0dXJuXCIpIHtcbiAgICAgICAgICBjb250ZXh0LmFicnVwdChcInJldHVyblwiLCBjb250ZXh0LmFyZyk7XG4gICAgICAgIH1cblxuICAgICAgICBzdGF0ZSA9IEdlblN0YXRlRXhlY3V0aW5nO1xuXG4gICAgICAgIHZhciByZWNvcmQgPSB0cnlDYXRjaChpbm5lckZuLCBzZWxmLCBjb250ZXh0KTtcbiAgICAgICAgaWYgKHJlY29yZC50eXBlID09PSBcIm5vcm1hbFwiKSB7XG4gICAgICAgICAgLy8gSWYgYW4gZXhjZXB0aW9uIGlzIHRocm93biBmcm9tIGlubmVyRm4sIHdlIGxlYXZlIHN0YXRlID09PVxuICAgICAgICAgIC8vIEdlblN0YXRlRXhlY3V0aW5nIGFuZCBsb29wIGJhY2sgZm9yIGFub3RoZXIgaW52b2NhdGlvbi5cbiAgICAgICAgICBzdGF0ZSA9IGNvbnRleHQuZG9uZVxuICAgICAgICAgICAgPyBHZW5TdGF0ZUNvbXBsZXRlZFxuICAgICAgICAgICAgOiBHZW5TdGF0ZVN1c3BlbmRlZFlpZWxkO1xuXG4gICAgICAgICAgaWYgKHJlY29yZC5hcmcgPT09IENvbnRpbnVlU2VudGluZWwpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB2YWx1ZTogcmVjb3JkLmFyZyxcbiAgICAgICAgICAgIGRvbmU6IGNvbnRleHQuZG9uZVxuICAgICAgICAgIH07XG5cbiAgICAgICAgfSBlbHNlIGlmIChyZWNvcmQudHlwZSA9PT0gXCJ0aHJvd1wiKSB7XG4gICAgICAgICAgc3RhdGUgPSBHZW5TdGF0ZUNvbXBsZXRlZDtcbiAgICAgICAgICAvLyBEaXNwYXRjaCB0aGUgZXhjZXB0aW9uIGJ5IGxvb3BpbmcgYmFjayBhcm91bmQgdG8gdGhlXG4gICAgICAgICAgLy8gY29udGV4dC5kaXNwYXRjaEV4Y2VwdGlvbihjb250ZXh0LmFyZykgY2FsbCBhYm92ZS5cbiAgICAgICAgICBjb250ZXh0Lm1ldGhvZCA9IFwidGhyb3dcIjtcbiAgICAgICAgICBjb250ZXh0LmFyZyA9IHJlY29yZC5hcmc7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgLy8gQ2FsbCBkZWxlZ2F0ZS5pdGVyYXRvcltjb250ZXh0Lm1ldGhvZF0oY29udGV4dC5hcmcpIGFuZCBoYW5kbGUgdGhlXG4gIC8vIHJlc3VsdCwgZWl0aGVyIGJ5IHJldHVybmluZyBhIHsgdmFsdWUsIGRvbmUgfSByZXN1bHQgZnJvbSB0aGVcbiAgLy8gZGVsZWdhdGUgaXRlcmF0b3IsIG9yIGJ5IG1vZGlmeWluZyBjb250ZXh0Lm1ldGhvZCBhbmQgY29udGV4dC5hcmcsXG4gIC8vIHNldHRpbmcgY29udGV4dC5kZWxlZ2F0ZSB0byBudWxsLCBhbmQgcmV0dXJuaW5nIHRoZSBDb250aW51ZVNlbnRpbmVsLlxuICBmdW5jdGlvbiBtYXliZUludm9rZURlbGVnYXRlKGRlbGVnYXRlLCBjb250ZXh0KSB7XG4gICAgdmFyIG1ldGhvZCA9IGRlbGVnYXRlLml0ZXJhdG9yW2NvbnRleHQubWV0aG9kXTtcbiAgICBpZiAobWV0aG9kID09PSB1bmRlZmluZWQpIHtcbiAgICAgIC8vIEEgLnRocm93IG9yIC5yZXR1cm4gd2hlbiB0aGUgZGVsZWdhdGUgaXRlcmF0b3IgaGFzIG5vIC50aHJvd1xuICAgICAgLy8gbWV0aG9kIGFsd2F5cyB0ZXJtaW5hdGVzIHRoZSB5aWVsZCogbG9vcC5cbiAgICAgIGNvbnRleHQuZGVsZWdhdGUgPSBudWxsO1xuXG4gICAgICBpZiAoY29udGV4dC5tZXRob2QgPT09IFwidGhyb3dcIikge1xuICAgICAgICBpZiAoZGVsZWdhdGUuaXRlcmF0b3IucmV0dXJuKSB7XG4gICAgICAgICAgLy8gSWYgdGhlIGRlbGVnYXRlIGl0ZXJhdG9yIGhhcyBhIHJldHVybiBtZXRob2QsIGdpdmUgaXQgYVxuICAgICAgICAgIC8vIGNoYW5jZSB0byBjbGVhbiB1cC5cbiAgICAgICAgICBjb250ZXh0Lm1ldGhvZCA9IFwicmV0dXJuXCI7XG4gICAgICAgICAgY29udGV4dC5hcmcgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgbWF5YmVJbnZva2VEZWxlZ2F0ZShkZWxlZ2F0ZSwgY29udGV4dCk7XG5cbiAgICAgICAgICBpZiAoY29udGV4dC5tZXRob2QgPT09IFwidGhyb3dcIikge1xuICAgICAgICAgICAgLy8gSWYgbWF5YmVJbnZva2VEZWxlZ2F0ZShjb250ZXh0KSBjaGFuZ2VkIGNvbnRleHQubWV0aG9kIGZyb21cbiAgICAgICAgICAgIC8vIFwicmV0dXJuXCIgdG8gXCJ0aHJvd1wiLCBsZXQgdGhhdCBvdmVycmlkZSB0aGUgVHlwZUVycm9yIGJlbG93LlxuICAgICAgICAgICAgcmV0dXJuIENvbnRpbnVlU2VudGluZWw7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29udGV4dC5tZXRob2QgPSBcInRocm93XCI7XG4gICAgICAgIGNvbnRleHQuYXJnID0gbmV3IFR5cGVFcnJvcihcbiAgICAgICAgICBcIlRoZSBpdGVyYXRvciBkb2VzIG5vdCBwcm92aWRlIGEgJ3Rocm93JyBtZXRob2RcIik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBDb250aW51ZVNlbnRpbmVsO1xuICAgIH1cblxuICAgIHZhciByZWNvcmQgPSB0cnlDYXRjaChtZXRob2QsIGRlbGVnYXRlLml0ZXJhdG9yLCBjb250ZXh0LmFyZyk7XG5cbiAgICBpZiAocmVjb3JkLnR5cGUgPT09IFwidGhyb3dcIikge1xuICAgICAgY29udGV4dC5tZXRob2QgPSBcInRocm93XCI7XG4gICAgICBjb250ZXh0LmFyZyA9IHJlY29yZC5hcmc7XG4gICAgICBjb250ZXh0LmRlbGVnYXRlID0gbnVsbDtcbiAgICAgIHJldHVybiBDb250aW51ZVNlbnRpbmVsO1xuICAgIH1cblxuICAgIHZhciBpbmZvID0gcmVjb3JkLmFyZztcblxuICAgIGlmICghIGluZm8pIHtcbiAgICAgIGNvbnRleHQubWV0aG9kID0gXCJ0aHJvd1wiO1xuICAgICAgY29udGV4dC5hcmcgPSBuZXcgVHlwZUVycm9yKFwiaXRlcmF0b3IgcmVzdWx0IGlzIG5vdCBhbiBvYmplY3RcIik7XG4gICAgICBjb250ZXh0LmRlbGVnYXRlID0gbnVsbDtcbiAgICAgIHJldHVybiBDb250aW51ZVNlbnRpbmVsO1xuICAgIH1cblxuICAgIGlmIChpbmZvLmRvbmUpIHtcbiAgICAgIC8vIEFzc2lnbiB0aGUgcmVzdWx0IG9mIHRoZSBmaW5pc2hlZCBkZWxlZ2F0ZSB0byB0aGUgdGVtcG9yYXJ5XG4gICAgICAvLyB2YXJpYWJsZSBzcGVjaWZpZWQgYnkgZGVsZWdhdGUucmVzdWx0TmFtZSAoc2VlIGRlbGVnYXRlWWllbGQpLlxuICAgICAgY29udGV4dFtkZWxlZ2F0ZS5yZXN1bHROYW1lXSA9IGluZm8udmFsdWU7XG5cbiAgICAgIC8vIFJlc3VtZSBleGVjdXRpb24gYXQgdGhlIGRlc2lyZWQgbG9jYXRpb24gKHNlZSBkZWxlZ2F0ZVlpZWxkKS5cbiAgICAgIGNvbnRleHQubmV4dCA9IGRlbGVnYXRlLm5leHRMb2M7XG5cbiAgICAgIC8vIElmIGNvbnRleHQubWV0aG9kIHdhcyBcInRocm93XCIgYnV0IHRoZSBkZWxlZ2F0ZSBoYW5kbGVkIHRoZVxuICAgICAgLy8gZXhjZXB0aW9uLCBsZXQgdGhlIG91dGVyIGdlbmVyYXRvciBwcm9jZWVkIG5vcm1hbGx5LiBJZlxuICAgICAgLy8gY29udGV4dC5tZXRob2Qgd2FzIFwibmV4dFwiLCBmb3JnZXQgY29udGV4dC5hcmcgc2luY2UgaXQgaGFzIGJlZW5cbiAgICAgIC8vIFwiY29uc3VtZWRcIiBieSB0aGUgZGVsZWdhdGUgaXRlcmF0b3IuIElmIGNvbnRleHQubWV0aG9kIHdhc1xuICAgICAgLy8gXCJyZXR1cm5cIiwgYWxsb3cgdGhlIG9yaWdpbmFsIC5yZXR1cm4gY2FsbCB0byBjb250aW51ZSBpbiB0aGVcbiAgICAgIC8vIG91dGVyIGdlbmVyYXRvci5cbiAgICAgIGlmIChjb250ZXh0Lm1ldGhvZCAhPT0gXCJyZXR1cm5cIikge1xuICAgICAgICBjb250ZXh0Lm1ldGhvZCA9IFwibmV4dFwiO1xuICAgICAgICBjb250ZXh0LmFyZyA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBSZS15aWVsZCB0aGUgcmVzdWx0IHJldHVybmVkIGJ5IHRoZSBkZWxlZ2F0ZSBtZXRob2QuXG4gICAgICByZXR1cm4gaW5mbztcbiAgICB9XG5cbiAgICAvLyBUaGUgZGVsZWdhdGUgaXRlcmF0b3IgaXMgZmluaXNoZWQsIHNvIGZvcmdldCBpdCBhbmQgY29udGludWUgd2l0aFxuICAgIC8vIHRoZSBvdXRlciBnZW5lcmF0b3IuXG4gICAgY29udGV4dC5kZWxlZ2F0ZSA9IG51bGw7XG4gICAgcmV0dXJuIENvbnRpbnVlU2VudGluZWw7XG4gIH1cblxuICAvLyBEZWZpbmUgR2VuZXJhdG9yLnByb3RvdHlwZS57bmV4dCx0aHJvdyxyZXR1cm59IGluIHRlcm1zIG9mIHRoZVxuICAvLyB1bmlmaWVkIC5faW52b2tlIGhlbHBlciBtZXRob2QuXG4gIGRlZmluZUl0ZXJhdG9yTWV0aG9kcyhHcCk7XG5cbiAgR3BbdG9TdHJpbmdUYWdTeW1ib2xdID0gXCJHZW5lcmF0b3JcIjtcblxuICAvLyBBIEdlbmVyYXRvciBzaG91bGQgYWx3YXlzIHJldHVybiBpdHNlbGYgYXMgdGhlIGl0ZXJhdG9yIG9iamVjdCB3aGVuIHRoZVxuICAvLyBAQGl0ZXJhdG9yIGZ1bmN0aW9uIGlzIGNhbGxlZCBvbiBpdC4gU29tZSBicm93c2VycycgaW1wbGVtZW50YXRpb25zIG9mIHRoZVxuICAvLyBpdGVyYXRvciBwcm90b3R5cGUgY2hhaW4gaW5jb3JyZWN0bHkgaW1wbGVtZW50IHRoaXMsIGNhdXNpbmcgdGhlIEdlbmVyYXRvclxuICAvLyBvYmplY3QgdG8gbm90IGJlIHJldHVybmVkIGZyb20gdGhpcyBjYWxsLiBUaGlzIGVuc3VyZXMgdGhhdCBkb2Vzbid0IGhhcHBlbi5cbiAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9mYWNlYm9vay9yZWdlbmVyYXRvci9pc3N1ZXMvMjc0IGZvciBtb3JlIGRldGFpbHMuXG4gIEdwW2l0ZXJhdG9yU3ltYm9sXSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzO1xuICB9O1xuXG4gIEdwLnRvU3RyaW5nID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIFwiW29iamVjdCBHZW5lcmF0b3JdXCI7XG4gIH07XG5cbiAgZnVuY3Rpb24gcHVzaFRyeUVudHJ5KGxvY3MpIHtcbiAgICB2YXIgZW50cnkgPSB7IHRyeUxvYzogbG9jc1swXSB9O1xuXG4gICAgaWYgKDEgaW4gbG9jcykge1xuICAgICAgZW50cnkuY2F0Y2hMb2MgPSBsb2NzWzFdO1xuICAgIH1cblxuICAgIGlmICgyIGluIGxvY3MpIHtcbiAgICAgIGVudHJ5LmZpbmFsbHlMb2MgPSBsb2NzWzJdO1xuICAgICAgZW50cnkuYWZ0ZXJMb2MgPSBsb2NzWzNdO1xuICAgIH1cblxuICAgIHRoaXMudHJ5RW50cmllcy5wdXNoKGVudHJ5KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlc2V0VHJ5RW50cnkoZW50cnkpIHtcbiAgICB2YXIgcmVjb3JkID0gZW50cnkuY29tcGxldGlvbiB8fCB7fTtcbiAgICByZWNvcmQudHlwZSA9IFwibm9ybWFsXCI7XG4gICAgZGVsZXRlIHJlY29yZC5hcmc7XG4gICAgZW50cnkuY29tcGxldGlvbiA9IHJlY29yZDtcbiAgfVxuXG4gIGZ1bmN0aW9uIENvbnRleHQodHJ5TG9jc0xpc3QpIHtcbiAgICAvLyBUaGUgcm9vdCBlbnRyeSBvYmplY3QgKGVmZmVjdGl2ZWx5IGEgdHJ5IHN0YXRlbWVudCB3aXRob3V0IGEgY2F0Y2hcbiAgICAvLyBvciBhIGZpbmFsbHkgYmxvY2spIGdpdmVzIHVzIGEgcGxhY2UgdG8gc3RvcmUgdmFsdWVzIHRocm93biBmcm9tXG4gICAgLy8gbG9jYXRpb25zIHdoZXJlIHRoZXJlIGlzIG5vIGVuY2xvc2luZyB0cnkgc3RhdGVtZW50LlxuICAgIHRoaXMudHJ5RW50cmllcyA9IFt7IHRyeUxvYzogXCJyb290XCIgfV07XG4gICAgdHJ5TG9jc0xpc3QuZm9yRWFjaChwdXNoVHJ5RW50cnksIHRoaXMpO1xuICAgIHRoaXMucmVzZXQodHJ1ZSk7XG4gIH1cblxuICBydW50aW1lLmtleXMgPSBmdW5jdGlvbihvYmplY3QpIHtcbiAgICB2YXIga2V5cyA9IFtdO1xuICAgIGZvciAodmFyIGtleSBpbiBvYmplY3QpIHtcbiAgICAgIGtleXMucHVzaChrZXkpO1xuICAgIH1cbiAgICBrZXlzLnJldmVyc2UoKTtcblxuICAgIC8vIFJhdGhlciB0aGFuIHJldHVybmluZyBhbiBvYmplY3Qgd2l0aCBhIG5leHQgbWV0aG9kLCB3ZSBrZWVwXG4gICAgLy8gdGhpbmdzIHNpbXBsZSBhbmQgcmV0dXJuIHRoZSBuZXh0IGZ1bmN0aW9uIGl0c2VsZi5cbiAgICByZXR1cm4gZnVuY3Rpb24gbmV4dCgpIHtcbiAgICAgIHdoaWxlIChrZXlzLmxlbmd0aCkge1xuICAgICAgICB2YXIga2V5ID0ga2V5cy5wb3AoKTtcbiAgICAgICAgaWYgKGtleSBpbiBvYmplY3QpIHtcbiAgICAgICAgICBuZXh0LnZhbHVlID0ga2V5O1xuICAgICAgICAgIG5leHQuZG9uZSA9IGZhbHNlO1xuICAgICAgICAgIHJldHVybiBuZXh0O1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIFRvIGF2b2lkIGNyZWF0aW5nIGFuIGFkZGl0aW9uYWwgb2JqZWN0LCB3ZSBqdXN0IGhhbmcgdGhlIC52YWx1ZVxuICAgICAgLy8gYW5kIC5kb25lIHByb3BlcnRpZXMgb2ZmIHRoZSBuZXh0IGZ1bmN0aW9uIG9iamVjdCBpdHNlbGYuIFRoaXNcbiAgICAgIC8vIGFsc28gZW5zdXJlcyB0aGF0IHRoZSBtaW5pZmllciB3aWxsIG5vdCBhbm9ueW1pemUgdGhlIGZ1bmN0aW9uLlxuICAgICAgbmV4dC5kb25lID0gdHJ1ZTtcbiAgICAgIHJldHVybiBuZXh0O1xuICAgIH07XG4gIH07XG5cbiAgZnVuY3Rpb24gdmFsdWVzKGl0ZXJhYmxlKSB7XG4gICAgaWYgKGl0ZXJhYmxlKSB7XG4gICAgICB2YXIgaXRlcmF0b3JNZXRob2QgPSBpdGVyYWJsZVtpdGVyYXRvclN5bWJvbF07XG4gICAgICBpZiAoaXRlcmF0b3JNZXRob2QpIHtcbiAgICAgICAgcmV0dXJuIGl0ZXJhdG9yTWV0aG9kLmNhbGwoaXRlcmFibGUpO1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIGl0ZXJhYmxlLm5leHQgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICByZXR1cm4gaXRlcmFibGU7XG4gICAgICB9XG5cbiAgICAgIGlmICghaXNOYU4oaXRlcmFibGUubGVuZ3RoKSkge1xuICAgICAgICB2YXIgaSA9IC0xLCBuZXh0ID0gZnVuY3Rpb24gbmV4dCgpIHtcbiAgICAgICAgICB3aGlsZSAoKytpIDwgaXRlcmFibGUubGVuZ3RoKSB7XG4gICAgICAgICAgICBpZiAoaGFzT3duLmNhbGwoaXRlcmFibGUsIGkpKSB7XG4gICAgICAgICAgICAgIG5leHQudmFsdWUgPSBpdGVyYWJsZVtpXTtcbiAgICAgICAgICAgICAgbmV4dC5kb25lID0gZmFsc2U7XG4gICAgICAgICAgICAgIHJldHVybiBuZXh0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIG5leHQudmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgbmV4dC5kb25lID0gdHJ1ZTtcblxuICAgICAgICAgIHJldHVybiBuZXh0O1xuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiBuZXh0Lm5leHQgPSBuZXh0O1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFJldHVybiBhbiBpdGVyYXRvciB3aXRoIG5vIHZhbHVlcy5cbiAgICByZXR1cm4geyBuZXh0OiBkb25lUmVzdWx0IH07XG4gIH1cbiAgcnVudGltZS52YWx1ZXMgPSB2YWx1ZXM7XG5cbiAgZnVuY3Rpb24gZG9uZVJlc3VsdCgpIHtcbiAgICByZXR1cm4geyB2YWx1ZTogdW5kZWZpbmVkLCBkb25lOiB0cnVlIH07XG4gIH1cblxuICBDb250ZXh0LnByb3RvdHlwZSA9IHtcbiAgICBjb25zdHJ1Y3RvcjogQ29udGV4dCxcblxuICAgIHJlc2V0OiBmdW5jdGlvbihza2lwVGVtcFJlc2V0KSB7XG4gICAgICB0aGlzLnByZXYgPSAwO1xuICAgICAgdGhpcy5uZXh0ID0gMDtcbiAgICAgIC8vIFJlc2V0dGluZyBjb250ZXh0Ll9zZW50IGZvciBsZWdhY3kgc3VwcG9ydCBvZiBCYWJlbCdzXG4gICAgICAvLyBmdW5jdGlvbi5zZW50IGltcGxlbWVudGF0aW9uLlxuICAgICAgdGhpcy5zZW50ID0gdGhpcy5fc2VudCA9IHVuZGVmaW5lZDtcbiAgICAgIHRoaXMuZG9uZSA9IGZhbHNlO1xuICAgICAgdGhpcy5kZWxlZ2F0ZSA9IG51bGw7XG5cbiAgICAgIHRoaXMubWV0aG9kID0gXCJuZXh0XCI7XG4gICAgICB0aGlzLmFyZyA9IHVuZGVmaW5lZDtcblxuICAgICAgdGhpcy50cnlFbnRyaWVzLmZvckVhY2gocmVzZXRUcnlFbnRyeSk7XG5cbiAgICAgIGlmICghc2tpcFRlbXBSZXNldCkge1xuICAgICAgICBmb3IgKHZhciBuYW1lIGluIHRoaXMpIHtcbiAgICAgICAgICAvLyBOb3Qgc3VyZSBhYm91dCB0aGUgb3B0aW1hbCBvcmRlciBvZiB0aGVzZSBjb25kaXRpb25zOlxuICAgICAgICAgIGlmIChuYW1lLmNoYXJBdCgwKSA9PT0gXCJ0XCIgJiZcbiAgICAgICAgICAgICAgaGFzT3duLmNhbGwodGhpcywgbmFtZSkgJiZcbiAgICAgICAgICAgICAgIWlzTmFOKCtuYW1lLnNsaWNlKDEpKSkge1xuICAgICAgICAgICAgdGhpc1tuYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuXG4gICAgc3RvcDogZnVuY3Rpb24oKSB7XG4gICAgICB0aGlzLmRvbmUgPSB0cnVlO1xuXG4gICAgICB2YXIgcm9vdEVudHJ5ID0gdGhpcy50cnlFbnRyaWVzWzBdO1xuICAgICAgdmFyIHJvb3RSZWNvcmQgPSByb290RW50cnkuY29tcGxldGlvbjtcbiAgICAgIGlmIChyb290UmVjb3JkLnR5cGUgPT09IFwidGhyb3dcIikge1xuICAgICAgICB0aHJvdyByb290UmVjb3JkLmFyZztcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMucnZhbDtcbiAgICB9LFxuXG4gICAgZGlzcGF0Y2hFeGNlcHRpb246IGZ1bmN0aW9uKGV4Y2VwdGlvbikge1xuICAgICAgaWYgKHRoaXMuZG9uZSkge1xuICAgICAgICB0aHJvdyBleGNlcHRpb247XG4gICAgICB9XG5cbiAgICAgIHZhciBjb250ZXh0ID0gdGhpcztcbiAgICAgIGZ1bmN0aW9uIGhhbmRsZShsb2MsIGNhdWdodCkge1xuICAgICAgICByZWNvcmQudHlwZSA9IFwidGhyb3dcIjtcbiAgICAgICAgcmVjb3JkLmFyZyA9IGV4Y2VwdGlvbjtcbiAgICAgICAgY29udGV4dC5uZXh0ID0gbG9jO1xuXG4gICAgICAgIGlmIChjYXVnaHQpIHtcbiAgICAgICAgICAvLyBJZiB0aGUgZGlzcGF0Y2hlZCBleGNlcHRpb24gd2FzIGNhdWdodCBieSBhIGNhdGNoIGJsb2NrLFxuICAgICAgICAgIC8vIHRoZW4gbGV0IHRoYXQgY2F0Y2ggYmxvY2sgaGFuZGxlIHRoZSBleGNlcHRpb24gbm9ybWFsbHkuXG4gICAgICAgICAgY29udGV4dC5tZXRob2QgPSBcIm5leHRcIjtcbiAgICAgICAgICBjb250ZXh0LmFyZyA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAhISBjYXVnaHQ7XG4gICAgICB9XG5cbiAgICAgIGZvciAodmFyIGkgPSB0aGlzLnRyeUVudHJpZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgICAgdmFyIGVudHJ5ID0gdGhpcy50cnlFbnRyaWVzW2ldO1xuICAgICAgICB2YXIgcmVjb3JkID0gZW50cnkuY29tcGxldGlvbjtcblxuICAgICAgICBpZiAoZW50cnkudHJ5TG9jID09PSBcInJvb3RcIikge1xuICAgICAgICAgIC8vIEV4Y2VwdGlvbiB0aHJvd24gb3V0c2lkZSBvZiBhbnkgdHJ5IGJsb2NrIHRoYXQgY291bGQgaGFuZGxlXG4gICAgICAgICAgLy8gaXQsIHNvIHNldCB0aGUgY29tcGxldGlvbiB2YWx1ZSBvZiB0aGUgZW50aXJlIGZ1bmN0aW9uIHRvXG4gICAgICAgICAgLy8gdGhyb3cgdGhlIGV4Y2VwdGlvbi5cbiAgICAgICAgICByZXR1cm4gaGFuZGxlKFwiZW5kXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGVudHJ5LnRyeUxvYyA8PSB0aGlzLnByZXYpIHtcbiAgICAgICAgICB2YXIgaGFzQ2F0Y2ggPSBoYXNPd24uY2FsbChlbnRyeSwgXCJjYXRjaExvY1wiKTtcbiAgICAgICAgICB2YXIgaGFzRmluYWxseSA9IGhhc093bi5jYWxsKGVudHJ5LCBcImZpbmFsbHlMb2NcIik7XG5cbiAgICAgICAgICBpZiAoaGFzQ2F0Y2ggJiYgaGFzRmluYWxseSkge1xuICAgICAgICAgICAgaWYgKHRoaXMucHJldiA8IGVudHJ5LmNhdGNoTG9jKSB7XG4gICAgICAgICAgICAgIHJldHVybiBoYW5kbGUoZW50cnkuY2F0Y2hMb2MsIHRydWUpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnByZXYgPCBlbnRyeS5maW5hbGx5TG9jKSB7XG4gICAgICAgICAgICAgIHJldHVybiBoYW5kbGUoZW50cnkuZmluYWxseUxvYyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICB9IGVsc2UgaWYgKGhhc0NhdGNoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5wcmV2IDwgZW50cnkuY2F0Y2hMb2MpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGhhbmRsZShlbnRyeS5jYXRjaExvYywgdHJ1ZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICB9IGVsc2UgaWYgKGhhc0ZpbmFsbHkpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnByZXYgPCBlbnRyeS5maW5hbGx5TG9jKSB7XG4gICAgICAgICAgICAgIHJldHVybiBoYW5kbGUoZW50cnkuZmluYWxseUxvYyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidHJ5IHN0YXRlbWVudCB3aXRob3V0IGNhdGNoIG9yIGZpbmFsbHlcIik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcblxuICAgIGFicnVwdDogZnVuY3Rpb24odHlwZSwgYXJnKSB7XG4gICAgICBmb3IgKHZhciBpID0gdGhpcy50cnlFbnRyaWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgIHZhciBlbnRyeSA9IHRoaXMudHJ5RW50cmllc1tpXTtcbiAgICAgICAgaWYgKGVudHJ5LnRyeUxvYyA8PSB0aGlzLnByZXYgJiZcbiAgICAgICAgICAgIGhhc093bi5jYWxsKGVudHJ5LCBcImZpbmFsbHlMb2NcIikgJiZcbiAgICAgICAgICAgIHRoaXMucHJldiA8IGVudHJ5LmZpbmFsbHlMb2MpIHtcbiAgICAgICAgICB2YXIgZmluYWxseUVudHJ5ID0gZW50cnk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGZpbmFsbHlFbnRyeSAmJlxuICAgICAgICAgICh0eXBlID09PSBcImJyZWFrXCIgfHxcbiAgICAgICAgICAgdHlwZSA9PT0gXCJjb250aW51ZVwiKSAmJlxuICAgICAgICAgIGZpbmFsbHlFbnRyeS50cnlMb2MgPD0gYXJnICYmXG4gICAgICAgICAgYXJnIDw9IGZpbmFsbHlFbnRyeS5maW5hbGx5TG9jKSB7XG4gICAgICAgIC8vIElnbm9yZSB0aGUgZmluYWxseSBlbnRyeSBpZiBjb250cm9sIGlzIG5vdCBqdW1waW5nIHRvIGFcbiAgICAgICAgLy8gbG9jYXRpb24gb3V0c2lkZSB0aGUgdHJ5L2NhdGNoIGJsb2NrLlxuICAgICAgICBmaW5hbGx5RW50cnkgPSBudWxsO1xuICAgICAgfVxuXG4gICAgICB2YXIgcmVjb3JkID0gZmluYWxseUVudHJ5ID8gZmluYWxseUVudHJ5LmNvbXBsZXRpb24gOiB7fTtcbiAgICAgIHJlY29yZC50eXBlID0gdHlwZTtcbiAgICAgIHJlY29yZC5hcmcgPSBhcmc7XG5cbiAgICAgIGlmIChmaW5hbGx5RW50cnkpIHtcbiAgICAgICAgdGhpcy5tZXRob2QgPSBcIm5leHRcIjtcbiAgICAgICAgdGhpcy5uZXh0ID0gZmluYWxseUVudHJ5LmZpbmFsbHlMb2M7XG4gICAgICAgIHJldHVybiBDb250aW51ZVNlbnRpbmVsO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5jb21wbGV0ZShyZWNvcmQpO1xuICAgIH0sXG5cbiAgICBjb21wbGV0ZTogZnVuY3Rpb24ocmVjb3JkLCBhZnRlckxvYykge1xuICAgICAgaWYgKHJlY29yZC50eXBlID09PSBcInRocm93XCIpIHtcbiAgICAgICAgdGhyb3cgcmVjb3JkLmFyZztcbiAgICAgIH1cblxuICAgICAgaWYgKHJlY29yZC50eXBlID09PSBcImJyZWFrXCIgfHxcbiAgICAgICAgICByZWNvcmQudHlwZSA9PT0gXCJjb250aW51ZVwiKSB7XG4gICAgICAgIHRoaXMubmV4dCA9IHJlY29yZC5hcmc7XG4gICAgICB9IGVsc2UgaWYgKHJlY29yZC50eXBlID09PSBcInJldHVyblwiKSB7XG4gICAgICAgIHRoaXMucnZhbCA9IHRoaXMuYXJnID0gcmVjb3JkLmFyZztcbiAgICAgICAgdGhpcy5tZXRob2QgPSBcInJldHVyblwiO1xuICAgICAgICB0aGlzLm5leHQgPSBcImVuZFwiO1xuICAgICAgfSBlbHNlIGlmIChyZWNvcmQudHlwZSA9PT0gXCJub3JtYWxcIiAmJiBhZnRlckxvYykge1xuICAgICAgICB0aGlzLm5leHQgPSBhZnRlckxvYztcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIENvbnRpbnVlU2VudGluZWw7XG4gICAgfSxcblxuICAgIGZpbmlzaDogZnVuY3Rpb24oZmluYWxseUxvYykge1xuICAgICAgZm9yICh2YXIgaSA9IHRoaXMudHJ5RW50cmllcy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkge1xuICAgICAgICB2YXIgZW50cnkgPSB0aGlzLnRyeUVudHJpZXNbaV07XG4gICAgICAgIGlmIChlbnRyeS5maW5hbGx5TG9jID09PSBmaW5hbGx5TG9jKSB7XG4gICAgICAgICAgdGhpcy5jb21wbGV0ZShlbnRyeS5jb21wbGV0aW9uLCBlbnRyeS5hZnRlckxvYyk7XG4gICAgICAgICAgcmVzZXRUcnlFbnRyeShlbnRyeSk7XG4gICAgICAgICAgcmV0dXJuIENvbnRpbnVlU2VudGluZWw7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuXG4gICAgXCJjYXRjaFwiOiBmdW5jdGlvbih0cnlMb2MpIHtcbiAgICAgIGZvciAodmFyIGkgPSB0aGlzLnRyeUVudHJpZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgICAgdmFyIGVudHJ5ID0gdGhpcy50cnlFbnRyaWVzW2ldO1xuICAgICAgICBpZiAoZW50cnkudHJ5TG9jID09PSB0cnlMb2MpIHtcbiAgICAgICAgICB2YXIgcmVjb3JkID0gZW50cnkuY29tcGxldGlvbjtcbiAgICAgICAgICBpZiAocmVjb3JkLnR5cGUgPT09IFwidGhyb3dcIikge1xuICAgICAgICAgICAgdmFyIHRocm93biA9IHJlY29yZC5hcmc7XG4gICAgICAgICAgICByZXNldFRyeUVudHJ5KGVudHJ5KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHRocm93bjtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBUaGUgY29udGV4dC5jYXRjaCBtZXRob2QgbXVzdCBvbmx5IGJlIGNhbGxlZCB3aXRoIGEgbG9jYXRpb25cbiAgICAgIC8vIGFyZ3VtZW50IHRoYXQgY29ycmVzcG9uZHMgdG8gYSBrbm93biBjYXRjaCBibG9jay5cbiAgICAgIHRocm93IG5ldyBFcnJvcihcImlsbGVnYWwgY2F0Y2ggYXR0ZW1wdFwiKTtcbiAgICB9LFxuXG4gICAgZGVsZWdhdGVZaWVsZDogZnVuY3Rpb24oaXRlcmFibGUsIHJlc3VsdE5hbWUsIG5leHRMb2MpIHtcbiAgICAgIHRoaXMuZGVsZWdhdGUgPSB7XG4gICAgICAgIGl0ZXJhdG9yOiB2YWx1ZXMoaXRlcmFibGUpLFxuICAgICAgICByZXN1bHROYW1lOiByZXN1bHROYW1lLFxuICAgICAgICBuZXh0TG9jOiBuZXh0TG9jXG4gICAgICB9O1xuXG4gICAgICBpZiAodGhpcy5tZXRob2QgPT09IFwibmV4dFwiKSB7XG4gICAgICAgIC8vIERlbGliZXJhdGVseSBmb3JnZXQgdGhlIGxhc3Qgc2VudCB2YWx1ZSBzbyB0aGF0IHdlIGRvbid0XG4gICAgICAgIC8vIGFjY2lkZW50YWxseSBwYXNzIGl0IG9uIHRvIHRoZSBkZWxlZ2F0ZS5cbiAgICAgICAgdGhpcy5hcmcgPSB1bmRlZmluZWQ7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBDb250aW51ZVNlbnRpbmVsO1xuICAgIH1cbiAgfTtcbn0pKFxuICAvLyBJbiBzbG9wcHkgbW9kZSwgdW5ib3VuZCBgdGhpc2AgcmVmZXJzIHRvIHRoZSBnbG9iYWwgb2JqZWN0LCBmYWxsYmFjayB0b1xuICAvLyBGdW5jdGlvbiBjb25zdHJ1Y3RvciBpZiB3ZSdyZSBpbiBnbG9iYWwgc3RyaWN0IG1vZGUuIFRoYXQgaXMgc2FkbHkgYSBmb3JtXG4gIC8vIG9mIGluZGlyZWN0IGV2YWwgd2hpY2ggdmlvbGF0ZXMgQ29udGVudCBTZWN1cml0eSBQb2xpY3kuXG4gIChmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXMgfSkoKSB8fCBGdW5jdGlvbihcInJldHVybiB0aGlzXCIpKClcbik7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vcmVnZW5lcmF0b3ItcnVudGltZS9ydW50aW1lLmpzXG4vLyBtb2R1bGUgaWQgPSAyMDdcbi8vIG1vZHVsZSBjaHVua3MgPSAwIl0sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file