From 779fc8cf5069ea719a36fe5cb56bdba32e1bbdb9 Mon Sep 17 00:00:00 2001 From: Sebastien LE MOUILLOUR <32456736+smouillour@users.noreply.github.com> Date: Mon, 15 Apr 2024 10:37:08 +0200 Subject: [PATCH] fix: Move jsfc in fork, rename folder json-schema-form-core and some small fixes (#5272) --- .changeset/seven-bananas-perform.md | 8 + .../json-schema-form-core}/.eslintrc.json | 0 .../json-schema-form-core}/.gitignore | 0 .../json-schema-form-core}/.jscsrc | 0 .../json-schema-form-core}/.mocharc.json | 0 .../json-schema-form-core}/.travis.yml | 0 .../json-schema-form-core}/CHANGELOG.md | 0 .../json-schema-form-core}/LICENSE | 0 .../json-schema-form-core}/README.md | 21 +- .../json-schema-form-core}/package.json | 9 +- .../src/canonical-title-map.spec.js | 0 .../src/canonical-title-map.ts | 2 +- .../json-schema-form-core}/src/index.js | 0 .../json-schema-form-core}/src/merge.js | 0 .../json-schema-form-core}/src/merge.spec.js | 0 .../json-schema-form-core}/src/module.spec.js | 11 +- .../json-schema-form-core}/src/resolve.js | 2 +- .../src/resolve.spec.js | 0 .../src/schema-defaults.test.js | 0 .../src/schema-defaults.ts | 14 +- .../json-schema-form-core}/src/select.js | 0 .../json-schema-form-core}/src/select.test.js | 0 .../src/sf-path.test.js | 0 .../json-schema-form-core}/src/sf-path.ts | 0 .../src/traverse.test.js | 0 .../json-schema-form-core}/src/traverse.ts | 0 .../json-schema-form-core}/src/validate.js | 0 .../src/validate.test.js | 0 .../talend-scripts.json | 0 fork/json-schema-form-core/test.md | 257 + .../json-schema-form-core}/tsconfig.json | 1 + fork/json-schema-form-core/webpack.config.js | 10 + packages/jsfc/lib/json-refs-standalone-min.js | 2 - packages/jsfc/lib/json-refs-standalone.js | 5409 ----------------- packages/jsfc/test.md | 228 - packages/jsfc/webpack.config.js | 5 - tools/scripts-config-jest/test-setup.js | 4 + yarn.lock | 52 +- 38 files changed, 322 insertions(+), 5713 deletions(-) create mode 100644 .changeset/seven-bananas-perform.md rename {packages/jsfc => fork/json-schema-form-core}/.eslintrc.json (100%) rename {packages/jsfc => fork/json-schema-form-core}/.gitignore (100%) rename {packages/jsfc => fork/json-schema-form-core}/.jscsrc (100%) rename {packages/jsfc => fork/json-schema-form-core}/.mocharc.json (100%) rename {packages/jsfc => fork/json-schema-form-core}/.travis.yml (100%) rename {packages/jsfc => fork/json-schema-form-core}/CHANGELOG.md (100%) rename {packages/jsfc => fork/json-schema-form-core}/LICENSE (100%) rename {packages/jsfc => fork/json-schema-form-core}/README.md (82%) rename {packages/jsfc => fork/json-schema-form-core}/package.json (96%) rename {packages/jsfc => fork/json-schema-form-core}/src/canonical-title-map.spec.js (100%) rename {packages/jsfc => fork/json-schema-form-core}/src/canonical-title-map.ts (94%) rename {packages/jsfc => fork/json-schema-form-core}/src/index.js (100%) rename {packages/jsfc => fork/json-schema-form-core}/src/merge.js (100%) rename {packages/jsfc => fork/json-schema-form-core}/src/merge.spec.js (100%) rename {packages/jsfc => fork/json-schema-form-core}/src/module.spec.js (99%) rename {packages/jsfc => fork/json-schema-form-core}/src/resolve.js (89%) rename {packages/jsfc => fork/json-schema-form-core}/src/resolve.spec.js (100%) rename {packages/jsfc => fork/json-schema-form-core}/src/schema-defaults.test.js (100%) rename {packages/jsfc => fork/json-schema-form-core}/src/schema-defaults.ts (95%) rename {packages/jsfc => fork/json-schema-form-core}/src/select.js (100%) rename {packages/jsfc => fork/json-schema-form-core}/src/select.test.js (100%) rename {packages/jsfc => fork/json-schema-form-core}/src/sf-path.test.js (100%) rename {packages/jsfc => fork/json-schema-form-core}/src/sf-path.ts (100%) rename {packages/jsfc => fork/json-schema-form-core}/src/traverse.test.js (100%) rename {packages/jsfc => fork/json-schema-form-core}/src/traverse.ts (100%) rename {packages/jsfc => fork/json-schema-form-core}/src/validate.js (100%) rename {packages/jsfc => fork/json-schema-form-core}/src/validate.test.js (100%) rename {packages/jsfc => fork/json-schema-form-core}/talend-scripts.json (100%) create mode 100644 fork/json-schema-form-core/test.md rename {packages/jsfc => fork/json-schema-form-core}/tsconfig.json (87%) create mode 100644 fork/json-schema-form-core/webpack.config.js delete mode 100644 packages/jsfc/lib/json-refs-standalone-min.js delete mode 100644 packages/jsfc/lib/json-refs-standalone.js delete mode 100644 packages/jsfc/test.md delete mode 100644 packages/jsfc/webpack.config.js diff --git a/.changeset/seven-bananas-perform.md b/.changeset/seven-bananas-perform.md new file mode 100644 index 00000000000..c86644fddc0 --- /dev/null +++ b/.changeset/seven-bananas-perform.md @@ -0,0 +1,8 @@ +--- +"@talend/json-schema-form-core": patch +--- + +- JSFC is a fork of https://github.com/json-schema-form/json-schema-form-core : its place is in the Fork folder +- Remove local copy of json-refs and use package instead +- add missing type to fix ts compilation error +- add a polyfill for json-refs: path-browserify diff --git a/packages/jsfc/.eslintrc.json b/fork/json-schema-form-core/.eslintrc.json similarity index 100% rename from packages/jsfc/.eslintrc.json rename to fork/json-schema-form-core/.eslintrc.json diff --git a/packages/jsfc/.gitignore b/fork/json-schema-form-core/.gitignore similarity index 100% rename from packages/jsfc/.gitignore rename to fork/json-schema-form-core/.gitignore diff --git a/packages/jsfc/.jscsrc b/fork/json-schema-form-core/.jscsrc similarity index 100% rename from packages/jsfc/.jscsrc rename to fork/json-schema-form-core/.jscsrc diff --git a/packages/jsfc/.mocharc.json b/fork/json-schema-form-core/.mocharc.json similarity index 100% rename from packages/jsfc/.mocharc.json rename to fork/json-schema-form-core/.mocharc.json diff --git a/packages/jsfc/.travis.yml b/fork/json-schema-form-core/.travis.yml similarity index 100% rename from packages/jsfc/.travis.yml rename to fork/json-schema-form-core/.travis.yml diff --git a/packages/jsfc/CHANGELOG.md b/fork/json-schema-form-core/CHANGELOG.md similarity index 100% rename from packages/jsfc/CHANGELOG.md rename to fork/json-schema-form-core/CHANGELOG.md diff --git a/packages/jsfc/LICENSE b/fork/json-schema-form-core/LICENSE similarity index 100% rename from packages/jsfc/LICENSE rename to fork/json-schema-form-core/LICENSE diff --git a/packages/jsfc/README.md b/fork/json-schema-form-core/README.md similarity index 82% rename from packages/jsfc/README.md rename to fork/json-schema-form-core/README.md index aa05bda5f7c..485213c45bf 100644 --- a/packages/jsfc/README.md +++ b/fork/json-schema-form-core/README.md @@ -1,4 +1,5 @@ # JSON Schema Form Core + [![Gitter](https://img.shields.io/badge/GITTER-JOIN%20CHAT%20%E2%86%92-ff69b4.svg?style=flat-square)](https://gitter.im/json-schema-form/angular-schema-form?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status](https://travis-ci.org/json-schema-form/json-schema-form-core.svg?branch=development)](https://travis-ci.org/json-schema-form/json-schema-form-core) @@ -11,11 +12,13 @@ You **DO NOT** use this file in addition to Angular Schema Form, it is embedded build into any frameworks using it. ## Work-In-Progress! + There is [test output](docs/test.md) that forms some super basic documentation and I intend to expand them much further to the point of almost being useful before I create a proper API and document that. ## Keeping Track + After changing to Webpack 2, this library now includes a detailed version header which is passed through into `Angular Schema Form` and also the `Bootstrap` decorator bundle @@ -31,6 +34,7 @@ header which is passed through into `Angular Schema Form` and also the `Bootstra ``` ## Contributing / Plans + The main contributions we need to the core at the moment are related to both the migration of `Angular Schema Form` features to the core (like templates/builders) and the addition of an API for use by ASF (Angular) and RSF (React) libraries. @@ -40,21 +44,24 @@ Please contact @Anthropic via our [Gitter](https://gitter.im/json-schema-form/an ## Testing it ### With Angular Schema Form + There is a branch in angular-schema-form called `feature/webpack-babel` that integrates the core. To use it roughly follow these steps: -* Clone angular-schema-form to a **sibling** directory and switch to branch `feature/webpack-babel` -* `npm install` to install dependencies -* `npm run build` to build with the core. -* Use dist/angular-schema-form.js, now with the core from this folder. *No need to also load ObjectPath since it is already included* +- Clone angular-schema-form to a **sibling** directory and switch to branch `feature/webpack-babel` +- `npm install` to install dependencies +- `npm run build` to build with the core. +- Use dist/angular-schema-form.js, now with the core from this folder. _No need to also load ObjectPath since it is already included_ ### With Mocha tests + Tests are written in mocha + chai and run trough `npm test`. When the command `npm run testdoc` is run instead, the tests will also generate a readable `markdown` file [test.md](docs/test.md) to document elements of the library. ## Notes -* ObjectPath is bundled with json-schema-form-core -* angular-schema-form bundles json-schema-form-core so the user doesn't have to include it as an dependency. -* The code for not using ObjectPath on Angular 1.2 is removed. Could maybe be fixed but I (davidlgj) strongly believe its time to drop Angular 1.2 support since it complicates validation code as well. + +- ObjectPath is bundled with json-schema-form-core +- angular-schema-form bundles json-schema-form-core so the user doesn't have to include it as a dependency. +- The code for not using ObjectPath on Angular 1.2 is removed. Could maybe be fixed but I (davidlgj) strongly believe its time to drop Angular 1.2 support since it complicates validation code as well. diff --git a/packages/jsfc/package.json b/fork/json-schema-form-core/package.json similarity index 96% rename from packages/jsfc/package.json rename to fork/json-schema-form-core/package.json index db287e92964..af6d44cb4e1 100644 --- a/packages/jsfc/package.json +++ b/fork/json-schema-form-core/package.json @@ -39,21 +39,22 @@ "json-schema" ], "devDependencies": { + "@talend/babel-plugin-assets-api": "^1.3.1", + "@talend/babel-plugin-import-from-index": "^1.7.1", "@talend/eslint-config": "^13.0.3", "@talend/eslint-plugin": "^1.1.1", - "@talend/scripts-core": "^16.3.6", "@talend/scripts-config-react-webpack": "^16.5.1", "@talend/scripts-config-typescript": "^11.2.1", - "@talend/babel-plugin-import-from-index": "^1.7.1", - "@talend/babel-plugin-assets-api": "^1.3.1", + "@talend/scripts-core": "^16.3.6", "@types/chai": "^3.5.2", "@types/node": "^6.14.13", - "json-refs": "^3.0.15", "rimraf": "^5.0.5", "webpack": "^5.90.3" }, "dependencies": { + "json-refs": "3.0.15", "objectpath": "^1.2.2", + "path-browserify": "^1.0.1", "tv4": "^1.3.0" }, "publishConfig": { diff --git a/packages/jsfc/src/canonical-title-map.spec.js b/fork/json-schema-form-core/src/canonical-title-map.spec.js similarity index 100% rename from packages/jsfc/src/canonical-title-map.spec.js rename to fork/json-schema-form-core/src/canonical-title-map.spec.js diff --git a/packages/jsfc/src/canonical-title-map.ts b/fork/json-schema-form-core/src/canonical-title-map.ts similarity index 94% rename from packages/jsfc/src/canonical-title-map.ts rename to fork/json-schema-form-core/src/canonical-title-map.ts index e73dbfb5b3f..392e6c9e48d 100644 --- a/packages/jsfc/src/canonical-title-map.ts +++ b/fork/json-schema-form-core/src/canonical-title-map.ts @@ -2,7 +2,7 @@ // in the list format. export default function (titleMap: Array, originalEnum?: any) { if (!Array.isArray(titleMap)) { - const canonical = []; + const canonical: any = []; if (originalEnum) { originalEnum.forEach(value => { canonical.push({ name: titleMap[value], value }); diff --git a/packages/jsfc/src/index.js b/fork/json-schema-form-core/src/index.js similarity index 100% rename from packages/jsfc/src/index.js rename to fork/json-schema-form-core/src/index.js diff --git a/packages/jsfc/src/merge.js b/fork/json-schema-form-core/src/merge.js similarity index 100% rename from packages/jsfc/src/merge.js rename to fork/json-schema-form-core/src/merge.js diff --git a/packages/jsfc/src/merge.spec.js b/fork/json-schema-form-core/src/merge.spec.js similarity index 100% rename from packages/jsfc/src/merge.spec.js rename to fork/json-schema-form-core/src/merge.spec.js diff --git a/packages/jsfc/src/module.spec.js b/fork/json-schema-form-core/src/module.spec.js similarity index 99% rename from packages/jsfc/src/module.spec.js rename to fork/json-schema-form-core/src/module.spec.js index 1c3ee688ac3..00010d88e40 100644 --- a/packages/jsfc/src/module.spec.js +++ b/fork/json-schema-form-core/src/module.spec.js @@ -1,15 +1,16 @@ import chai from 'chai'; import { describe, it } from 'mocha'; + import { + canonicalTitleMap, + jsonref, merge, + schemaDefaults, select, - traverseSchema, + sfPath, traverseForm, + traverseSchema, validate, - sfPath, - schemaDefaults, - canonicalTitleMap, - jsonref, } from '.'; chai.should(); diff --git a/packages/jsfc/src/resolve.js b/fork/json-schema-form-core/src/resolve.js similarity index 89% rename from packages/jsfc/src/resolve.js rename to fork/json-schema-form-core/src/resolve.js index ee81a78d056..d5245b941a2 100644 --- a/packages/jsfc/src/resolve.js +++ b/fork/json-schema-form-core/src/resolve.js @@ -1,4 +1,4 @@ -import * as JsonRefs from './../lib/json-refs-standalone'; +import * as JsonRefs from 'json-refs'; export function jsonref(schema, callBack) { let promise = new Promise(function (resolve, reject) { diff --git a/packages/jsfc/src/resolve.spec.js b/fork/json-schema-form-core/src/resolve.spec.js similarity index 100% rename from packages/jsfc/src/resolve.spec.js rename to fork/json-schema-form-core/src/resolve.spec.js diff --git a/packages/jsfc/src/schema-defaults.test.js b/fork/json-schema-form-core/src/schema-defaults.test.js similarity index 100% rename from packages/jsfc/src/schema-defaults.test.js rename to fork/json-schema-form-core/src/schema-defaults.test.js diff --git a/packages/jsfc/src/schema-defaults.ts b/fork/json-schema-form-core/src/schema-defaults.ts similarity index 95% rename from packages/jsfc/src/schema-defaults.ts rename to fork/json-schema-form-core/src/schema-defaults.ts index 90adb2c2936..032da7dccbf 100644 --- a/packages/jsfc/src/schema-defaults.ts +++ b/fork/json-schema-form-core/src/schema-defaults.ts @@ -16,7 +16,7 @@ const stripNullType = type => { // Creates an default titleMap list from an enum, i.e. a list of strings. const enumToTitleMap = enm => { - const titleMap = []; // canonical titleMap format is a list. + const titleMap: any = []; // canonical titleMap format is a list. enm.forEach(name => { titleMap.push({ name, value: name }); }); @@ -94,7 +94,7 @@ export function stdFormObj(name, schema, options) { f.validationMessage = schema.validationMessage; } if (schema.enumNames) { - f.titleMap = canonicalTitleMap(schema.enumNames, schema['enum']); + f.titleMap = canonicalTitleMap(schema.enumNames, schema.enum); } f.schema = schema; @@ -107,7 +107,7 @@ export function stdFormObj(name, schema, options) { /*** Schema types to form type mappings, with defaults ***/ export function text(name, schema, options) { - if (stripNullType(schema.type) === 'string' && !schema['enum']) { + if (stripNullType(schema.type) === 'string' && !schema.enum) { const f = stdFormObj(name, schema, options); f.key = options.path; f.type = 'text'; @@ -149,12 +149,12 @@ export function checkbox(name, schema, options) { } export function select(name, schema, options) { - if (stripNullType(schema.type) === 'string' && schema['enum']) { + if (stripNullType(schema.type) === 'string' && schema.enum) { const f = stdFormObj(name, schema, options); f.key = options.path; f.type = 'select'; if (!f.titleMap) { - f.titleMap = enumToTitleMap(schema['enum']); + f.titleMap = enumToTitleMap(schema.enum); } options.lookup[stringify(options.path)] = f; return f; @@ -162,12 +162,12 @@ export function select(name, schema, options) { } export function checkboxes(name, schema, options) { - if (stripNullType(schema.type) === 'array' && schema.items && schema.items['enum']) { + if (stripNullType(schema.type) === 'array' && schema.items && schema.items.enum) { const f = stdFormObj(name, schema, options); f.key = options.path; f.type = 'checkboxes'; if (!f.titleMap) { - f.titleMap = enumToTitleMap(schema.items['enum']); + f.titleMap = enumToTitleMap(schema.items.enum); } options.lookup[stringify(options.path)] = f; return f; diff --git a/packages/jsfc/src/select.js b/fork/json-schema-form-core/src/select.js similarity index 100% rename from packages/jsfc/src/select.js rename to fork/json-schema-form-core/src/select.js diff --git a/packages/jsfc/src/select.test.js b/fork/json-schema-form-core/src/select.test.js similarity index 100% rename from packages/jsfc/src/select.test.js rename to fork/json-schema-form-core/src/select.test.js diff --git a/packages/jsfc/src/sf-path.test.js b/fork/json-schema-form-core/src/sf-path.test.js similarity index 100% rename from packages/jsfc/src/sf-path.test.js rename to fork/json-schema-form-core/src/sf-path.test.js diff --git a/packages/jsfc/src/sf-path.ts b/fork/json-schema-form-core/src/sf-path.ts similarity index 100% rename from packages/jsfc/src/sf-path.ts rename to fork/json-schema-form-core/src/sf-path.ts diff --git a/packages/jsfc/src/traverse.test.js b/fork/json-schema-form-core/src/traverse.test.js similarity index 100% rename from packages/jsfc/src/traverse.test.js rename to fork/json-schema-form-core/src/traverse.test.js diff --git a/packages/jsfc/src/traverse.ts b/fork/json-schema-form-core/src/traverse.ts similarity index 100% rename from packages/jsfc/src/traverse.ts rename to fork/json-schema-form-core/src/traverse.ts diff --git a/packages/jsfc/src/validate.js b/fork/json-schema-form-core/src/validate.js similarity index 100% rename from packages/jsfc/src/validate.js rename to fork/json-schema-form-core/src/validate.js diff --git a/packages/jsfc/src/validate.test.js b/fork/json-schema-form-core/src/validate.test.js similarity index 100% rename from packages/jsfc/src/validate.test.js rename to fork/json-schema-form-core/src/validate.test.js diff --git a/packages/jsfc/talend-scripts.json b/fork/json-schema-form-core/talend-scripts.json similarity index 100% rename from packages/jsfc/talend-scripts.json rename to fork/json-schema-form-core/talend-scripts.json diff --git a/fork/json-schema-form-core/test.md b/fork/json-schema-form-core/test.md new file mode 100644 index 00000000000..185599bbb72 --- /dev/null +++ b/fork/json-schema-form-core/test.md @@ -0,0 +1,257 @@ +# TOC + +- [merge.js](#mergejs) + - [merge](#mergejs-merge) +- [schema-defaults.js](#schema-defaultsjs) - [createDefaults](#schema-defaultsjs-createdefaults) - [defaultForm](#schema-defaultsjs-defaultform) + + + + +# merge.js + +should contain a function for merging schema and form definitions. + +```js +_merge.merge.should.be.an('function'); +``` + + + +## merge + +should combine a schema and form definition, regardless of order. + +```js +(0, _merge.merge)(schema, ['name', 'gender']).should.be.deep.equal(stdForm.form); +(0, _merge.merge)(schema, ['gender']).should.be.deep.equal([stdForm.form[1]]); +(0, _merge.merge)(schema, ['gender', 'name']).should.be.deep.equal([ + stdForm.form[1], + stdForm.form[0], +]); +``` + +should handle a wildcard \* in the form definition. + +```js +(0, _merge.merge)(schema, ['*']).should.be.deep.equal(stdForm.form); +``` + +should allow items that are not in the schema. + +```js +(0, _merge.merge)(schema, ['*', { type: 'fieldset' }]).should.be.deep.equal( + stdForm.form.concat([{ type: 'fieldset' }]), +); +``` + + + +# schema-defaults.js + +should hold functions for generating a default form schema from defaults it creates. + +```js +_schemaDefaults.defaultForm.should.be.an('function'); +_schemaDefaults.createDefaults.should.be.an('function'); +``` + + + +## createDefaults + +should create default rules. + +```js +var rules = (0, _schemaDefaults.createDefaults)(); +rules.should.be.an('object'); +``` + + + +## defaultForm + +should generate default form def from a schema. + +```js +var schema = { + type: 'object', + properties: { + name: { + title: 'Name', + description: 'Gimme yea name lad', + type: 'string', + }, + gender: { + title: 'Choose', + type: 'string', + enum: ['undefined', 'null', 'NaN'], + }, + overEighteen: { + title: 'Are you over 18 years old?', + type: 'boolean', + default: false, + }, + attributes: { + type: 'object', + required: ['eyecolor'], + properties: { + eyecolor: { type: 'string', title: 'Eye color' }, + haircolor: { type: 'string', title: 'Hair color' }, + shoulders: { + type: 'object', + title: 'Shoulders', + properties: { + left: { type: 'string' }, + right: { type: 'string' }, + }, + }, + }, + }, + }, +}; +var form = [ + { + title: 'Name', + description: 'Gimme yea name lad', + schema: { + title: 'Name', + description: 'Gimme yea name lad', + type: 'string', + }, + ngModelOptions: {}, + key: ['name'], + type: 'text', + }, + { + title: 'Choose', + schema: { + title: 'Choose', + type: 'string', + enum: ['undefined', 'null', 'NaN'], + }, + ngModelOptions: {}, + key: ['gender'], + type: 'select', + titleMap: [ + { + name: 'undefined', + value: 'undefined', + }, + { + name: 'null', + value: 'null', + }, + { + name: 'NaN', + value: 'NaN', + }, + ], + }, + { + title: 'Are you over 18 years old?', + schema: { + title: 'Are you over 18 years old?', + type: 'boolean', + default: false, + }, + ngModelOptions: {}, + key: ['overEighteen'], + type: 'checkbox', + }, + { + title: 'attributes', + schema: { + type: 'object', + required: ['eyecolor'], + properties: { + eyecolor: { + type: 'string', + title: 'Eye color', + }, + haircolor: { + type: 'string', + title: 'Hair color', + }, + shoulders: { + type: 'object', + title: 'Shoulders', + properties: { + left: { + type: 'string', + }, + right: { + type: 'string', + }, + }, + }, + }, + }, + ngModelOptions: {}, + key: ['attributes'], + type: 'fieldset', + items: [ + { + title: 'Eye color', + required: true, + schema: { + type: 'string', + title: 'Eye color', + }, + ngModelOptions: {}, + key: ['attributes', 'eyecolor'], + type: 'text', + }, + { + title: 'Hair color', + schema: { + type: 'string', + title: 'Hair color', + }, + ngModelOptions: {}, + key: ['attributes', 'haircolor'], + type: 'text', + }, + { + title: 'Shoulders', + schema: { + type: 'object', + title: 'Shoulders', + properties: { + left: { + type: 'string', + }, + right: { + type: 'string', + }, + }, + }, + ngModelOptions: {}, + key: ['attributes', 'shoulders'], + type: 'fieldset', + items: [ + { + title: 'left', + schema: { + type: 'string', + }, + ngModelOptions: {}, + key: ['attributes', 'shoulders', 'left'], + type: 'text', + }, + { + title: 'right', + schema: { + type: 'string', + }, + ngModelOptions: {}, + key: ['attributes', 'shoulders', 'right'], + type: 'text', + }, + ], + }, + ], + }, +]; +var f = (0, _schemaDefaults.defaultForm)(schema, (0, _schemaDefaults.createDefaults)()); +f.form.should.be.deep.equal(form); +``` diff --git a/packages/jsfc/tsconfig.json b/fork/json-schema-form-core/tsconfig.json similarity index 87% rename from packages/jsfc/tsconfig.json rename to fork/json-schema-form-core/tsconfig.json index 03264a1df9f..0f7c9589bbb 100644 --- a/packages/jsfc/tsconfig.json +++ b/fork/json-schema-form-core/tsconfig.json @@ -2,6 +2,7 @@ "extends": "@talend/scripts-config-typescript/tsconfig.json", "include": ["src/**/*"], "compilerOptions": { + "noImplicitAny": false, "declaration": true, "target": "ES5", "module": "CommonJs" diff --git a/fork/json-schema-form-core/webpack.config.js b/fork/json-schema-form-core/webpack.config.js new file mode 100644 index 00000000000..cc1e44e43e2 --- /dev/null +++ b/fork/json-schema-form-core/webpack.config.js @@ -0,0 +1,10 @@ +module.exports = { + output: { + filename: 'index.js', + }, + resolve: { + fallback: { + path: require.resolve('path-browserify'), + }, + }, +}; diff --git a/packages/jsfc/lib/json-refs-standalone-min.js b/packages/jsfc/lib/json-refs-standalone-min.js deleted file mode 100644 index 93b61893630..00000000000 --- a/packages/jsfc/lib/json-refs-standalone-min.js +++ /dev/null @@ -1,2 +0,0 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.JsonRefs=e()}}(function(){var e;return function t(e,r,n){function o(s,a){if(!r[s]){if(!e[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(i)return i(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var f=r[s]={exports:{}};e[s][0].call(f.exports,function(t){var r=e[s][1][t];return o(r?r:t)},f,f.exports,t,e,r,n)}return r[s].exports}for(var i="function"==typeof require&&require,s=0;s-1?n=i:(r=d(e,"Undefined")?void 0:m(e),d(r,"Undefined")?n=i:(n=r,n.path=F(U.join(r.path,i.path)),n.query=o(r.query,i.query))),n.fragment=void 0,(-1===M.indexOf(n.reference)&&0===n.path.indexOf("../")?"../":"")+q.serialize(n)}function s(e,t){var r,n=[];return t.length>0&&(r=e,t.slice(0,t.length-1).forEach(function(e){e in r&&(r=r[e],n.push(r))})),n}function a(e,t,r,o,i,s,a,f,p){var h,l;if(r.length>0)try{h=c(t,r)}catch(y){"remote"===e&&(o.error=y.message,o.missing=!0)}else h=t;return d(h,"Undefined")||(o.value=h),d(h,"Array")||d(h,"Object")?(l=n(i),"local"===e?(delete l.subDocPath,t=h):(l.relativeBase=U.dirname(s[s.length-1]),0===r.length?delete l.subDocPath:l.subDocPath=r),u(t,l,s,a,f,p)):void 0}function u(e,t,r,n,o,s){var u=Promise.resolve(),c=n.length?j(n[n.length-1]):[],f=O(e,t),p=t.subDocPath||[],l=S(p),y=["#"];return r.forEach(function(e,t){"#"!==e.charAt(0)&&y.push(n[t])}),y.reverse(),"#"!==(r[r.length-1]||"").charAt(0)&&(o.documents[S(c)]=e),Object.keys(f).forEach(function(v){var m,g,b,E,w=f[v];b=0===r.length?c.concat(j(v)):c.concat(j(v).slice(0===r.length?0:p.length)),E=S(b),d(o[E],"Undefined")&&(o.refs[E]=f[v],d(w.error,"Undefined")&&"invalid"!==w.type&&(L.indexOf(w.type)>-1?(m=i(t.relativeBase,w.uri),g=r.indexOf(m)):(m=w.uri,g=n.indexOf(m)),w.ancestorPtrs=y,w.indirect=s,-1===g?L.indexOf(w.type)>-1?u=u.then(function(){return h(m,t).then(function(e){return a("remote",e,d(w.uriDetails.fragment,"Undefined")?[]:j(decodeURI(w.uriDetails.fragment)),w,t,r.concat(m),n.concat(E),o,s)})["catch"](function(e){w.error=e.message,w.missing=!0})}):0!==E.indexOf(m+"/")&&E!==m&&0!==l.indexOf(m+"/")&&l!==m?0!==m.indexOf(l+"/")&&(u=u.then(function(){return a("local",e,j(m),w,t,r.concat(m),n.concat(E),o,s||-1===m.indexOf(l+"/")&&m!==l)})):w.circular=!0:(n.slice(g).forEach(function(e){o.refs[e].circular=!0}),w.circular=!0)))}),u=u.then(function(){function e(i,s,a,u){Object.keys(o.refs).forEach(function(c){var f=o.refs[c];-1===n.indexOf(u)&&-1===r.indexOf(a)&&-1===t.indexOf(u)&&c!==a&&0===c.indexOf(u+"/")&&(s.indexOf(u)>-1?s.forEach(function(e){-1===t.indexOf(u)&&t.push(e)}):e(i.concat(a),s.concat(u),c,f.uri),r.push(a),n.push(u))})}var t=[],r=[],n=[];Object.keys(o.refs).forEach(function(r){var n=o.refs[r];"local"!==n.type||n.circular||-1!==t.indexOf(n.uri)||e([],[],r,n.uri)}),Object.keys(o.refs).forEach(function(e){var r=o.refs[e];t.indexOf(r.uri)>-1&&(r.circular=!0)})}).then(function(){return o})}function c(e,t){var r=e;return t.forEach(function(e){if(e=decodeURI(e),!(e in r))throw Error("JSON Pointer points to missing location: "+S(t));r=r[e]}),r}function f(e){return Object.keys(e).filter(function(e){return"$ref"!==e})}function p(e){var t;switch(e.uriDetails.reference){case"absolute":case"uri":t="remote";break;case"same-document":t="local";break;default:t=e.uriDetails.reference}return t}function h(e,t){var r=k[e],o=Promise.resolve(),i=n(t.loaderOptions||{});return d(r,"Undefined")?(d(i.processContent,"Undefined")&&(i.processContent=function(e,t){t(void 0,JSON.parse(e.text))}),o=I.load(decodeURI(e),i),o=o.then(function(t){return k[e]={value:t},t})["catch"](function(t){throw k[e]={error:t},t})):o=o.then(function(){return r.value}),o=o.then(function(e){return n(e)})}function l(e,t){var r=!0;try{if(!d(e,"Object"))throw new Error("obj is not an Object");if(!d(e.$ref,"String"))throw new Error("obj.$ref is not a String")}catch(n){if(t)throw n;r=!1}return r}function d(e,t){return"Undefined"===t?"undefined"==typeof e:Object.prototype.toString.call(e)==="[object "+t+"]"}function y(e){var t,r;return d(e.filter,"Array")||d(e.filter,"String")?(r=d(e.filter,"String")?[e.filter]:e.filter,t=function(e){return r.indexOf(e.type)>-1||r.indexOf(p(e))>-1}):d(e.filter,"Function")?t=e.filter:d(e.filter,"Undefined")&&(t=function(){return!0}),function(r,n){return("invalid"!==r.type||e.includeInvalid===!0)&&t(r,n)}}function v(e){var t;return d(e.subDocPath,"Array")?t=e.subDocPath:d(e.subDocPath,"String")?t=j(e.subDocPath):d(e.subDocPath,"Undefined")&&(t=[]),t}function m(e){return q.parse(encodeURI(decodeURI(e)))}function g(e,t,r){c(e,t.slice(0,t.length-1))[decodeURI(t[t.length-1])]=r}function b(e,t,r,n){function o(t,o){r.push(o),b(e,t,r,n),r.pop()}var i=!0;d(n,"Function")&&(i=n(e,t,r)),-1===e.indexOf(t)&&(e.push(t),i!==!1&&(d(t,"Array")?t.forEach(function(e,t){o(e,t.toString())}):d(t,"Object")&&Object.keys(t).forEach(function(e){o(t[e],e)}))),e.pop()}function E(e,t){if(e=d(e,"Undefined")?{}:n(e),!d(e,"Object"))throw new TypeError("options must be an Object");if(!(d(e.filter,"Undefined")||d(e.filter,"Array")||d(e.filter,"Function")||d(e.filter,"String")))throw new TypeError("options.filter must be an Array, a Function of a String");if(!d(e.includeInvalid,"Undefined")&&!d(e.includeInvalid,"Boolean"))throw new TypeError("options.includeInvalid must be a Boolean");if(!d(e.refPreProcessor,"Undefined")&&!d(e.refPreProcessor,"Function"))throw new TypeError("options.refPreProcessor must be a Function");if(!d(e.refPostProcessor,"Undefined")&&!d(e.refPostProcessor,"Function"))throw new TypeError("options.refPostProcessor must be a Function");if(!d(e.subDocPath,"Undefined")&&!d(e.subDocPath,"Array")&&!_(e.subDocPath))throw new TypeError("options.subDocPath must be an Array of path segments or a valid JSON Pointer");if(e.filter=y(e),e.subDocPath=v(e),!d(t,"Undefined"))try{c(t,e.subDocPath)}catch(r){throw r.message=r.message.replace("JSON Pointer","options.subDocPath"),r}return e}function w(){k={}}function x(e){if(!d(e,"Array"))throw new TypeError("path must be an array");return e.map(function(e){return d(e,"String")||(e=JSON.stringify(e)),decodeURI(e.replace(/~1/g,"/").replace(/~0/g,"~"))})}function C(e){if(!d(e,"Array"))throw new TypeError("path must be an array");return e.map(function(e){return d(e,"String")||(e=JSON.stringify(e)),e.replace(/~/g,"~0").replace(/\//g,"~1")})}function O(e,t){var r={};if(!d(e,"Array")&&!d(e,"Object"))throw new TypeError("obj must be an Array or an Object");return t=E(t,e),b(s(e,t.subDocPath),c(e,t.subDocPath),n(t.subDocPath),function(e,o,i){var s,a=!0;return l(o)&&(d(t.refPreProcessor,"Undefined")||(o=t.refPreProcessor(n(o),i)),s=T(o),d(t.refPostProcessor,"Undefined")||(s=t.refPostProcessor(s,i)),t.filter(s,i)&&(r[S(i)]=s),f(o).length>0&&(a=!1)),a}),r}function P(e,t){var r=Promise.resolve();return r=r.then(function(){if(!d(e,"String"))throw new TypeError("location must be a string");return t=E(t),e=i(t.relativeBase,e),h(e,t)}).then(function(r){var o=n(k[e]),i=n(t),s=m(e);return d(o.refs,"Undefined")&&(delete i.filter,delete i.subDocPath,i.includeInvalid=!0,k[e].refs=O(r,i)),d(t.filter,"Undefined")||(i.filter=t.filter),d(s.fragment,"Undefined")?d(s.subDocPath,"Undefined")||(i.subDocPath=t.subDocPath):i.subDocPath=j(decodeURI(s.fragment)),{refs:O(r,i),value:r}})}function T(e){var t,r,n,o={def:e};try{l(e,!0)?(t=e.$ref,n=$[t],d(n,"Undefined")&&(n=$[t]=m(t)),o.uri=t,o.uriDetails=n,d(n.error,"Undefined")?o.type=p(o):(o.error=o.uriDetails.error,o.type="invalid"),r=f(e),r.length>0&&(o.warning="Extra JSON Reference properties will be ignored: "+r.join(", "))):o.type="invalid"}catch(i){o.error=i.message,o.type="invalid"}return o}function _(e,t){var r,n=!0;try{if(!d(e,"String"))throw new Error("ptr is not a String");if(""!==e){if(r=e.charAt(0),-1===["#","/"].indexOf(r))throw new Error("ptr must start with a / or #/");if("#"===r&&"#"!==e&&"/"!==e.charAt(1))throw new Error("ptr must start with a / or #/");if(e.match(H))throw new Error("ptr has invalid token(s)")}}catch(o){if(t===!0)throw o;n=!1}return n}function A(e,t){return l(e,t)&&"invalid"!==T(e,t).type}function j(e){if(!_(e))throw new Error("ptr must be a JSON Pointer");var t=e.split("/");return t.shift(),x(t)}function S(e,t){if(!d(e,"Array"))throw new Error("path must be an Array");return(t!==!1?"#":"")+(e.length>0?"/":"")+C(e).join("/")}function D(e,t){var r=Promise.resolve();return r=r.then(function(){if(!d(e,"Array")&&!d(e,"Object"))throw new TypeError("obj must be an Array or an Object");t=E(t,e),e=n(e)}).then(function(){return u(e,t,[],[],{documents:{},refs:{}})}).then(function(t){function r(e,t){return j(e).length-j(t).length}var n={},o={};return Object.keys(t.refs).sort(r).forEach(function(r){var i=t.refs[r];i.indirect||(o[r]=i),delete i.indirect,d(i.error,"Undefined")&&"invalid"!==i.type?(d(i.value,"Undefined")&&i.circular&&(i.value=i.def),d(i.value,"Undefined")?n[r]=i:("#"===r?e=i.value:g(e,j(r),i.value),delete i.ancestorPtrs)):delete i.ancestorPtrs}),Object.keys(n).forEach(function(r){var o=n[r];o.ancestorPtrs.forEach(function(n,i){if(d(o.value,"Undefined"))try{o.value=c(t.documents[n],j(o.uri)),delete o.ancestorPtrs,g(e,j(r),o.value)}catch(s){i===o.ancestorPtrs.length-1&&(o.error=s.message,o.missing=!0,delete o.ancestorPtrs)}})}),{refs:o,resolved:e}})}function R(e,t){var r=Promise.resolve();return r=r.then(function(){if(!d(e,"String"))throw new TypeError("location must be a string");return t=E(t),e=i(t.relativeBase,e),h(e,t)}).then(function(r){var o=n(t),i=m(e);return d(i.fragment,"Undefined")||(o.subDocPath=j(decodeURI(i.fragment))),o.relativeBase=U.dirname(e),D(r,o).then(function(e){return{refs:e.refs,resolved:e.resolved,value:r}})})}var U=e("path"),I=e("path-loader"),N=e("querystring"),F=e("slash"),q=e("uri-js"),H=/~(?:[^01]|$)/g,k={},L=["relative","remote"],M=["absolute","uri"],$={};"undefined"==typeof Promise&&e("native-promise-only"),t.exports.clearCache=w,t.exports.decodePath=x,t.exports.encodePath=C,t.exports.findRefs=O,t.exports.findRefsAt=P,t.exports.getRefDetails=T,t.exports.isPtr=_,t.exports.isRef=A,t.exports.pathFromPtr=j,t.exports.pathToPtr=S,t.exports.resolveRefs=D,t.exports.resolveRefsAt=R},{"native-promise-only":3,path:4,"path-loader":5,querystring:11,slash:13,"uri-js":23}],2:[function(e,t,r){function n(e){return e?o(e):void 0}function o(e){for(var t in n.prototype)e[t]=n.prototype[t];return e}t.exports=n,n.prototype.on=n.prototype.addEventListener=function(e,t){return this._callbacks=this._callbacks||{},(this._callbacks["$"+e]=this._callbacks["$"+e]||[]).push(t),this},n.prototype.once=function(e,t){function r(){this.off(e,r),t.apply(this,arguments)}return r.fn=t,this.on(e,r),this},n.prototype.off=n.prototype.removeListener=n.prototype.removeAllListeners=n.prototype.removeEventListener=function(e,t){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var r=this._callbacks["$"+e];if(!r)return this;if(1==arguments.length)return delete this._callbacks["$"+e],this;for(var n,o=0;on;++n)r[n].apply(this,t)}return this},n.prototype.listeners=function(e){return this._callbacks=this._callbacks||{},this._callbacks["$"+e]||[]},n.prototype.hasListeners=function(e){return!!this.listeners(e).length}},{}],3:[function(t,r,n){(function(t){!function(t,n,o){n[t]=n[t]||o(),"undefined"!=typeof r&&r.exports?r.exports=n[t]:"function"==typeof e&&e.amd&&e(function(){return n[t]})}("Promise","undefined"!=typeof t?t:this,function(){"use strict";function e(e,t){h.add(e,t),p||(p=d(h.drain))}function t(e){var t,r=typeof e;return null==e||"object"!=r&&"function"!=r||(t=e.then),"function"==typeof t?t:!1}function r(){for(var e=0;e0&&e(r,u))}catch(c){i.call(new a(u),c)}}}function i(t){var n=this;n.triggered||(n.triggered=!0,n.def&&(n=n.def),n.msg=t,n.state=2,n.chain.length>0&&e(r,n))}function s(e,t,r,n){for(var o=0;o=0;n--){var o=e[n];"."===o?e.splice(n,1):".."===o?(e.splice(n,1),r++):r&&(e.splice(n,1),r--)}if(t)for(;r--;r)e.unshift("..");return e}function n(e,t){if(e.filter)return e.filter(t);for(var r=[],n=0;n=-1&&!o;i--){var s=i>=0?arguments[i]:e.cwd();if("string"!=typeof s)throw new TypeError("Arguments to path.resolve must be strings");s&&(r=s+"/"+r,o="/"===s.charAt(0))}return r=t(n(r.split("/"),function(e){return!!e}),!o).join("/"),(o?"/":"")+r||"."},r.normalize=function(e){var o=r.isAbsolute(e),i="/"===s(e,-1);return e=t(n(e.split("/"),function(e){return!!e}),!o).join("/"),e||o||(e="."),e&&i&&(e+="/"),(o?"/":"")+e},r.isAbsolute=function(e){return"/"===e.charAt(0)},r.join=function(){var e=Array.prototype.slice.call(arguments,0);return r.normalize(n(e,function(e,t){if("string"!=typeof e)throw new TypeError("Arguments to path.join must be strings");return e}).join("/"))},r.relative=function(e,t){function n(e){for(var t=0;t=0&&""===e[r];r--);return t>r?[]:e.slice(t,r-t+1)}e=r.resolve(e).substr(1),t=r.resolve(t).substr(1);for(var o=n(e.split("/")),i=n(t.split("/")),s=Math.min(o.length,i.length),a=s,u=0;s>u;u++)if(o[u]!==i[u]){a=u;break}for(var c=[],u=a;ut&&(t=e.length+t),e.substr(t,r)}}).call(this,e("_process"))},{_process:8}],5:[function(e,t,r){"use strict";function n(e){return"undefined"!=typeof e&&(e=-1===e.indexOf("://")?"":e.split("://")[0]),e}function o(e){var t=n(e),r=i[t];if("undefined"==typeof r){if(""!==t)throw new Error("Unsupported scheme: "+t);r=s}return r}var i={file:e("./lib/loaders/file"),http:e("./lib/loaders/http"),https:e("./lib/loaders/http")},s="object"==typeof window||"function"==typeof importScripts?i.http:i.file;"undefined"==typeof Promise&&e("native-promise-only"),t.exports.load=function(e,t){var r=Promise.resolve();return"undefined"==typeof t&&(t={}),r=r.then(function(){if("undefined"==typeof e)throw new TypeError("location is required");if("string"!=typeof e)throw new TypeError("location must be a string");if("undefined"!=typeof t){if("object"!=typeof t)throw new TypeError("options must be an object");if("undefined"!=typeof t.processContent&&"function"!=typeof t.processContent)throw new TypeError("options.processContent must be a function")}}),r=r.then(function(){return new Promise(function(r,n){var i=o(e);i.load(e,t||{},function(e,t){e?n(e):r(t)})})}).then(function(e){return t.processContent?new Promise(function(r,n){t.processContent("object"==typeof e?e:{text:e},function(e,t){e?n(e):r(t)})}):"object"==typeof e?e.text:e})}},{"./lib/loaders/file":6,"./lib/loaders/http":7,"native-promise-only":3}],6:[function(e,t,r){"use strict";var n=new TypeError("The 'file' scheme is not supported in the browser");t.exports.getBase=function(){throw n},t.exports.load=function(){var e=arguments[arguments.length-1];if("function"!=typeof e)throw n;e(n)}},{}],7:[function(e,t,r){"use strict";var n=e("superagent"),o=["delete","get","head","patch","post","put"];t.exports.load=function(e,t,r){function i(e,t){e?r(e):("function"==typeof t.buffer&&t.buffer(!0),t.end(function(e,t){e?r(e):r(void 0,t)}))}var s,a,u=t.method?t.method.toLowerCase():"get";if("undefined"!=typeof t.method?"string"!=typeof t.method?s=new TypeError("options.method must be a string"):-1===o.indexOf(t.method)&&(s=new TypeError("options.method must be one of the following: "+o.slice(0,o.length-1).join(", ")+" or "+o[o.length-1])):"undefined"!=typeof t.prepareRequest&&"function"!=typeof t.prepareRequest&&(s=new TypeError("options.prepareRequest must be a function")),s)r(s);else if(a=n["delete"===u?"del":u](e),t.prepareRequest)try{t.prepareRequest(a,i)}catch(c){r(c)}else i(void 0,a)}},{superagent:14}],8:[function(e,t,r){function n(){f=!1,a.length?c=a.concat(c):p=-1,c.length&&o()}function o(){if(!f){var e=setTimeout(n);f=!0;for(var t=c.length;t;){for(a=c,c=[];++p1)for(var r=1;r0&&c>u&&(c=u);for(var f=0;c>f;++f){var p,h,l,d,y=e[f].replace(a,"%20"),v=y.indexOf(r);v>=0?(p=y.substr(0,v),h=y.substr(v+1)):(p=y,h=""),l=decodeURIComponent(p),d=decodeURIComponent(h),n(s,l)?o(s[l])?s[l].push(d):s[l]=[s[l],d]:s[l]=d}return s};var o=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)}},{}],10:[function(e,t,r){"use strict";function n(e,t){if(e.map)return e.map(t);for(var r=[],n=0;nn;)i=t.call(null,i,e[n],++n,e);return i}},{}],13:[function(e,t,r){"use strict";t.exports=function(e){var t=/^\\\\\?\\/.test(e),r=/[^\x00-\x80]+/.test(e);return t||r?e:e.replace(/\\/g,"/")}},{}],14:[function(e,t,r){function n(){}function o(e){var t={}.toString.call(e);switch(t){case"[object File]":case"[object Blob]":case"[object FormData]":return!0;default:return!1}}function i(e){if(!b(e))return e;var t=[];for(var r in e)null!=e[r]&&s(t,r,e[r]);return t.join("&")}function s(e,t,r){return Array.isArray(r)?r.forEach(function(r){s(e,t,r)}):void e.push(encodeURIComponent(t)+"="+encodeURIComponent(r))}function a(e){for(var t,r,n={},o=e.split("&"),i=0,s=o.length;s>i;++i)r=o[i],t=r.split("="),n[decodeURIComponent(t[0])]=decodeURIComponent(t[1]);return n}function u(e){var t,r,n,o,i=e.split(/\r?\n/),s={};i.pop();for(var a=0,u=i.length;u>a;++a)r=i[a],t=r.indexOf(":"),n=r.slice(0,t).toLowerCase(),o=w(r.slice(t+1)),s[n]=o;return s}function c(e){return/[\/+]json\b/.test(e)}function f(e){return e.split(/ *; */).shift()}function p(e){return m(e.split(/ *; */),function(e,t){var r=t.split(/ *= */),n=r.shift(),o=r.shift();return n&&o&&(e[n]=o),e},{})}function h(e,t){t=t||{},this.req=e,this.xhr=this.req.xhr,this.text="HEAD"!=this.req.method&&(""===this.xhr.responseType||"text"===this.xhr.responseType)||"undefined"==typeof this.xhr.responseType?this.xhr.responseText:null,this.statusText=this.req.xhr.statusText,this.setStatusProperties(this.xhr.status),this.header=this.headers=u(this.xhr.getAllResponseHeaders()),this.header["content-type"]=this.xhr.getResponseHeader("content-type"),this.setHeaderProperties(this.header),this.body="HEAD"!=this.req.method?this.parseBody(this.text?this.text:this.xhr.response):null}function l(e,t){var r=this;this._query=this._query||[],this.method=e,this.url=t,this.header={},this._header={},this.on("end",function(){var e=null,t=null;try{t=new h(r)}catch(n){return e=new Error("Parser is unable to parse the response"),e.parse=!0,e.original=n,e.rawResponse=r.xhr&&r.xhr.responseText?r.xhr.responseText:null,e.statusCode=r.xhr&&r.xhr.status?r.xhr.status:null,r.callback(e)}if(r.emit("response",t),e)return r.callback(e,t);if(t.status>=200&&t.status<300)return r.callback(e,t);var o=new Error(t.statusText||"Unsuccessful HTTP response");o.original=e,o.response=t,o.status=t.status,r.callback(o,t)})}function d(e,t){var r=E("DELETE",e);return t&&r.end(t),r}var y,v=e("emitter"),m=e("reduce"),g=e("./request-base"),b=e("./is-object");y="undefined"!=typeof window?window:"undefined"!=typeof self?self:this;var E=t.exports=e("./request").bind(null,l);E.getXHR=function(){if(!(!y.XMLHttpRequest||y.location&&"file:"==y.location.protocol&&y.ActiveXObject))return new XMLHttpRequest;try{return new ActiveXObject("Microsoft.XMLHTTP")}catch(e){}try{return new ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(e){}try{return new ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(e){}try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(e){}return!1};var w="".trim?function(e){return e.trim()}:function(e){return e.replace(/(^\s*|\s*$)/g,"")};E.serializeObject=i,E.parseString=a,E.types={html:"text/html",json:"application/json",xml:"application/xml",urlencoded:"application/x-www-form-urlencoded",form:"application/x-www-form-urlencoded","form-data":"application/x-www-form-urlencoded"},E.serialize={"application/x-www-form-urlencoded":i,"application/json":JSON.stringify},E.parse={"application/x-www-form-urlencoded":a,"application/json":JSON.parse},h.prototype.get=function(e){return this.header[e.toLowerCase()]},h.prototype.setHeaderProperties=function(e){var t=this.header["content-type"]||"";this.type=f(t);var r=p(t);for(var n in r)this[n]=r[n]},h.prototype.parseBody=function(e){var t=E.parse[this.type];return!t&&c(this.type)&&(t=E.parse["application/json"]),t&&e&&(e.length||e instanceof Object)?t(e):null},h.prototype.setStatusProperties=function(e){1223===e&&(e=204);var t=e/100|0;this.status=this.statusCode=e,this.statusType=t,this.info=1==t,this.ok=2==t,this.clientError=4==t,this.serverError=5==t,this.error=4==t||5==t?this.toError():!1,this.accepted=202==e,this.noContent=204==e,this.badRequest=400==e,this.unauthorized=401==e,this.notAcceptable=406==e,this.notFound=404==e,this.forbidden=403==e},h.prototype.toError=function(){var e=this.req,t=e.method,r=e.url,n="cannot "+t+" "+r+" ("+this.status+")",o=new Error(n);return o.status=this.status,o.method=t,o.url=r,o},E.Response=h,v(l.prototype);for(var x in g)l.prototype[x]=g[x];l.prototype.abort=function(){return this.aborted?void 0:(this.aborted=!0,this.xhr.abort(),this.clearTimeout(),this.emit("abort"),this)},l.prototype.type=function(e){return this.set("Content-Type",E.types[e]||e),this},l.prototype.responseType=function(e){return this._responseType=e,this},l.prototype.accept=function(e){return this.set("Accept",E.types[e]||e),this},l.prototype.auth=function(e,t,r){switch(r||(r={type:"basic"}),r.type){case"basic":var n=btoa(e+":"+t);this.set("Authorization","Basic "+n);break;case"auto":this.username=e,this.password=t}return this},l.prototype.query=function(e){return"string"!=typeof e&&(e=i(e)),e&&this._query.push(e),this},l.prototype.attach=function(e,t,r){return this._getFormData().append(e,t,r||t.name),this},l.prototype._getFormData=function(){return this._formData||(this._formData=new y.FormData),this._formData},l.prototype.send=function(e){var t=b(e),r=this._header["content-type"];if(t&&b(this._data))for(var n in e)this._data[n]=e[n];else"string"==typeof e?(r||this.type("form"),r=this._header["content-type"],"application/x-www-form-urlencoded"==r?this._data=this._data?this._data+"&"+e:e:this._data=(this._data||"")+e):this._data=e;return!t||o(e)?this:(r||this.type("json"),this)},h.prototype.parse=function(e){return y.console&&console.warn("Client-side parse() method has been renamed to serialize(). This method is not compatible with superagent v2.0"),this.serialize(e),this},h.prototype.serialize=function(e){return this._parser=e,this},l.prototype.callback=function(e,t){var r=this._callback;this.clearTimeout(),r(e,t)},l.prototype.crossDomainError=function(){var e=new Error("Request has been terminated\nPossible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc.");e.crossDomain=!0,e.status=this.status,e.method=this.method,e.url=this.url,this.callback(e)},l.prototype.timeoutError=function(){var e=this._timeout,t=new Error("timeout of "+e+"ms exceeded");t.timeout=e,this.callback(t)},l.prototype.withCredentials=function(){return this._withCredentials=!0,this},l.prototype.end=function(e){var t=this,r=this.xhr=E.getXHR(),i=this._query.join("&"),s=this._timeout,a=this._formData||this._data;this._callback=e||n,r.onreadystatechange=function(){if(4==r.readyState){var e;try{e=r.status}catch(n){e=0}if(0==e){if(t.timedout)return t.timeoutError();if(t.aborted)return;return t.crossDomainError()}t.emit("end")}};var u=function(e){e.total>0&&(e.percent=e.loaded/e.total*100),e.direction="download",t.emit("progress",e)};this.hasListeners("progress")&&(r.onprogress=u);try{r.upload&&this.hasListeners("progress")&&(r.upload.onprogress=u)}catch(f){}if(s&&!this._timer&&(this._timer=setTimeout(function(){t.timedout=!0,t.abort()},s)),i&&(i=E.serializeObject(i),this.url+=~this.url.indexOf("?")?"&"+i:"?"+i),this.username&&this.password?r.open(this.method,this.url,!0,this.username,this.password):r.open(this.method,this.url,!0),this._withCredentials&&(r.withCredentials=!0),"GET"!=this.method&&"HEAD"!=this.method&&"string"!=typeof a&&!o(a)){var p=this._header["content-type"],h=this._parser||E.serialize[p?p.split(";")[0]:""];!h&&c(p)&&(h=E.serialize["application/json"]),h&&(a=h(a))}for(var l in this.header)null!=this.header[l]&&r.setRequestHeader(l,this.header[l]);return this._responseType&&(r.responseType=this._responseType),this.emit("request",this),r.send("undefined"!=typeof a?a:null),this},E.Request=l,E.get=function(e,t,r){var n=E("GET",e);return"function"==typeof t&&(r=t,t=null),t&&n.query(t),r&&n.end(r),n},E.head=function(e,t,r){var n=E("HEAD",e);return"function"==typeof t&&(r=t,t=null),t&&n.send(t),r&&n.end(r),n},E.del=d,E["delete"]=d,E.patch=function(e,t,r){var n=E("PATCH",e);return"function"==typeof t&&(r=t,t=null),t&&n.send(t),r&&n.end(r),n},E.post=function(e,t,r){var n=E("POST",e);return"function"==typeof t&&(r=t,t=null),t&&n.send(t),r&&n.end(r),n},E.put=function(e,t,r){var n=E("PUT",e);return"function"==typeof t&&(r=t,t=null),t&&n.send(t),r&&n.end(r),n}},{"./is-object":15,"./request":17,"./request-base":16,emitter:2,reduce:12}],15:[function(e,t,r){function n(e){return null!=e&&"object"==typeof e}t.exports=n},{}],16:[function(e,t,r){var n=e("./is-object");r.clearTimeout=function(){return this._timeout=0,clearTimeout(this._timer),this},r.parse=function(e){return this._parser=e,this},r.timeout=function(e){return this._timeout=e,this},r.then=function(e,t){return this.end(function(r,n){r?t(r):e(n)})},r.use=function(e){return e(this),this},r.get=function(e){return this._header[e.toLowerCase()]},r.getHeader=r.get,r.set=function(e,t){if(n(e)){for(var r in e)this.set(r,e[r]);return this}return this._header[e.toLowerCase()]=t,this.header[e]=t,this},r.unset=function(e){return delete this._header[e.toLowerCase()], -delete this.header[e],this},r.field=function(e,t){return this._getFormData().append(e,t),this}},{"./is-object":15}],17:[function(e,t,r){function n(e,t,r){return"function"==typeof r?new e("GET",t).end(r):2==arguments.length?new e("GET",t):new e(t,r)}t.exports=n},{}],18:[function(e,t,r){var n=function(){function e(e){throw new RangeError(P[e])}function t(e,t){for(var r=e.length,n=[];r--;)n[r]=t(e[r]);return n}function r(e,r){var n=e.split("@"),o="";n.length>1&&(o=n[0]+"@",e=n[1]),e=e.replace(O,".");var i=e.split("."),s=t(i,r).join(".");return o+s}function n(e){for(var t,r,n=[],o=0,i=e.length;i>o;)t=e.charCodeAt(o++),t>=55296&&56319>=t&&i>o?(r=e.charCodeAt(o++),56320==(64512&r)?n.push(((1023&t)<<10)+(1023&r)+65536):(n.push(t),o--)):n.push(t);return n}function o(e){return t(e,function(e){var t="";return e>65535&&(e-=65536,t+=A(e>>>10&1023|55296),e=56320|1023&e),t+=A(e)}).join("")}function i(e){return 10>e-48?e-22:26>e-65?e-65:26>e-97?e-97:d}function s(e,t){return e+22+75*(26>e)-((0!=t)<<5)}function a(e,t,r){var n=0;for(e=r?_(e/g):e>>1,e+=_(e/t);e>T*v>>1;n+=d)e=_(e/T);return _(n+(T+1)*e/(e+m))}function u(t){var r,n,s,u,c,f,p,h,m,g,x=[],C=t.length,O=0,P=E,T=b;for(n=t.lastIndexOf(w),0>n&&(n=0),s=0;n>s;++s)t.charCodeAt(s)>=128&&e("not-basic"),x.push(t.charCodeAt(s));for(u=n>0?n+1:0;C>u;){for(c=O,f=1,p=d;u>=C&&e("invalid-input"),h=i(t.charCodeAt(u++)),(h>=d||h>_((l-O)/f))&&e("overflow"),O+=h*f,m=T>=p?y:p>=T+v?v:p-T,!(m>h);p+=d)g=d-m,f>_(l/g)&&e("overflow"),f*=g;r=x.length+1,T=a(O-c,r,0==c),_(O/r)>l-P&&e("overflow"),P+=_(O/r),O%=r,x.splice(O++,0,P)}return o(x)}function c(t){var r,o,i,u,c,f,p,h,m,g,x,C,O,P,T,j=[];for(t=n(t),C=t.length,r=E,o=0,c=b,f=0;C>f;++f)x=t[f],128>x&&j.push(A(x));for(i=u=j.length,u&&j.push(w);C>i;){for(p=l,f=0;C>f;++f)x=t[f],x>=r&&p>x&&(p=x);for(O=i+1,p-r>_((l-o)/O)&&e("overflow"),o+=(p-r)*O,r=p,f=0;C>f;++f)if(x=t[f],r>x&&++o>l&&e("overflow"),x==r){for(h=o,m=d;g=c>=m?y:m>=c+v?v:m-c,!(g>h);m+=d)T=h-g,P=d-g,j.push(A(s(g+T%P,0))),h=_(T/P);j.push(A(s(h,0))),c=a(o,O,i==u),o=0,++i}++o,++r}return j.join("")}function f(e){return r(e,function(e){return x.test(e)?u(e.slice(4).toLowerCase()):e})}function p(e){return r(e,function(e){return C.test(e)?"xn--"+c(e):e})}var h,l=2147483647,d=36,y=1,v=26,m=38,g=700,b=72,E=128,w="-",x=/^xn--/,C=/[^\x20-\x7E]/,O=/[\x2E\u3002\uFF0E\uFF61]/g,P={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},T=d-y,_=Math.floor,A=String.fromCharCode;return h={version:"1.3.2",ucs2:{decode:n,encode:o},decode:u,encode:c,toASCII:p,toUnicode:f}}();"undefined"==typeof COMPILED&&"undefined"!=typeof t&&(t.exports=n)},{}],19:[function(e,t,r){e("./schemes/http"),e("./schemes/urn"),e("./schemes/mailto")},{"./schemes/http":20,"./schemes/mailto":21,"./schemes/urn":22}],20:[function(e,t,r){if("undefined"==typeof COMPILED&&"undefined"==typeof n&&"function"==typeof e)var n=e("../uri");n.SCHEMES.http=n.SCHEMES.https={domainHost:!0,parse:function(e,t){return e.host||(e.error=e.error||"HTTP URIs must have a host."),e},serialize:function(e,t){return e.port!==("https"!==String(e.scheme).toLowerCase()?80:443)&&""!==e.port||(e.port=void 0),e.path||(e.path="/"),e}}},{"../uri":23}],21:[function(e,t,r){if("undefined"==typeof COMPILED&&"undefined"==typeof n&&"function"==typeof e)var n=e("../uri"),o=e("../punycode");!function(){function e(){for(var e=[],t=0;t1){e[0]=e[0].slice(0,-1);for(var r=e.length-1,n=1;r>n;++n)e[n]=e[n].slice(1,-1);return e[r]=e[r].slice(1),e.join("")}return e[0]}function t(e){return"(?:"+e+")"}function r(e){return e.toUpperCase()}function i(e){var t=n.pctDecChars(e);return t.match(D)?t:e}function s(e){return void 0!==e&&null!==e?e instanceof Array&&!e.callee?e:"number"!=typeof e.length||e.split||e.setInterval||e.call?[e]:Array.prototype.slice.call(e):[]}var a={},u=n.IRI_SUPPORT,c="[A-Za-z0-9\\-\\.\\_\\~"+(u?"\\xA0-\\u200D\\u2010-\\u2029\\u202F-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF":"")+"]",f="[0-9A-Fa-f]",p=t(t("%[EFef]"+f+"%"+f+f+"%"+f+f)+"|"+t("%[89A-Fa-f]"+f+"%"+f+f)+"|"+t("%"+f+f)),h="[A-Za-z0-9\\!\\$\\%\\'\\*\\+\\-\\^\\_\\`\\{\\|\\}\\~]",l="[\\!\\$\\%\\'\\(\\)\\*\\+\\,\\-\\.0-9\\<\\>A-Z\\x5E-\\x7E]",d=e(l,'[\\"\\\\]'),y=t(h+"+"+t("\\."+h+"+")+"*"),v=t("\\\\"+d),m=t(l+"|"+v),g=t('\\"'+m+'*\\"'),b="[\\x21-\\x5A\\x5E-\\x7E]",E="[\\!\\$\\'\\(\\)\\*\\+\\,\\;\\:\\@]",w=t(c+"|"+p+"|"+E),x=t(y+"|\\["+b+"*\\]"),C=t(y+"|"+g),O=t(C+"\\@"+x),P=t(O+t("\\,"+O)+"*"),T=t(w+"*"),_=T,A=t(T+"\\="+_),j=t(A+t("\\&"+A)+"*"),S=t("\\?"+j),D=(n.VALIDATE_SUPPORT&&new RegExp("^mailto\\:"+P+"?"+S+"?$"),new RegExp(c,"g")),R=new RegExp(p,"g"),U=new RegExp(e("[^]",h,"[\\.]",'[\\"]',d),"g"),I=new RegExp(e("[^]",h,"[\\.]","[\\[]",b,"[\\]]"),"g"),N=new RegExp(e("[^]",c,E),"g"),F=N,q=n.VALIDATE_SUPPORT&&new RegExp("^"+P+"$"),H=n.VALIDATE_SUPPORT&&new RegExp("^"+j+"$");n.SCHEMES.mailto={parse:function(e,t){n.VALIDATE_SUPPORT&&!e.error&&(e.path&&!q.test(e.path)?e.error="Email address is not valid":e.query&&!H.test(e.query)&&(e.error="Header fields are invalid"));var r=e.to=e.path?e.path.split(","):[];if(e.path=void 0,e.query){for(var i=!1,s={},a=e.query.split("&"),u=0,c=a.length;c>u;++u){var f=a[u].split("=");switch(f[0]){case"to":for(var p=f[1].split(","),h=0,l=p.length;l>h;++h)r.push(p[h]);break;case"subject":e.subject=n.unescapeComponent(f[1],t);break;case"body":e.body=n.unescapeComponent(f[1],t);break;default:i=!0,s[n.unescapeComponent(f[0],t)]=n.unescapeComponent(f[1],t)}}i&&(e.headers=s)}e.query=void 0;for(var u=0,c=r.length;c>u;++u){var d=r[u].split("@");if(d[0]=n.unescapeComponent(d[0]),"undefined"==typeof o||t.unicodeSupport)d[1]=n.unescapeComponent(d[1],t).toLowerCase();else try{d[1]=o.toASCII(n.unescapeComponent(d[1],t).toLowerCase())}catch(y){e.error=e.error||"Email address's domain name can not be converted to ASCII via punycode: "+y}r[u]=d.join("@")}return e},serialize:function(e,t){var u=s(e.to);if(u){for(var c=0,f=u.length;f>c;++c){var p=String(u[c]),h=p.lastIndexOf("@"),l=p.slice(0,h),d=p.slice(h+1);if(l=l.replace(R,i).replace(R,r).replace(U,n.pctEncChar),"undefined"!=typeof o)try{d=t.iri?o.toUnicode(d):o.toASCII(n.unescapeComponent(d,t).toLowerCase())}catch(y){e.error=e.error||"Email address's domain name can not be converted to "+(t.iri?"Unicode":"ASCII")+" via punycode: "+y}else d=d.replace(R,i).toLowerCase().replace(R,r).replace(I,n.pctEncChar);u[c]=l+"@"+d}e.path=u.join(",")}var v=e.headers=e.headers||{};e.subject&&(v.subject=e.subject),e.body&&(v.body=e.body);var m=[];for(var g in v)v[g]!==a[g]&&m.push(g.replace(R,i).replace(R,r).replace(N,n.pctEncChar)+"="+v[g].replace(R,i).replace(R,r).replace(F,n.pctEncChar));return m.length&&(e.query=m.join("&")),e}}}()},{"../punycode":18,"../uri":23}],22:[function(e,t,r){if("undefined"==typeof COMPILED&&"undefined"==typeof n&&"function"==typeof e)var n=e("../uri");!function(){var e=n.pctEncChar,t="(?:[0-9A-Za-z][0-9A-Za-z\\-]{1,31})",r="(?:\\%[0-9A-Fa-f]{2})",o="[0-9A-Za-z\\(\\)\\+\\,\\-\\.\\:\\=\\@\\;\\$\\_\\!\\*\\'\\/\\?\\#]",i="(?:(?:"+r+"|"+o+")+)",s=new RegExp("^urn\\:("+t+")$"),a=new RegExp("^("+t+")\\:("+i+")$"),u=/^([^\:]+)\:(.*)/,c=/[\x00-\x20\\\"\&\<\>\[\]\^\`\{\|\}\~\x7F-\xFF]/g,f=/^[0-9A-Fa-f]{8}(?:\-[0-9A-Fa-f]{4}){3}\-[0-9A-Fa-f]{12}$/;n.SCHEMES.urn={parse:function(e,t){var r,o,i=e.path.match(a);return i||(t.tolerant||(e.error=e.error||"URN is not strictly valid."),i=e.path.match(u)),i?(r="urn:"+i[1].toLowerCase(),o=n.SCHEMES[r],o||(o=n.SCHEMES[r]={parse:function(e,t){return e},serialize:n.SCHEMES.urn.serialize}),e.scheme=r,e.path=i[2],e=o.parse(e,t)):e.error=e.error||"URN can not be parsed.",e},serialize:function(t,r){var n,o=t.scheme||r.scheme;if(o&&"urn"!==o){var n=o.match(s);n||(n=["urn:"+o,o]),t.scheme="urn",t.path=n[1]+":"+(t.path?t.path.replace(c,e):"")}return t}},n.SCHEMES["urn:uuid"]={parse:function(e,t){return t.tolerant||e.path&&e.path.match(f)||(e.error=e.error||"UUID is not valid."),e},serialize:function(e,t){return t.tolerant||e.path&&e.path.match(f)?e.path=(e.path||"").toLowerCase():e.scheme=void 0,n.SCHEMES.urn.serialize(e,t)}}}()},{"../uri":23}],23:[function(e,t,r){var n=!1,o=!0,i=!0,s=function(){function e(){for(var e=[],t=0;t1){e[0]=e[0].slice(0,-1);for(var r=e.length-1,n=1;r>n;++n)e[n]=e[n].slice(1,-1);return e[r]=e[r].slice(1),e.join("")}return e[0]}function t(e){return"(?:"+e+")"}function r(r){var n="[A-Za-z]",o="[0-9]",s=e(o,"[A-Fa-f]"),a=t(t("%[EFef]"+s+"%"+s+s+"%"+s+s)+"|"+t("%[89A-Fa-f]"+s+"%"+s+s)+"|"+t("%"+s+s)),u="[\\:\\/\\?\\#\\[\\]\\@]",c="[\\!\\$\\&\\'\\(\\)\\*\\+\\,\\;\\=]",f=e(u,c),p=r?"[\\xA0-\\u200D\\u2010-\\u2029\\u202F-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]":"[]",h=r?"[\\uE000-\\uF8FF]":"[]",l=e(n,o,"[\\-\\.\\_\\~]",p),d=t(n+e(n,o,"[\\+\\-\\.]")+"*"),y=t(t(a+"|"+e(l,c,"[\\:]"))+"*"),v=t(t("25[0-5]")+"|"+t("2[0-4]"+o)+"|"+t("1"+o+o)+"|"+t("[1-9]"+o)+"|"+o),m=t(v+"\\."+v+"\\."+v+"\\."+v),g=t(s+"{1,4}"),b=(t(t(g+"\\:"+g)+"|"+m),t(e(l,c,"[\\:]")+"+")),E=t("v"+s+"+\\."+e(l,c,"[\\:]")+"+"),w=t("\\["+t(b+"|"+E)+"\\]"),x=t(t(a+"|"+e(l,c))+"*"),C=t(w+"|"+m+"(?!"+x+")|"+x),O=t(o+"*"),P=t(t(y+"@")+"?"+C+t("\\:"+O)+"?"),T=t(a+"|"+e(l,c,"[\\:\\@]")),_=t(T+"*"),A=t(T+"+"),j=t(t(a+"|"+e(l,c,"[\\@]"))+"+"),S=t(t("\\/"+_)+"*"),D=t("\\/"+t(A+S)+"?"),R=t(j+S),U=t(A+S),I="(?!"+T+")",N=(t(S+"|"+D+"|"+R+"|"+U+"|"+I),t(t(T+"|"+e("[\\/\\?]",h))+"*")),F=t(t(T+"|[\\/\\?]")+"*"),q=t(t("\\/\\/"+P+S)+"|"+D+"|"+U+"|"+I),H=t(d+"\\:"+q+t("\\?"+N)+"?"+t("\\#"+F)+"?"),k=t(t("\\/\\/"+P+S)+"|"+D+"|"+R+"|"+I),L=t(k+t("\\?"+N)+"?"+t("\\#"+F)+"?"),M=(t(H+"|"+L),t(d+"\\:"+q+t("\\?"+N)+"?"),"^("+d+")\\:"+t(t("\\/\\/("+t("("+y+")@")+"?("+C+")"+t("\\:("+O+")")+"?)")+"?("+S+"|"+D+"|"+U+"|"+I+")")+t("\\?("+N+")")+"?"+t("\\#("+F+")")+"?$"),$="^(){0}"+t(t("\\/\\/("+t("("+y+")@")+"?("+C+")"+t("\\:("+O+")")+"?)")+"?("+S+"|"+D+"|"+R+"|"+I+")")+t("\\?("+N+")")+"?"+t("\\#("+F+")")+"?$";"^("+d+")\\:"+t(t("\\/\\/("+t("("+y+")@")+"?("+C+")"+t("\\:("+O+")")+"?)")+"?("+S+"|"+D+"|"+U+"|"+I+")")+t("\\?("+N+")")+"?$","^"+t("\\#("+F+")")+"?$","^"+t("("+y+")@")+"?("+C+")"+t("\\:("+O+")")+"?$";return{URI_REF:i&&new RegExp("("+M+")|("+$+")"),NOT_SCHEME:new RegExp(e("[^]",n,o,"[\\+\\-\\.]"),"g"),NOT_USERINFO:new RegExp(e("[^\\%\\:]",l,c),"g"),NOT_HOST:new RegExp(e("[^\\%]",l,c),"g"),NOT_PATH:new RegExp(e("[^\\%\\/\\:\\@]",l,c),"g"),NOT_PATH_NOSCHEME:new RegExp(e("[^\\%\\/\\@]",l,c),"g"),NOT_QUERY:new RegExp(e("[^\\%]",l,c,"[\\:\\@\\/\\?]",h),"g"),NOT_FRAGMENT:new RegExp(e("[^\\%]",l,c,"[\\:\\@\\/\\?]"),"g"),ESCAPE:new RegExp(e("[^]",l,c),"g"),UNRESERVED:new RegExp(l,"g"),OTHER_CHARS:new RegExp(e("[^\\%]",l,f),"g"),PCT_ENCODED:new RegExp(a,"g")}}function n(e){var t,r=e.charCodeAt(0);return t=16>r?"%0"+r.toString(16).toUpperCase():128>r?"%"+r.toString(16).toUpperCase():2048>r?"%"+(r>>6|192).toString(16).toUpperCase()+"%"+(63&r|128).toString(16).toUpperCase():"%"+(r>>12|224).toString(16).toUpperCase()+"%"+(r>>6&63|128).toString(16).toUpperCase()+"%"+(63&r|128).toString(16).toUpperCase()}function s(e){for(var t,r,n,o="",i=0,s=e.length;s>i;)t=parseInt(e.substr(i+1,2),16),128>t?(o+=String.fromCharCode(t),i+=3):t>=194&&224>t?(s-i>=6?(r=parseInt(e.substr(i+4,2),16),o+=String.fromCharCode((31&t)<<6|63&r)):o+=e.substr(i,6),i+=6):t>=224?(s-i>=9?(r=parseInt(e.substr(i+4,2),16),n=parseInt(e.substr(i+7,2),16),o+=String.fromCharCode((15&t)<<12|(63&r)<<6|63&n)):o+=e.substr(i,9),i+=9):(o+=e.substr(i,3),i+=3);return o}function u(e){return void 0===e?"undefined":null===e?"null":Object.prototype.toString.call(e).split(" ").pop().split("]").shift().toLowerCase()}function c(e){return e.toUpperCase()}function f(e,t){function r(e){var r=s(e);return r.match(t.UNRESERVED)?r:e}return e.scheme&&(e.scheme=String(e.scheme).replace(t.PCT_ENCODED,r).toLowerCase().replace(t.NOT_SCHEME,"")),void 0!==e.userinfo&&(e.userinfo=String(e.userinfo).replace(t.PCT_ENCODED,r).replace(t.NOT_USERINFO,n).replace(t.PCT_ENCODED,c)),void 0!==e.host&&(e.host=String(e.host).replace(t.PCT_ENCODED,r).toLowerCase().replace(t.NOT_HOST,n).replace(t.PCT_ENCODED,c)),void 0!==e.path&&(e.path=String(e.path).replace(t.PCT_ENCODED,r).replace(e.scheme?t.NOT_PATH:t.NOT_PATH_NOSCHEME,n).replace(t.PCT_ENCODED,c)),void 0!==e.query&&(e.query=String(e.query).replace(t.PCT_ENCODED,r).replace(t.NOT_QUERY,n).replace(t.PCT_ENCODED,c)),void 0!==e.fragment&&(e.fragment=String(e.fragment).replace(t.PCT_ENCODED,r).replace(t.NOT_FRAGMENT,n).replace(t.PCT_ENCODED,c)),e}function p(e,t){void 0===t&&(t={});var r,n,u=o&&t.iri!==!1?x:w,c=!1,p={};if("suffix"===t.reference&&(e=(t.scheme?t.scheme+":":"")+"//"+e),i?(r=e.match(u.URI_REF),r&&(r=r[1]?r.slice(1,10):r.slice(10,19)),r||(c=!0,t.tolerant||(p.error=p.error||"URI is not strictly valid."),r=e.match(C))):r=e.match(C),r){if(A?(p.scheme=r[1],p.userinfo=r[3],p.host=r[4],p.port=parseInt(r[5],10),p.path=r[6]||"",p.query=r[7],p.fragment=r[8],isNaN(p.port)&&(p.port=r[5])):(p.scheme=r[1]||void 0,p.userinfo=-1!==e.indexOf("@")?r[3]:void 0,p.host=-1!==e.indexOf("//")?r[4]:void 0,p.port=parseInt(r[5],10),p.path=r[6]||"",p.query=-1!==e.indexOf("?")?r[7]:void 0,p.fragment=-1!==e.indexOf("#")?r[8]:void 0,isNaN(p.port)&&(p.port=e.match(/\/\/(?:.|\n)*\:(?:\/|\?|\#|$)/)?r[4]:void 0)),void 0!==p.scheme||void 0!==p.userinfo||void 0!==p.host||void 0!==p.port||p.path||void 0!==p.query?void 0===p.scheme?p.reference="relative":void 0===p.fragment?p.reference="absolute":p.reference="uri":p.reference="same-document",t.reference&&"suffix"!==t.reference&&t.reference!==p.reference&&(p.error=p.error||"URI is not a "+t.reference+" reference."),n=j[(t.scheme||p.scheme||"").toLowerCase()],!o||"undefined"==typeof a||t.unicodeSupport||n&&n.unicodeSupport)f(p,u);else{if(p.host&&(t.domainHost||n&&n.domainHost))try{p.host=a.toASCII(p.host.replace(u.PCT_ENCODED,s).toLowerCase())}catch(h){p.error=p.error||"Host's domain name can not be converted to ASCII via punycode: "+h}f(p,w)}n&&n.parse&&n.parse(p,t)}else c=!0,p.error=p.error||"URI can not be parsed.";return p}function h(e,t){var r=[];return void 0!==e.userinfo&&(r.push(e.userinfo),r.push("@")),void 0!==e.host&&r.push(e.host),"number"==typeof e.port&&(r.push(":"),r.push(e.port.toString(10))),r.length?r.join(""):void 0}function l(e){for(var t,r=[];e.length;)e.match(O)?e=e.replace(O,""):e.match(P)?e=e.replace(P,"/"):e.match(T)?(e=e.replace(T,"/"),r.pop()):"."===e||".."===e?e="":(t=e.match(_)[0],e=e.slice(t.length),r.push(t));return r.join("")}function d(e,t){void 0===t&&(t={});var r,n,i,u=o&&t.iri?x:w,c=[];if(r=j[(t.scheme||e.scheme||"").toLowerCase()],r&&r.serialize&&r.serialize(e,t),o&&"undefined"!=typeof a&&e.host&&(t.domainHost||r&&r.domainHost))try{e.host=t.iri?a.toUnicode(e.host):a.toASCII(e.host.replace(u.PCT_ENCODED,s).toLowerCase())}catch(p){e.error=e.error||"Host's domain name can not be converted to "+(t.iri?"Unicode":"ASCII")+" via punycode: "+p}return f(e,u),"suffix"!==t.reference&&e.scheme&&(c.push(e.scheme),c.push(":")),n=h(e,t),void 0!==n&&("suffix"!==t.reference&&c.push("//"),c.push(n),e.path&&"/"!==e.path.charAt(0)&&c.push("/")),void 0!==e.path&&(i=e.path,t.absolutePath||r&&r.absolutePath||(i=l(i)),void 0===n&&(i=i.replace(/^\/\//,"/%2F")),c.push(i)),void 0!==e.query&&(c.push("?"),c.push(e.query)),void 0!==e.fragment&&(c.push("#"),c.push(e.fragment)),c.join("")}function y(e,t,r,n){void 0===r&&(r={});var o={};return n||(e=p(d(e,r),r),t=p(d(t,r),r)),r=r||{},!r.tolerant&&t.scheme?(o.scheme=t.scheme,o.userinfo=t.userinfo,o.host=t.host,o.port=t.port,o.path=l(t.path),o.query=t.query):(void 0!==t.userinfo||void 0!==t.host||void 0!==t.port?(o.userinfo=t.userinfo,o.host=t.host,o.port=t.port,o.path=l(t.path),o.query=t.query):(t.path?("/"===t.path.charAt(0)?o.path=l(t.path):(void 0===e.userinfo&&void 0===e.host&&void 0===e.port||e.path?e.path?o.path=e.path.slice(0,e.path.lastIndexOf("/")+1)+t.path:o.path=t.path:o.path="/"+t.path,o.path=l(o.path)),o.query=t.query):(o.path=e.path,void 0!==t.query?o.query=t.query:o.query=e.query),o.userinfo=e.userinfo,o.host=e.host,o.port=e.port),o.scheme=e.scheme),o.fragment=t.fragment,o}function v(e,t,r){return d(y(p(e,r),p(t,r),r,!0),r)}function m(e,t){return"string"==typeof e?e=d(p(e,t),t):"object"===u(e)&&(e=p(d(e,t),t)),e}function g(e,t,r){return"string"==typeof e?e=d(p(e,r),r):"object"===u(e)&&(e=d(e,r)),"string"==typeof t?t=d(p(t,r),r):"object"===u(t)&&(t=d(t,r)),e===t}function b(e,t){return e&&e.toString().replace(o&&t&&t.iri?x.ESCAPE:w.ESCAPE,n)}function E(e,t){return e&&e.toString().replace(o&&t&&t.iri?x.PCT_ENCODED:w.PCT_ENCODED,s)}var w=r(!1),x=o?r(!0):void 0,C=/^(?:([^:\/?#]+):)?(?:\/\/((?:([^\/?#@]*)@)?([^\/?#:]*)(?:\:(\d*))?))?([^?#]*)(?:\?([^#]*))?(?:#((?:.|\n)*))?/i,O=/^\.\.?\//,P=/^\/\.(\/|$)/,T=/^\/\.\.(\/|$)/,_=/^\/?(?:.|\n)*?(?=\/|$)/,A=void 0==="".match(/(){0}/)[1],j={};return{IRI_SUPPORT:o,VALIDATE_SUPPORT:i,pctEncChar:n,pctDecChars:s,SCHEMES:j,parse:p,_recomposeAuthority:h,removeDotSegments:l,serialize:d,resolveComponents:y,resolve:v,normalize:m,equal:g,escapeComponent:b,unescapeComponent:E}}();if(!n&&"undefined"!=typeof t&&"function"==typeof e){var a=e("./punycode");t.exports=s,e("./schemes")}},{"./punycode":18,"./schemes":19}]},{},[1])(1)}); \ No newline at end of file diff --git a/packages/jsfc/lib/json-refs-standalone.js b/packages/jsfc/lib/json-refs-standalone.js deleted file mode 100644 index e9ec4475dcb..00000000000 --- a/packages/jsfc/lib/json-refs-standalone.js +++ /dev/null @@ -1,5409 +0,0 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.JsonRefs = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o -1) { - combinedDetails = u2Details; - } else { - u1Details = isType(u1, 'Undefined') ? undefined : parseURI(u1); - - if (!isType(u1Details, 'Undefined')) { - combinedDetails = u1Details; - - // Join the paths - combinedDetails.path = slash(path.join(u1Details.path, u2Details.path)); - - // Join query parameters - combinedDetails.query = combineQueryParams(u1Details.query, u2Details.query); - } else { - combinedDetails = u2Details; - } - } - - // Remove the fragment - combinedDetails.fragment = undefined; - - // For relative URIs, add back the '..' since it was removed above - return (remoteUriTypes.indexOf(combinedDetails.reference) === -1 && - combinedDetails.path.indexOf('../') === 0 ? '../' : '') + URI.serialize(combinedDetails); -} - -function findAncestors (obj, path) { - var ancestors = []; - var node; - - if (path.length > 0) { - node = obj; - - path.slice(0, path.length - 1).forEach(function (seg) { - if (seg in node) { - node = node[seg]; - - ancestors.push(node); - } - }); - } - - return ancestors; -} - -function processSubDocument (mode, doc, subDocPath, refDetails, options, parents, parentPtrs, allRefs, indirect) { - var refValue; - var rOptions; - - if (subDocPath.length > 0) { - try { - refValue = findValue(doc, subDocPath); - } catch (err) { - // We only mark missing remote references as missing because local references can have deferred values - if (mode === 'remote') { - refDetails.error = err.message; - refDetails.missing = true; - } - } - } else { - refValue = doc; - } - - if (!isType(refValue, 'Undefined')) { - refDetails.value = refValue; - } - - if (isType(refValue, 'Array') || isType(refValue, 'Object')) { - rOptions = clone(options); - - if (mode === 'local') { - delete rOptions.subDocPath; - - // Traverse the dereferenced value - doc = refValue; - } else { - rOptions.relativeBase = path.dirname(parents[parents.length - 1]); - - if (subDocPath.length === 0) { - delete rOptions.subDocPath; - } else { - rOptions.subDocPath = subDocPath; - } - } - - return findRefsRecursive(doc, rOptions, parents, parentPtrs, allRefs, indirect); - } -} - -// Should this be its own exported API? -function findRefsRecursive (obj, options, parents, parentPtrs, allRefs, indirect) { - var allTasks = Promise.resolve(); - var parentPath = parentPtrs.length ? pathFromPtr(parentPtrs[parentPtrs.length - 1]) : []; - var refs = findRefs(obj, options); - var subDocPath = options.subDocPath || []; - var subDocPtr = pathToPtr(subDocPath); - var ancestorPtrs = ['#']; - - parents.forEach(function (parent, index) { - if (parent.charAt(0) !== '#') { - ancestorPtrs.push(parentPtrs[index]); - } - }); - - // Reverse the order so we search them in the proper order - ancestorPtrs.reverse(); - - if ((parents[parents.length - 1] || '').charAt(0) !== '#') { - allRefs.documents[pathToPtr(parentPath)] = obj; - } - - Object.keys(refs).forEach(function (refPtr) { - var refDetails = refs[refPtr]; - var location; - var parentIndex; - var refFullPath; - var refFullPtr; - - // If there are no parents, treat the reference pointer as-is. Otherwise, the reference is a reference within a - // remote document and its sub document path prefix must be removed. - if (parents.length === 0) { - refFullPath = parentPath.concat(pathFromPtr(refPtr)); - } else { - refFullPath = parentPath.concat(pathFromPtr(refPtr).slice(parents.length === 0 ? 0 : subDocPath.length)); - } - - refFullPtr = pathToPtr(refFullPath); - - // It is possible to process the same reference more than once in the event of hierarchical references so we avoid - // processing a reference if we've already done so. - if (!isType(allRefs[refFullPtr], 'Undefined')) { - return; - } - - // Record the reference metadata - allRefs.refs[refFullPtr] = refs[refPtr]; - - // Do not process invalid references - if (isType(refDetails.error, 'Undefined') && refDetails.type !== 'invalid') { - if (remoteTypes.indexOf(refDetails.type) > -1) { - location = combineURIs(options.relativeBase, refDetails.uri); - parentIndex = parents.indexOf(location); - } else { - location = refDetails.uri; - parentIndex = parentPtrs.indexOf(location); - } - - // Record ancestor paths - refDetails.ancestorPtrs = ancestorPtrs; - - // Record if the reference is indirect based on its parent - refDetails.indirect = indirect; - - // Only process non-circular references further - if (parentIndex === -1) { - if (remoteTypes.indexOf(refDetails.type) > -1) { - allTasks = allTasks - .then(function () { - return getRemoteDocument(location, options) - .then(function (doc) { - return processSubDocument('remote', - doc, - isType(refDetails.uriDetails.fragment, 'Undefined') ? - [] : - pathFromPtr(decodeURI(refDetails.uriDetails.fragment)), - refDetails, - options, - parents.concat(location), - parentPtrs.concat(refFullPtr), - allRefs, - indirect); - }) - .catch(function (err) { - refDetails.error = err.message; - refDetails.missing = true; - }); - }); - } else { - if (refFullPtr.indexOf(location + '/') !== 0 && refFullPtr !== location && - subDocPtr.indexOf(location + '/') !== 0 && subDocPtr !== location) { - if (location.indexOf(subDocPtr + '/') !== 0) { - allTasks = allTasks - .then(function () { - return processSubDocument('local', - obj, - pathFromPtr(location), - refDetails, - options, - parents.concat(location), - parentPtrs.concat(refFullPtr), - allRefs, - indirect || (location.indexOf(subDocPtr + '/') === -1 && location !== subDocPtr)); - }); - } - } else { - refDetails.circular = true; - } - } - } else { - // Mark seen ancestors as circular - parentPtrs.slice(parentIndex).forEach(function (parentPtr) { - allRefs.refs[parentPtr].circular = true; - }); - - refDetails.circular = true; - } - } - }); - - allTasks = allTasks - .then(function () { - // Identify indirect, local circular references (Issue 82) - var circulars = []; - var processedRefPtrs = []; - var processedRefs = []; - - function walkRefs (parentPtrs, parentRefs, refPtr, ref) { - Object.keys(allRefs.refs).forEach(function (dRefPtr) { - var dRefDetails = allRefs.refs[dRefPtr]; - - // Do not process already processed references or references that are not a nested references - if (processedRefs.indexOf(ref) === -1 && processedRefPtrs.indexOf(refPtr) === -1 && - circulars.indexOf(ref) === -1 && dRefPtr !== refPtr && dRefPtr.indexOf(ref + '/') === 0) { - if (parentRefs.indexOf(ref) > -1) { - parentRefs.forEach(function (parentRef) { - if (circulars.indexOf(ref) === -1) { - circulars.push(parentRef); - } - }); - } else { - walkRefs(parentPtrs.concat(refPtr), parentRefs.concat(ref), dRefPtr, dRefDetails.uri); - } - - processedRefPtrs.push(refPtr); - processedRefs.push(ref); - } - }); - } - - Object.keys(allRefs.refs).forEach(function (refPtr) { - var refDetails = allRefs.refs[refPtr]; - - // Only process local, non-circular references - if (refDetails.type === 'local' && !refDetails.circular && circulars.indexOf(refDetails.uri) === -1) { - walkRefs([], [], refPtr, refDetails.uri); - } - }); - - Object.keys(allRefs.refs).forEach(function (refPtr) { - var refDetails = allRefs.refs[refPtr]; - - if (circulars.indexOf(refDetails.uri) > -1) { - refDetails.circular = true; - } - }); - }) - .then(function () { - return allRefs; - }); - - return allTasks; -} - -function findValue (obj, path) { - var value = obj; - - path.forEach(function (seg) { - seg = decodeURI(seg); - - if (seg in value) { - value = value[seg]; - } else { - throw Error('JSON Pointer points to missing location: ' + pathToPtr(path)); - } - }); - - return value; -} - -function getExtraRefKeys (ref) { - return Object.keys(ref).filter(function (key) { - return key !== '$ref'; - }); -} - -function getRefType (refDetails) { - var type; - - // Convert the URI reference to one of our types - switch (refDetails.uriDetails.reference) { - case 'absolute': - case 'uri': - type = 'remote'; - break; - case 'same-document': - type = 'local'; - break; - default: - type = refDetails.uriDetails.reference; - } - - return type; -} - -function getRemoteDocument (url, options) { - var cacheEntry = remoteCache[url]; - var allTasks = Promise.resolve(); - var loaderOptions = clone(options.loaderOptions || {}); - - if (isType(cacheEntry, 'Undefined')) { - // If there is no content processor, default to processing the raw response as JSON - if (isType(loaderOptions.processContent, 'Undefined')) { - loaderOptions.processContent = function (res, callback) { - callback(undefined, JSON.parse(res.text)); - }; - } - - // Attempt to load the resource using path-loader - allTasks = PathLoader.load(decodeURI(url), loaderOptions); - - // Update the cache - allTasks = allTasks - .then(function (res) { - remoteCache[url] = { - value: res - }; - - return res; - }) - .catch(function (err) { - remoteCache[url] = { - error: err - }; - - throw err; - }); - } else { - // Return the cached version - allTasks = allTasks.then(function () { - return cacheEntry.value; - }); - } - - // Return a cloned version to avoid updating the cache - allTasks = allTasks.then(function (res) { - return clone(res); - }); - - return allTasks; -} - -function isRefLike (obj, throwWithDetails) { - var refLike = true; - - try { - if (!isType(obj, 'Object')) { - throw new Error('obj is not an Object'); - } else if (!isType(obj.$ref, 'String')) { - throw new Error('obj.$ref is not a String'); - } - } catch (err) { - if (throwWithDetails) { - throw err; - } - - refLike = false; - } - - return refLike; -} - -function isType (obj, type) { - // A PhantomJS bug (https://github.com/ariya/phantomjs/issues/11722) prohibits us from using the same approach for - // undefined checking that we use for other types. - if (type === 'Undefined') { - return typeof obj === 'undefined'; - } else { - return Object.prototype.toString.call(obj) === '[object ' + type + ']'; - } -} - -function makeRefFilter (options) { - var refFilter; - var validTypes; - - if (isType(options.filter, 'Array') || isType(options.filter, 'String')) { - validTypes = isType(options.filter, 'String') ? [options.filter] : options.filter; - refFilter = function (refDetails) { - // Check the exact type or for invalid URIs, check its original type - return validTypes.indexOf(refDetails.type) > -1 || validTypes.indexOf(getRefType(refDetails)) > -1; - }; - } else if (isType(options.filter, 'Function')) { - refFilter = options.filter; - } else if (isType(options.filter, 'Undefined')) { - refFilter = function () { - return true; - }; - } - - return function (refDetails, path) { - return (refDetails.type !== 'invalid' || options.includeInvalid === true) && refFilter(refDetails, path); - }; -} - -function makeSubDocPath (options) { - var subDocPath; - - if (isType(options.subDocPath, 'Array')) { - subDocPath = options.subDocPath; - } else if (isType(options.subDocPath, 'String')) { - subDocPath = pathFromPtr(options.subDocPath); - } else if (isType(options.subDocPath, 'Undefined')) { - subDocPath = []; - } - - return subDocPath; -} - -function parseURI (uri) { - // We decode first to avoid doubly encoding - return URI.parse(encodeURI(decodeURI(uri))); -} - -function setValue (obj, refPath, value) { - findValue(obj, refPath.slice(0, refPath.length - 1))[decodeURI(refPath[refPath.length - 1])] = value; -} - -function walk (ancestors, node, path, fn) { - var processChildren = true; - - function walkItem (item, segment) { - path.push(segment); - walk(ancestors, item, path, fn); - path.pop(); - } - - // Call the iteratee - if (isType(fn, 'Function')) { - processChildren = fn(ancestors, node, path); - } - - // We do not process circular objects again - if (ancestors.indexOf(node) === -1) { - ancestors.push(node); - - if (processChildren !== false) { - if (isType(node, 'Array')) { - node.forEach(function (member, index) { - walkItem(member, index.toString()); - }); - } else if (isType(node, 'Object')) { - Object.keys(node).forEach(function (key) { - walkItem(node[key], key); - }); - } - } - } - - ancestors.pop(); -} - -function validateOptions (options, obj) { - if (isType(options, 'Undefined')) { - // Default to an empty options object - options = {}; - } else { - // Clone the options so we do not alter the ones passed in - options = clone(options); - } - - if (!isType(options, 'Object')) { - throw new TypeError('options must be an Object'); - } else if (!isType(options.filter, 'Undefined') && - !isType(options.filter, 'Array') && - !isType(options.filter, 'Function') && - !isType(options.filter, 'String')) { - throw new TypeError('options.filter must be an Array, a Function of a String'); - } else if (!isType(options.includeInvalid, 'Undefined') && - !isType(options.includeInvalid, 'Boolean')) { - throw new TypeError('options.includeInvalid must be a Boolean'); - } else if (!isType(options.refPreProcessor, 'Undefined') && - !isType(options.refPreProcessor, 'Function')) { - throw new TypeError('options.refPreProcessor must be a Function'); - } else if (!isType(options.refPostProcessor, 'Undefined') && - !isType(options.refPostProcessor, 'Function')) { - throw new TypeError('options.refPostProcessor must be a Function'); - } else if (!isType(options.subDocPath, 'Undefined') && - !isType(options.subDocPath, 'Array') && - !isPtr(options.subDocPath)) { - // If a pointer is provided, throw an error if it's not the proper type - throw new TypeError('options.subDocPath must be an Array of path segments or a valid JSON Pointer'); - } - - options.filter = makeRefFilter(options); - - // Set the subDocPath to avoid everyone else having to compute it - options.subDocPath = makeSubDocPath(options); - - if (!isType(obj, 'Undefined')) { - try { - findValue(obj, options.subDocPath); - } catch (err) { - err.message = err.message.replace('JSON Pointer', 'options.subDocPath'); - - throw err; - } - } - - return options; -} - -/* Module Members */ - -/* - * Each of the functions below are defined as function statements and *then* exported in two steps instead of one due - * to a bug in jsdoc (https://github.com/jsdoc2md/jsdoc-parse/issues/18) that causes our documentation to be - * generated improperly. The impact to the user is significant enough for us to warrant working around it until this - * is fixed. - */ - -/** - * The options used for various JsonRefs APIs. - * - * @typedef {object} JsonRefsOptions - * - * @param {string|string[]|function} [filter=function () {return true;}] - The filter to use when gathering JSON - * References *(If this value is a single string or an array of strings, the value(s) are expected to be the `type(s)` - * you are interested in collecting as described in {@link module:JsonRefs.getRefDetails}. If it is a function, it is - * expected that the function behaves like {@link module:JsonRefs~RefDetailsFilter}.)* - * @param {boolean} [includeInvalid=false] - Whether or not to include invalid JSON Reference details *(This will make - * it so that objects that are like JSON Reference objects, as in they are an `Object` and the have a `$ref` property, - * but fail validation will be included. This is very useful for when you want to know if you have invalid JSON - * Reference definitions. This will not mean that APIs will process invalid JSON References but the reasons as to why - * the JSON References are invalid will be included in the returned metadata.)* - * @param {object} [loaderOptions] - The options to pass to - * {@link https://github.com/whitlockjc/path-loader/blob/master/docs/API.md#module_PathLoader.load|PathLoader~load} - * @param {module:JsonRefs~RefPreProcessor} [refPreProcessor] - The callback used to pre-process a JSON Reference like - * object *(This is called prior to validating the JSON Reference like object and getting its details)* - * @param {module:JsonRefs~RefPostProcessor} [refPostProcessor] - The callback used to post-process the JSON Reference - * metadata *(This is called prior filtering the references)* - * @param {string} [options.relativeBase] - The base location to use when resolving relative references *(Only useful - * for APIs that do remote reference resolution. If this value is not defined, - * {@link https://github.com/whitlockjc/path-loader|path-loader} will use `window.location.href` for the browser and - * `process.cwd()` for Node.js.)* - * @param {string|string[]} [options.subDocPath=[]] - The JSON Pointer or array of path segments to the sub document - * location to search from - */ - -/** - * Simple function used to filter out JSON References. - * - * @typedef {function} RefDetailsFilter - * - * @param {module:JsonRefs~UnresolvedRefDetails} refDetails - The JSON Reference details to test - * @param {string[]} path - The path to the JSON Reference - * - * @returns {boolean} whether the JSON Reference should be filtered *(out)* or not - */ - -/** - * Simple function used to pre-process a JSON Reference like object. - * - * @typedef {function} RefPreProcessor - * - * @param {object} obj - The JSON Reference like object - * @param {string[]} path - The path to the JSON Reference like object - * - * @returns {object} the processed JSON Reference like object - */ - -/** - * Simple function used to post-process a JSON Reference details. - * - * @typedef {function} RefPostProcessor - * - * @param {module:JsonRefs~UnresolvedRefDetails} refDetails - The JSON Reference details to test - * @param {string[]} path - The path to the JSON Reference - * - * @returns {object} the processed JSON Reference details object - */ - -/** - * Detailed information about resolved JSON References. - * - * @typedef {module:JsonRefs~UnresolvedRefDetails} ResolvedRefDetails - * - * @property {boolean} [circular] - Whether or not the JSON Reference is circular *(Will not be set if the JSON - * Reference is not circular)* - * @property {boolean} [missing] - Whether or not the referenced value was missing or not *(Will not be set if the - * referenced value is not missing)* - * @property {*} [value] - The referenced value *(Will not be set if the referenced value is missing)* - */ - -/** - * The results of resolving the JSON References of an array/object. - * - * @typedef {object} ResolvedRefsResults - * - * @property {module:JsonRefs~ResolvedRefDetails} refs - An object whose keys are JSON Pointers *(fragment version)* - * to where the JSON Reference is defined and whose values are {@link module:JsonRefs~ResolvedRefDetails} - * @property {object} resolved - The array/object with its JSON References fully resolved - */ - -/** - * An object containing the retrieved document and detailed information about its JSON References. - * - * @typedef {module:JsonRefs~ResolvedRefsResults} RetrievedRefsResults - * - * @property {object} value - The retrieved document - */ - -/** - * An object containing the retrieved document, the document with its references resolved and detailed information - * about its JSON References. - * - * @typedef {object} RetrievedResolvedRefsResults - * - * @property {module:JsonRefs~UnresolvedRefDetails} refs - An object whose keys are JSON Pointers *(fragment version)* - * to where the JSON Reference is defined and whose values are {@link module:JsonRefs~UnresolvedRefDetails} - * @property {ResolvedRefsResults} - An object whose keys are JSON Pointers *(fragment version)* - * to where the JSON Reference is defined and whose values are {@link module:JsonRefs~ResolvedRefDetails} - * @property {object} value - The retrieved document - */ - -/** - * Detailed information about unresolved JSON References. - * - * @typedef {object} UnresolvedRefDetails - * - * @property {object} def - The JSON Reference definition - * @property {string} [error] - The error information for invalid JSON Reference definition *(Only present when the - * JSON Reference definition is invalid or there was a problem retrieving a remote reference during resolution)* - * @property {string} uri - The URI portion of the JSON Reference - * @property {object} uriDetails - Detailed information about the URI as provided by - * {@link https://github.com/garycourt/uri-js|URI.parse}. - * @property {string} type - The JSON Reference type *(This value can be one of the following: `invalid`, `local`, - * `relative` or `remote`.)* - * @property {string} [warning] - The warning information *(Only present when the JSON Reference definition produces a - * warning)* - */ - -/** - * Clears the internal cache of remote documents, reference details, etc. - * - * @alias module:JsonRefs.clearCache - */ -function clearCache () { - remoteCache = {}; -} - -/** - * Takes an array of path segments and decodes the JSON Pointer tokens in them. - * - * @param {string[]} path - The array of path segments - * - * @returns {string} the array of path segments with their JSON Pointer tokens decoded - * - * @throws {Error} if the path is not an `Array` - * - * @see {@link https://tools.ietf.org/html/rfc6901#section-3} - * - * @alias module:JsonRefs.decodePath - */ -function decodePath (path) { - if (!isType(path, 'Array')) { - throw new TypeError('path must be an array'); - } - - return path.map(function (seg) { - if (!isType(seg, 'String')) { - seg = JSON.stringify(seg); - } - - return decodeURI(seg.replace(/~1/g, '/').replace(/~0/g, '~')); - }); -} - -/** - * Takes an array of path segments and encodes the special JSON Pointer characters in them. - * - * @param {string[]} path - The array of path segments - * - * @returns {string} the array of path segments with their JSON Pointer tokens encoded - * - * @throws {Error} if the path is not an `Array` - * - * @see {@link https://tools.ietf.org/html/rfc6901#section-3} - * - * @alias module:JsonRefs.encodePath - */ -function encodePath (path) { - if (!isType(path, 'Array')) { - throw new TypeError('path must be an array'); - } - - return path.map(function (seg) { - if (!isType(seg, 'String')) { - seg = JSON.stringify(seg); - } - - return seg.replace(/~/g, '~0').replace(/\//g, '~1'); - }); -} - -/** - * Finds JSON References defined within the provided array/object. - * - * @param {array|object} obj - The structure to find JSON References within - * @param {module:JsonRefs~JsonRefsOptions} [options] - The JsonRefs options - * - * @returns {object} an object whose keys are JSON Pointers *(fragment version)* to where the JSON Reference is defined - * and whose values are {@link module:JsonRefs~UnresolvedRefDetails}. - * - * @throws {Error} when the input arguments fail validation or if `options.subDocPath` points to an invalid location - * - * @alias module:JsonRefs.findRefs - * - * @example - * // Finding all valid references - * var allRefs = JsonRefs.findRefs(obj); - * // Finding all remote references - * var remoteRefs = JsonRefs.findRefs(obj, {filter: ['relative', 'remote']}); - * // Finding all invalid references - * var invalidRefs = JsonRefs.findRefs(obj, {filter: 'invalid', includeInvalid: true}); - */ -function findRefs (obj, options) { - var refs = {}; - - // Validate the provided document - if (!isType(obj, 'Array') && !isType(obj, 'Object')) { - throw new TypeError('obj must be an Array or an Object'); - } - - // Validate options - options = validateOptions(options, obj); - - // Walk the document (or sub document) and find all JSON References - walk(findAncestors(obj, options.subDocPath), - findValue(obj, options.subDocPath), - clone(options.subDocPath), - function (ancestors, node, path) { - var processChildren = true; - var refDetails; - - if (isRefLike(node)) { - // Pre-process the node when necessary - if (!isType(options.refPreProcessor, 'Undefined')) { - node = options.refPreProcessor(clone(node), path); - } - - refDetails = getRefDetails(node); - - // Post-process the reference details - if (!isType(options.refPostProcessor, 'Undefined')) { - refDetails = options.refPostProcessor(refDetails, path); - } - - if (options.filter(refDetails, path)) { - refs[pathToPtr(path)] = refDetails; - } - - // Whenever a JSON Reference has extra children, its children should not be processed. - // See: http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03#section-3 - if (getExtraRefKeys(node).length > 0) { - processChildren = false; - } - } - - return processChildren; - }); - - return refs; -} - -/** - * Finds JSON References defined within the document at the provided location. - * - * This API is identical to {@link module:JsonRefs.findRefs} except this API will retrieve a remote document and then - * return the result of {@link module:JsonRefs.findRefs} on the retrieved document. - * - * @param {string} location - The location to retrieve *(Can be relative or absolute, just make sure you look at the - * {@link module:JsonRefs~JsonRefsOptions|options documentation} to see how relative references are handled.)* - * @param {module:JsonRefs~JsonRefsOptions} [options] - The JsonRefs options - * - * @returns {Promise} a promise that resolves a {@link module:JsonRefs~RetrievedRefsResults} and rejects with an - * `Error` when the input arguments fail validation, when `options.subDocPath` points to an invalid location or when - * the location argument points to an unloadable resource - * - * @alias module:JsonRefs.findRefsAt - * - * @example - * // Example that only resolves references within a sub document - * JsonRefs.findRefsAt('http://petstore.swagger.io/v2/swagger.json', { - * subDocPath: '#/definitions' - * }) - * .then(function (res) { - * // Do something with the response - * // - * // res.refs: JSON Reference locations and details - * // res.value: The retrieved document - * }, function (err) { - * console.log(err.stack); - * }); - */ -function findRefsAt (location, options) { - var allTasks = Promise.resolve(); - - allTasks = allTasks - .then(function () { - // Validate the provided location - if (!isType(location, 'String')) { - throw new TypeError('location must be a string'); - } - - // Validate options - options = validateOptions(options); - - // Combine the location and the optional relative base - location = combineURIs(options.relativeBase, location); - - return getRemoteDocument(location, options); - }) - .then(function (res) { - var cacheEntry = clone(remoteCache[location]); - var cOptions = clone(options); - var uriDetails = parseURI(location); - - if (isType(cacheEntry.refs, 'Undefined')) { - // Do not filter any references so the cache is complete - delete cOptions.filter; - delete cOptions.subDocPath; - - cOptions.includeInvalid = true; - - remoteCache[location].refs = findRefs(res, cOptions); - } - - // Add the filter options back - if (!isType(options.filter, 'Undefined')) { - cOptions.filter = options.filter; - } - - if (!isType(uriDetails.fragment, 'Undefined')) { - cOptions.subDocPath = pathFromPtr(decodeURI(uriDetails.fragment)); - } else if (!isType(uriDetails.subDocPath, 'Undefined')) { - cOptions.subDocPath = options.subDocPath; - } - - // This will use the cache so don't worry about calling it twice - return { - refs: findRefs(res, cOptions), - value: res - }; - }); - - return allTasks; -} - -/** - * Returns detailed information about the JSON Reference. - * - * @param {object} obj - The JSON Reference definition - * - * @returns {module:JsonRefs~UnresolvedRefDetails} the detailed information - * - * @alias module:JsonRefs.getRefDetails - */ -function getRefDetails (obj) { - var details = { - def: obj - }; - var cacheKey; - var extraKeys; - var uriDetails; - - try { - if (isRefLike(obj, true)) { - cacheKey = obj.$ref; - uriDetails = uriDetailsCache[cacheKey]; - - if (isType(uriDetails, 'Undefined')) { - uriDetails = uriDetailsCache[cacheKey] = parseURI(cacheKey); - } - - details.uri = cacheKey; - details.uriDetails = uriDetails; - - if (isType(uriDetails.error, 'Undefined')) { - details.type = getRefType(details); - } else { - details.error = details.uriDetails.error; - details.type = 'invalid'; - } - - // Identify warning - extraKeys = getExtraRefKeys(obj); - - if (extraKeys.length > 0) { - details.warning = 'Extra JSON Reference properties will be ignored: ' + extraKeys.join(', '); - } - } else { - details.type = 'invalid'; - } - } catch (err) { - details.error = err.message; - details.type = 'invalid'; - } - - return details; -} - -/** - * Returns whether the argument represents a JSON Pointer. - * - * A string is a JSON Pointer if the following are all true: - * - * * The string is of type `String` - * * The string must be empty, `#` or start with a `/` or `#/` - * - * @param {string} ptr - The string to check - * @param {boolean} [throwWithDetails=false] - Whether or not to throw an `Error` with the details as to why the value - * provided is invalid - * - * @returns {boolean} the result of the check - * - * @throws {error} when the provided value is invalid and the `throwWithDetails` argument is `true` - * - * @alias module:JsonRefs.isPtr - * - * @see {@link https://tools.ietf.org/html/rfc6901#section-3} - * - * @example - * // Separating the different ways to invoke isPtr for demonstration purposes - * if (isPtr(str)) { - * // Handle a valid JSON Pointer - * } else { - * // Get the reason as to why the value is not a JSON Pointer so you can fix/report it - * try { - * isPtr(str, true); - * } catch (err) { - * // The error message contains the details as to why the provided value is not a JSON Pointer - * } - * } - */ -function isPtr (ptr, throwWithDetails) { - var valid = true; - var firstChar; - - try { - if (isType(ptr, 'String')) { - if (ptr !== '') { - firstChar = ptr.charAt(0); - - if (['#', '/'].indexOf(firstChar) === -1) { - throw new Error('ptr must start with a / or #/'); - } else if (firstChar === '#' && ptr !== '#' && ptr.charAt(1) !== '/') { - throw new Error('ptr must start with a / or #/'); - } else if (ptr.match(badPtrTokenRegex)) { - throw new Error('ptr has invalid token(s)'); - } - } - } else { - throw new Error('ptr is not a String'); - } - } catch (err) { - if (throwWithDetails === true) { - throw err; - } - - valid = false; - } - - return valid; -} - -/** - * Returns whether the argument represents a JSON Reference. - * - * An object is a JSON Reference only if the following are all true: - * - * * The object is of type `Object` - * * The object has a `$ref` property - * * The `$ref` property is a valid URI *(We do not require 100% strict URIs and will handle unescaped special - * characters.)* - * - * @param {object} obj - The object to check - * @param {boolean} [throwWithDetails=false] - Whether or not to throw an `Error` with the details as to why the value - * provided is invalid - * - * @returns {boolean} the result of the check - * - * @throws {error} when the provided value is invalid and the `throwWithDetails` argument is `true` - * - * @alias module:JsonRefs.isRef - * - * @see {@link http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03#section-3} - * - * @example - * // Separating the different ways to invoke isRef for demonstration purposes - * if (isRef(obj)) { - * // Handle a valid JSON Reference - * } else { - * // Get the reason as to why the value is not a JSON Reference so you can fix/report it - * try { - * isRef(str, true); - * } catch (err) { - * // The error message contains the details as to why the provided value is not a JSON Reference - * } - * } - */ -function isRef (obj, throwWithDetails) { - return isRefLike(obj, throwWithDetails) && getRefDetails(obj, throwWithDetails).type !== 'invalid'; -} - -/** - * Returns an array of path segments for the provided JSON Pointer. - * - * @param {string} ptr - The JSON Pointer - * - * @returns {string[]} the path segments - * - * @throws {Error} if the provided `ptr` argument is not a JSON Pointer - * - * @alias module:JsonRefs.pathFromPtr - */ -function pathFromPtr (ptr) { - if (!isPtr(ptr)) { - throw new Error('ptr must be a JSON Pointer'); - } - - var segments = ptr.split('/'); - - // Remove the first segment - segments.shift(); - - return decodePath(segments); -} - -/** - * Returns a JSON Pointer for the provided array of path segments. - * - * **Note:** If a path segment in `path` is not a `String`, it will be converted to one using `JSON.stringify`. - * - * @param {string[]} path - The array of path segments - * @param {boolean} [hashPrefix=true] - Whether or not create a hash-prefixed JSON Pointer - * - * @returns {string} the corresponding JSON Pointer - * - * @throws {Error} if the `path` argument is not an array - * - * @alias module:JsonRefs.pathToPtr - */ -function pathToPtr (path, hashPrefix) { - if (!isType(path, 'Array')) { - throw new Error('path must be an Array'); - } - - // Encode each segment and return - return (hashPrefix !== false ? '#' : '') + (path.length > 0 ? '/' : '') + encodePath(path).join('/'); -} - -/** - * Finds JSON References defined within the provided array/object and resolves them. - * - * @param {array|object} obj - The structure to find JSON References within - * @param {module:JsonRefs~JsonRefsOptions} [options] - The JsonRefs options - * - * @returns {Promise} a promise that resolves a {@link module:JsonRefs~ResolvedRefsResults} and rejects with an - * `Error` when the input arguments fail validation, when `options.subDocPath` points to an invalid location or when - * the location argument points to an unloadable resource - * - * @alias module:JsonRefs.resolveRefs - * - * @example - * // Example that only resolves relative and remote references - * JsonRefs.resolveRefs(swaggerObj, { - * filter: ['relative', 'remote'] - * }) - * .then(function (res) { - * // Do something with the response - * // - * // res.refs: JSON Reference locations and details - * // res.resolved: The document with the appropriate JSON References resolved - * }, function (err) { - * console.log(err.stack); - * }); - */ -function resolveRefs (obj, options) { - var allTasks = Promise.resolve(); - - allTasks = allTasks - .then(function () { - // Validate the provided document - if (!isType(obj, 'Array') && !isType(obj, 'Object')) { - throw new TypeError('obj must be an Array or an Object'); - } - - // Validate options - options = validateOptions(options, obj); - - // Clone the input so we do not alter it - obj = clone(obj); - }) - .then(function () { - return findRefsRecursive(obj, options, [], [], { - documents: {}, - refs: {} - }); - }) - .then(function (allRefs) { - var deferredRefs = {}; - var refs = {}; - - function pathSorter (p1, p2) { - return pathFromPtr(p1).length - pathFromPtr(p2).length; - } - - // Resolve all references with a known value - Object.keys(allRefs.refs).sort(pathSorter).forEach(function (refPtr) { - var refDetails = allRefs.refs[refPtr]; - - // Record all direct references - if (!refDetails.indirect) { - refs[refPtr] = refDetails; - } - - // Delete helper property - delete refDetails.indirect; - - if (isType(refDetails.error, 'Undefined') && refDetails.type !== 'invalid') { - if (isType(refDetails.value, 'Undefined') && refDetails.circular) { - refDetails.value = refDetails.def; - } - - // We defer processing all references without a value until later - if (isType(refDetails.value, 'Undefined')) { - deferredRefs[refPtr] = refDetails; - } else { - if (refPtr === '#') { - obj = refDetails.value; - } else { - setValue(obj, pathFromPtr(refPtr), refDetails.value); - } - - // Delete helper property - delete refDetails.ancestorPtrs; - } - } else { - // Delete helper property - delete refDetails.ancestorPtrs; - } - }); - - // Resolve all deferred references - Object.keys(deferredRefs).forEach(function (refPtr) { - var refDetails = deferredRefs[refPtr]; - - // Attempt to resolve the value against all if its ancestors in order - refDetails.ancestorPtrs.forEach(function (ancestorPtr, index) { - if (isType(refDetails.value, 'Undefined')) { - try { - refDetails.value = findValue(allRefs.documents[ancestorPtr], pathFromPtr(refDetails.uri)); - - // Delete helper property - delete refDetails.ancestorPtrs; - - setValue(obj, pathFromPtr(refPtr), refDetails.value); - } catch (err) { - if (index === refDetails.ancestorPtrs.length - 1) { - refDetails.error = err.message; - refDetails.missing = true; - - // Delete helper property - delete refDetails.ancestorPtrs; - } - } - } - }); - }); - - return { - refs: refs, - resolved: obj - }; - }); - - return allTasks; -} - -/** - * Resolves JSON References defined within the document at the provided location. - * - * This API is identical to {@link module:JsonRefs.resolveRefs} except this API will retrieve a remote document and then - * return the result of {@link module:JsonRefs.resolveRefs} on the retrieved document. - * - * @param {string} location - The location to retrieve *(Can be relative or absolute, just make sure you look at the - * {@link module:JsonRefs~JsonRefsOptions|options documentation} to see how relative references are handled.)* - * @param {module:JsonRefs~JsonRefsOptions} [options] - The JsonRefs options - * - * @returns {Promise} a promise that resolves a {@link module:JsonRefs~RetrievedResolvedRefsResults} and rejects with an - * `Error` when the input arguments fail validation, when `options.subDocPath` points to an invalid location or when - * the location argument points to an unloadable resource - * - * @alias module:JsonRefs.resolveRefsAt - * - * @example - * // Example that loads a JSON document (No options.loaderOptions.processContent required) and resolves all references - * JsonRefs.resolveRefsAt('./swagger.json') - * .then(function (res) { - * // Do something with the response - * // - * // res.refs: JSON Reference locations and details - * // res.resolved: The document with the appropriate JSON References resolved - * // res.value: The retrieved document - * }, function (err) { - * console.log(err.stack); - * }); - */ -function resolveRefsAt (location, options) { - var allTasks = Promise.resolve(); - - allTasks = allTasks - .then(function () { - // Validate the provided location - if (!isType(location, 'String')) { - throw new TypeError('location must be a string'); - } - - // Validate options - options = validateOptions(options); - - // Combine the location and the optional relative base - location = combineURIs(options.relativeBase, location); - - return getRemoteDocument(location, options); - }) - .then(function (res) { - var cOptions = clone(options); - var uriDetails = parseURI(location); - - // Set the sub document path if necessary - if (!isType(uriDetails.fragment, 'Undefined')) { - cOptions.subDocPath = pathFromPtr(decodeURI(uriDetails.fragment)); - } - - // Update the relative base based on the retrieved location - cOptions.relativeBase = path.dirname(location); - - return resolveRefs(res, cOptions) - .then(function (res2) { - return { - refs: res2.refs, - resolved: res2.resolved, - value: res - }; - }); - }); - - return allTasks; -} - -/* Export the module members */ -module.exports.clearCache = clearCache; -module.exports.decodePath = decodePath; -module.exports.encodePath = encodePath; -module.exports.findRefs = findRefs; -module.exports.findRefsAt = findRefsAt; -module.exports.getRefDetails = getRefDetails; -module.exports.isPtr = isPtr; -module.exports.isRef = isRef; -module.exports.pathFromPtr = pathFromPtr; -module.exports.pathToPtr = pathToPtr; -module.exports.resolveRefs = resolveRefs; -module.exports.resolveRefsAt = resolveRefsAt; - -},{"native-promise-only":3,"path":4,"path-loader":5,"querystring":11,"slash":13,"uri-js":23}],2:[function(require,module,exports){ - -/** - * Expose `Emitter`. - */ - -module.exports = Emitter; - -/** - * Initialize a new `Emitter`. - * - * @api public - */ - -function Emitter(obj) { - if (obj) return mixin(obj); -}; - -/** - * Mixin the emitter properties. - * - * @param {Object} obj - * @return {Object} - * @api private - */ - -function mixin(obj) { - for (var key in Emitter.prototype) { - obj[key] = Emitter.prototype[key]; - } - return obj; -} - -/** - * Listen on the given `event` with `fn`. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ - -Emitter.prototype.on = -Emitter.prototype.addEventListener = function(event, fn){ - this._callbacks = this._callbacks || {}; - (this._callbacks['$' + event] = this._callbacks['$' + event] || []) - .push(fn); - return this; -}; - -/** - * Adds an `event` listener that will be invoked a single - * time then automatically removed. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ - -Emitter.prototype.once = function(event, fn){ - function on() { - this.off(event, on); - fn.apply(this, arguments); - } - - on.fn = fn; - this.on(event, on); - return this; -}; - -/** - * Remove the given callback for `event` or all - * registered callbacks. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ - -Emitter.prototype.off = -Emitter.prototype.removeListener = -Emitter.prototype.removeAllListeners = -Emitter.prototype.removeEventListener = function(event, fn){ - this._callbacks = this._callbacks || {}; - - // all - if (0 == arguments.length) { - this._callbacks = {}; - return this; - } - - // specific event - var callbacks = this._callbacks['$' + event]; - if (!callbacks) return this; - - // remove all handlers - if (1 == arguments.length) { - delete this._callbacks['$' + event]; - return this; - } - - // remove specific handler - var cb; - for (var i = 0; i < callbacks.length; i++) { - cb = callbacks[i]; - if (cb === fn || cb.fn === fn) { - callbacks.splice(i, 1); - break; - } - } - return this; -}; - -/** - * Emit `event` with the given args. - * - * @param {String} event - * @param {Mixed} ... - * @return {Emitter} - */ - -Emitter.prototype.emit = function(event){ - this._callbacks = this._callbacks || {}; - var args = [].slice.call(arguments, 1) - , callbacks = this._callbacks['$' + event]; - - if (callbacks) { - callbacks = callbacks.slice(0); - for (var i = 0, len = callbacks.length; i < len; ++i) { - callbacks[i].apply(this, args); - } - } - - return this; -}; - -/** - * Return array of callbacks for `event`. - * - * @param {String} event - * @return {Array} - * @api public - */ - -Emitter.prototype.listeners = function(event){ - this._callbacks = this._callbacks || {}; - return this._callbacks['$' + event] || []; -}; - -/** - * Check if this emitter has `event` handlers. - * - * @param {String} event - * @return {Boolean} - * @api public - */ - -Emitter.prototype.hasListeners = function(event){ - return !! this.listeners(event).length; -}; - -},{}],3:[function(require,module,exports){ -(function (global){ -/*! Native Promise Only - v0.8.1 (c) Kyle Simpson - MIT License: http://getify.mit-license.org -*/ - -(function UMD(name,context,definition){ - // special form of UMD for polyfilling across evironments - context[name] = context[name] || definition(); - if (typeof module != "undefined" && module.exports) { module.exports = context[name]; } - else if (typeof define == "function" && define.amd) { define(function $AMD$(){ return context[name]; }); } -})("Promise",typeof global != "undefined" ? global : this,function DEF(){ - /*jshint validthis:true */ - "use strict"; - - var builtInProp, cycle, scheduling_queue, - ToString = Object.prototype.toString, - timer = (typeof setImmediate != "undefined") ? - function timer(fn) { return setImmediate(fn); } : - setTimeout - ; - - // dammit, IE8. - try { - Object.defineProperty({},"x",{}); - builtInProp = function builtInProp(obj,name,val,config) { - return Object.defineProperty(obj,name,{ - value: val, - writable: true, - configurable: config !== false - }); - }; - } - catch (err) { - builtInProp = function builtInProp(obj,name,val) { - obj[name] = val; - return obj; - }; - } - - // Note: using a queue instead of array for efficiency - scheduling_queue = (function Queue() { - var first, last, item; - - function Item(fn,self) { - this.fn = fn; - this.self = self; - this.next = void 0; - } - - return { - add: function add(fn,self) { - item = new Item(fn,self); - if (last) { - last.next = item; - } - else { - first = item; - } - last = item; - item = void 0; - }, - drain: function drain() { - var f = first; - first = last = cycle = void 0; - - while (f) { - f.fn.call(f.self); - f = f.next; - } - } - }; - })(); - - function schedule(fn,self) { - scheduling_queue.add(fn,self); - if (!cycle) { - cycle = timer(scheduling_queue.drain); - } - } - - // promise duck typing - function isThenable(o) { - var _then, o_type = typeof o; - - if (o != null && - ( - o_type == "object" || o_type == "function" - ) - ) { - _then = o.then; - } - return typeof _then == "function" ? _then : false; - } - - function notify() { - for (var i=0; i 0) { - schedule(notify,self); - } - } - } - catch (err) { - reject.call(new MakeDefWrapper(self),err); - } - } - - function reject(msg) { - var self = this; - - // already triggered? - if (self.triggered) { return; } - - self.triggered = true; - - // unwrap - if (self.def) { - self = self.def; - } - - self.msg = msg; - self.state = 2; - if (self.chain.length > 0) { - schedule(notify,self); - } - } - - function iteratePromises(Constructor,arr,resolver,rejecter) { - for (var idx=0; idx 0 - var up = 0; - for (var i = parts.length - 1; i >= 0; i--) { - var last = parts[i]; - if (last === '.') { - parts.splice(i, 1); - } else if (last === '..') { - parts.splice(i, 1); - up++; - } else if (up) { - parts.splice(i, 1); - up--; - } - } - - // if the path is allowed to go above the root, restore leading ..s - if (allowAboveRoot) { - for (; up--; up) { - parts.unshift('..'); - } - } - - return parts; -} - -// Split a filename into [root, dir, basename, ext], unix version -// 'root' is just a slash, or nothing. -var splitPathRe = - /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; -var splitPath = function(filename) { - return splitPathRe.exec(filename).slice(1); -}; - -// path.resolve([from ...], to) -// posix version -exports.resolve = function() { - var resolvedPath = '', - resolvedAbsolute = false; - - for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { - var path = (i >= 0) ? arguments[i] : process.cwd(); - - // Skip empty and invalid entries - if (typeof path !== 'string') { - throw new TypeError('Arguments to path.resolve must be strings'); - } else if (!path) { - continue; - } - - resolvedPath = path + '/' + resolvedPath; - resolvedAbsolute = path.charAt(0) === '/'; - } - - // At this point the path should be resolved to a full absolute path, but - // handle relative paths to be safe (might happen when process.cwd() fails) - - // Normalize the path - resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { - return !!p; - }), !resolvedAbsolute).join('/'); - - return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; -}; - -// path.normalize(path) -// posix version -exports.normalize = function(path) { - var isAbsolute = exports.isAbsolute(path), - trailingSlash = substr(path, -1) === '/'; - - // Normalize the path - path = normalizeArray(filter(path.split('/'), function(p) { - return !!p; - }), !isAbsolute).join('/'); - - if (!path && !isAbsolute) { - path = '.'; - } - if (path && trailingSlash) { - path += '/'; - } - - return (isAbsolute ? '/' : '') + path; -}; - -// posix version -exports.isAbsolute = function(path) { - return path.charAt(0) === '/'; -}; - -// posix version -exports.join = function() { - var paths = Array.prototype.slice.call(arguments, 0); - return exports.normalize(filter(paths, function(p, index) { - if (typeof p !== 'string') { - throw new TypeError('Arguments to path.join must be strings'); - } - return p; - }).join('/')); -}; - - -// path.relative(from, to) -// posix version -exports.relative = function(from, to) { - from = exports.resolve(from).substr(1); - to = exports.resolve(to).substr(1); - - function trim(arr) { - var start = 0; - for (; start < arr.length; start++) { - if (arr[start] !== '') break; - } - - var end = arr.length - 1; - for (; end >= 0; end--) { - if (arr[end] !== '') break; - } - - if (start > end) return []; - return arr.slice(start, end - start + 1); - } - - var fromParts = trim(from.split('/')); - var toParts = trim(to.split('/')); - - var length = Math.min(fromParts.length, toParts.length); - var samePartsLength = length; - for (var i = 0; i < length; i++) { - if (fromParts[i] !== toParts[i]) { - samePartsLength = i; - break; - } - } - - var outputParts = []; - for (var i = samePartsLength; i < fromParts.length; i++) { - outputParts.push('..'); - } - - outputParts = outputParts.concat(toParts.slice(samePartsLength)); - - return outputParts.join('/'); -}; - -exports.sep = '/'; -exports.delimiter = ':'; - -exports.dirname = function(path) { - var result = splitPath(path), - root = result[0], - dir = result[1]; - - if (!root && !dir) { - // No dirname whatsoever - return '.'; - } - - if (dir) { - // It has a dirname, strip trailing slash - dir = dir.substr(0, dir.length - 1); - } - - return root + dir; -}; - - -exports.basename = function(path, ext) { - var f = splitPath(path)[2]; - // TODO: make this comparison case-insensitive on windows? - if (ext && f.substr(-1 * ext.length) === ext) { - f = f.substr(0, f.length - ext.length); - } - return f; -}; - - -exports.extname = function(path) { - return splitPath(path)[3]; -}; - -function filter (xs, f) { - if (xs.filter) return xs.filter(f); - var res = []; - for (var i = 0; i < xs.length; i++) { - if (f(xs[i], i, xs)) res.push(xs[i]); - } - return res; -} - -// String.prototype.substr - negative index don't work in IE8 -var substr = 'ab'.substr(-1) === 'b' - ? function (str, start, len) { return str.substr(start, len) } - : function (str, start, len) { - if (start < 0) start = str.length + start; - return str.substr(start, len); - } -; - -}).call(this,require('_process')) - -},{"_process":8}],5:[function(require,module,exports){ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 Jeremy Whitlock - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -'use strict'; - -/** - * Utility that provides a single API for loading the content of a path/URL. - * - * @module PathLoader - */ - -var supportedLoaders = { - file: require('./lib/loaders/file'), - http: require('./lib/loaders/http'), - https: require('./lib/loaders/http') -}; -var defaultLoader = typeof window === 'object' || typeof importScripts === 'function' ? - supportedLoaders.http : - supportedLoaders.file; - -// Load promises polyfill if necessary -/* istanbul ignore if */ -if (typeof Promise === 'undefined') { - require('native-promise-only'); -} - -function getScheme (location) { - if (typeof location !== 'undefined') { - location = location.indexOf('://') === -1 ? '' : location.split('://')[0]; - } - - return location; -} - -/** - * Callback used to provide access to altering a remote request prior to the request being made. - * - * @typedef {function} PrepareRequestCallback - * - * @param {object} req - The Superagent request object - * @param {string} location - The location being retrieved - * @param {function} callback - First callback - * - * @alias module:PathLoader~PrepareRequestCallback - */ - - /** - * Callback used to provide access to processing the raw response of the request being made. *(HTTP loader only)* - * - * @typedef {function} ProcessResponseCallback - * - * @param {object} res - The Superagent response object *(For non-HTTP loaders, this object will be like the Superagent - * object in that it will have a `text` property whose value is the raw string value being processed. This was done - * for consistency.)* - * @param {function} callback - Error-first callback - * - * @returns {*} the result of processing the responsexs - * - * @alias module:PathLoader~ProcessResponseCallback - */ - -function getLoader (location) { - var scheme = getScheme(location); - var loader = supportedLoaders[scheme]; - - if (typeof loader === 'undefined') { - if (scheme === '') { - loader = defaultLoader; - } else { - throw new Error('Unsupported scheme: ' + scheme); - } - } - - return loader; -} - -/** - * Loads a document at the provided location and returns a JavaScript object representation. - * - * @param {object} location - The location to the document - * @param {object} [options] - The options - * @param {string} [options.encoding='utf-8'] - The encoding to use when loading the file *(File loader only)* - * @param {string} [options.method=get] - The HTTP method to use for the request *(HTTP loader only)* - * @param {module:PathLoader~PrepareRequestCallback} [options.prepareRequest] - The callback used to prepare the request - * *(HTTP loader only)* - * @param {module:PathLoader~ProcessResponseCallback} [options.processContent] - The callback used to process the - * response - * - * @returns {Promise} Always returns a promise even if there is a callback provided - * - * @example - * // Example using Promises - * - * PathLoader - * .load('./package.json') - * .then(JSON.parse) - * .then(function (document) { - * console.log(document.name + ' (' + document.version + '): ' + document.description); - * }, function (err) { - * console.error(err.stack); - * }); - * - * @example - * // Example using options.prepareRequest to provide authentication details for a remotely secure URL - * - * PathLoader - * .load('https://api.github.com/repos/whitlockjc/path-loader', { - * prepareRequest: function (req, callback) { - * req.auth('my-username', 'my-password'); - * callback(undefined, req); - * } - * }) - * .then(JSON.parse) - * .then(function (document) { - * console.log(document.full_name + ': ' + document.description); - * }, function (err) { - * console.error(err.stack); - * }); - * - * @example - * // Example loading a YAML file - * - * PathLoader - * .load('/Users/not-you/projects/path-loader/.travis.yml') - * .then(YAML.safeLoad) - * .then(function (document) { - * console.log('path-loader uses the', document.language, 'language.'); - * }, function (err) { - * console.error(err.stack); - * }); - * - * @example - * // Example loading a YAML file with options.processContent (Useful if you need information in the raw response) - * - * PathLoader - * .load('/Users/not-you/projects/path-loader/.travis.yml', { - * processContent: function (res, callback) { - * callback(YAML.safeLoad(res.text)); - * } - * }) - * .then(function (document) { - * console.log('path-loader uses the', document.language, 'language.'); - * }, function (err) { - * console.error(err.stack); - * }); - */ -module.exports.load = function (location, options) { - var allTasks = Promise.resolve(); - - // Default options to empty object - if (typeof options === 'undefined') { - options = {}; - } - - // Validate arguments - allTasks = allTasks.then(function () { - if (typeof location === 'undefined') { - throw new TypeError('location is required'); - } else if (typeof location !== 'string') { - throw new TypeError('location must be a string'); - } - - if (typeof options !== 'undefined') { - if (typeof options !== 'object') { - throw new TypeError('options must be an object'); - } else if (typeof options.processContent !== 'undefined' && typeof options.processContent !== 'function') { - throw new TypeError('options.processContent must be a function'); - } - } - }); - - // Load the document from the provided location and process it - allTasks = allTasks - .then(function () { - return new Promise(function (resolve, reject) { - var loader = getLoader(location); - - loader.load(location, options || {}, function (err, document) { - if (err) { - reject(err); - } else { - resolve(document); - } - }); - }); - }) - .then(function (res) { - if (options.processContent) { - return new Promise(function (resolve, reject) { - // For consistency between file and http, always send an object with a 'text' property containing the raw - // string value being processed. - options.processContent(typeof res === 'object' ? res : {text: res}, function (err, processed) { - if (err) { - reject(err); - } else { - resolve(processed); - } - }); - }); - } else { - // If there was no content processor, we will assume that for all objects that it is a Superagent response - // and will return its `text` property value. Otherwise, we will return the raw response. - return typeof res === 'object' ? res.text : res; - } - }); - - return allTasks; -}; - -},{"./lib/loaders/file":6,"./lib/loaders/http":7,"native-promise-only":3}],6:[function(require,module,exports){ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 Jeremy Whitlock - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -'use strict'; - -var unsupportedError = new TypeError('The \'file\' scheme is not supported in the browser'); - -/** - * The file loader is not supported in the browser. - * - * @throws {error} the file loader is not supported in the browser - */ -module.exports.getBase = function () { - throw unsupportedError; -}; - -/** - * The file loader is not supported in the browser. - */ -module.exports.load = function () { - var fn = arguments[arguments.length - 1]; - - if (typeof fn === 'function') { - fn(unsupportedError); - } else { - throw unsupportedError; - } -}; - -},{}],7:[function(require,module,exports){ -/* eslint-env node, browser */ - -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 Jeremy Whitlock - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -'use strict'; - -var request = require('superagent'); - -var supportedHttpMethods = ['delete', 'get', 'head', 'patch', 'post', 'put']; - -/** - * Loads a file from an http or https URL. - * - * @param {string} location - The document URL (If relative, location is relative to window.location.origin). - * @param {object} options - The loader options - * @param {string} [options.method=get] - The HTTP method to use for the request - * @param {module:PathLoader~PrepareRequestCallback} [options.prepareRequest] - The callback used to prepare a request - * @param {module:PathLoader~ProcessResponseCallback} [options.processContent] - The callback used to process the - * response - * @param {function} callback - The error-first callback - */ -module.exports.load = function (location, options, callback) { - var realMethod = options.method ? options.method.toLowerCase() : 'get'; - var err; - var realRequest; - - function makeRequest (err, req) { - if (err) { - callback(err); - } else { - // buffer() is only available in Node.js - if (typeof req.buffer === 'function') { - req.buffer(true); - } - - req - .end(function (err2, res) { - if (err2) { - callback(err2); - } else { - callback(undefined, res); - } - }); - } - } - - if (typeof options.method !== 'undefined') { - if (typeof options.method !== 'string') { - err = new TypeError('options.method must be a string'); - } else if (supportedHttpMethods.indexOf(options.method) === -1) { - err = new TypeError('options.method must be one of the following: ' + - supportedHttpMethods.slice(0, supportedHttpMethods.length - 1).join(', ') + ' or ' + - supportedHttpMethods[supportedHttpMethods.length - 1]); - } - } else if (typeof options.prepareRequest !== 'undefined' && typeof options.prepareRequest !== 'function') { - err = new TypeError('options.prepareRequest must be a function'); - } - - if (!err) { - realRequest = request[realMethod === 'delete' ? 'del' : realMethod](location); - - if (options.prepareRequest) { - try { - options.prepareRequest(realRequest, makeRequest); - } catch (err2) { - callback(err2); - } - } else { - makeRequest(undefined, realRequest); - } - } else { - callback(err); - } -}; - -},{"superagent":14}],8:[function(require,module,exports){ -// shim for using process in browser - -var process = module.exports = {}; -var queue = []; -var draining = false; -var currentQueue; -var queueIndex = -1; - -function cleanUpNextTick() { - draining = false; - if (currentQueue.length) { - queue = currentQueue.concat(queue); - } else { - queueIndex = -1; - } - if (queue.length) { - drainQueue(); - } -} - -function drainQueue() { - if (draining) { - return; - } - var timeout = setTimeout(cleanUpNextTick); - draining = true; - - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - while (++queueIndex < len) { - if (currentQueue) { - currentQueue[queueIndex].run(); - } - } - queueIndex = -1; - len = queue.length; - } - currentQueue = null; - draining = false; - clearTimeout(timeout); -} - -process.nextTick = function (fun) { - var args = new Array(arguments.length - 1); - if (arguments.length > 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - setTimeout(drainQueue, 0); - } -}; - -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; -} -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - -},{}],9:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -'use strict'; - -// If obj.hasOwnProperty has been overridden, then calling -// obj.hasOwnProperty(prop) will break. -// See: https://github.com/joyent/node/issues/1707 -function hasOwnProperty(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); -} - -module.exports = function(qs, sep, eq, options) { - sep = sep || '&'; - eq = eq || '='; - var obj = {}; - - if (typeof qs !== 'string' || qs.length === 0) { - return obj; - } - - var regexp = /\+/g; - qs = qs.split(sep); - - var maxKeys = 1000; - if (options && typeof options.maxKeys === 'number') { - maxKeys = options.maxKeys; - } - - var len = qs.length; - // maxKeys <= 0 means that we should not limit keys count - if (maxKeys > 0 && len > maxKeys) { - len = maxKeys; - } - - for (var i = 0; i < len; ++i) { - var x = qs[i].replace(regexp, '%20'), - idx = x.indexOf(eq), - kstr, vstr, k, v; - - if (idx >= 0) { - kstr = x.substr(0, idx); - vstr = x.substr(idx + 1); - } else { - kstr = x; - vstr = ''; - } - - k = decodeURIComponent(kstr); - v = decodeURIComponent(vstr); - - if (!hasOwnProperty(obj, k)) { - obj[k] = v; - } else if (isArray(obj[k])) { - obj[k].push(v); - } else { - obj[k] = [obj[k], v]; - } - } - - return obj; -}; - -var isArray = Array.isArray || function (xs) { - return Object.prototype.toString.call(xs) === '[object Array]'; -}; - -},{}],10:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -'use strict'; - -var stringifyPrimitive = function(v) { - switch (typeof v) { - case 'string': - return v; - - case 'boolean': - return v ? 'true' : 'false'; - - case 'number': - return isFinite(v) ? v : ''; - - default: - return ''; - } -}; - -module.exports = function(obj, sep, eq, name) { - sep = sep || '&'; - eq = eq || '='; - if (obj === null) { - obj = undefined; - } - - if (typeof obj === 'object') { - return map(objectKeys(obj), function(k) { - var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; - if (isArray(obj[k])) { - return map(obj[k], function(v) { - return ks + encodeURIComponent(stringifyPrimitive(v)); - }).join(sep); - } else { - return ks + encodeURIComponent(stringifyPrimitive(obj[k])); - } - }).join(sep); - - } - - if (!name) return ''; - return encodeURIComponent(stringifyPrimitive(name)) + eq + - encodeURIComponent(stringifyPrimitive(obj)); -}; - -var isArray = Array.isArray || function (xs) { - return Object.prototype.toString.call(xs) === '[object Array]'; -}; - -function map (xs, f) { - if (xs.map) return xs.map(f); - var res = []; - for (var i = 0; i < xs.length; i++) { - res.push(f(xs[i], i)); - } - return res; -} - -var objectKeys = Object.keys || function (obj) { - var res = []; - for (var key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key); - } - return res; -}; - -},{}],11:[function(require,module,exports){ -'use strict'; - -exports.decode = exports.parse = require('./decode'); -exports.encode = exports.stringify = require('./encode'); - -},{"./decode":9,"./encode":10}],12:[function(require,module,exports){ - -/** - * Reduce `arr` with `fn`. - * - * @param {Array} arr - * @param {Function} fn - * @param {Mixed} initial - * - * TODO: combatible error handling? - */ - -module.exports = function(arr, fn, initial){ - var idx = 0; - var len = arr.length; - var curr = arguments.length == 3 - ? initial - : arr[idx++]; - - while (idx < len) { - curr = fn.call(null, curr, arr[idx], ++idx, arr); - } - - return curr; -}; -},{}],13:[function(require,module,exports){ -'use strict'; -module.exports = function (str) { - var isExtendedLengthPath = /^\\\\\?\\/.test(str); - var hasNonAscii = /[^\x00-\x80]+/.test(str); - - if (isExtendedLengthPath || hasNonAscii) { - return str; - } - - return str.replace(/\\/g, '/'); -}; - -},{}],14:[function(require,module,exports){ -/** - * Module dependencies. - */ - -var Emitter = require('emitter'); -var reduce = require('reduce'); -var requestBase = require('./request-base'); -var isObject = require('./is-object'); - -/** - * Root reference for iframes. - */ - -var root; -if (typeof window !== 'undefined') { // Browser window - root = window; -} else if (typeof self !== 'undefined') { // Web Worker - root = self; -} else { // Other environments - root = this; -} - -/** - * Noop. - */ - -function noop(){}; - -/** - * Check if `obj` is a host object, - * we don't want to serialize these :) - * - * TODO: future proof, move to compoent land - * - * @param {Object} obj - * @return {Boolean} - * @api private - */ - -function isHost(obj) { - var str = {}.toString.call(obj); - - switch (str) { - case '[object File]': - case '[object Blob]': - case '[object FormData]': - return true; - default: - return false; - } -} - -/** - * Expose `request`. - */ - -var request = module.exports = require('./request').bind(null, Request); - -/** - * Determine XHR. - */ - -request.getXHR = function () { - if (root.XMLHttpRequest - && (!root.location || 'file:' != root.location.protocol - || !root.ActiveXObject)) { - return new XMLHttpRequest; - } else { - try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {} - try { return new ActiveXObject('Msxml2.XMLHTTP.6.0'); } catch(e) {} - try { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); } catch(e) {} - try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {} - } - return false; -}; - -/** - * Removes leading and trailing whitespace, added to support IE. - * - * @param {String} s - * @return {String} - * @api private - */ - -var trim = ''.trim - ? function(s) { return s.trim(); } - : function(s) { return s.replace(/(^\s*|\s*$)/g, ''); }; - -/** - * Serialize the given `obj`. - * - * @param {Object} obj - * @return {String} - * @api private - */ - -function serialize(obj) { - if (!isObject(obj)) return obj; - var pairs = []; - for (var key in obj) { - if (null != obj[key]) { - pushEncodedKeyValuePair(pairs, key, obj[key]); - } - } - return pairs.join('&'); -} - -/** - * Helps 'serialize' with serializing arrays. - * Mutates the pairs array. - * - * @param {Array} pairs - * @param {String} key - * @param {Mixed} val - */ - -function pushEncodedKeyValuePair(pairs, key, val) { - if (Array.isArray(val)) { - return val.forEach(function(v) { - pushEncodedKeyValuePair(pairs, key, v); - }); - } - pairs.push(encodeURIComponent(key) - + '=' + encodeURIComponent(val)); -} - -/** - * Expose serialization method. - */ - - request.serializeObject = serialize; - - /** - * Parse the given x-www-form-urlencoded `str`. - * - * @param {String} str - * @return {Object} - * @api private - */ - -function parseString(str) { - var obj = {}; - var pairs = str.split('&'); - var parts; - var pair; - - for (var i = 0, len = pairs.length; i < len; ++i) { - pair = pairs[i]; - parts = pair.split('='); - obj[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]); - } - - return obj; -} - -/** - * Expose parser. - */ - -request.parseString = parseString; - -/** - * Default MIME type map. - * - * superagent.types.xml = 'application/xml'; - * - */ - -request.types = { - html: 'text/html', - json: 'application/json', - xml: 'application/xml', - urlencoded: 'application/x-www-form-urlencoded', - 'form': 'application/x-www-form-urlencoded', - 'form-data': 'application/x-www-form-urlencoded' -}; - -/** - * Default serialization map. - * - * superagent.serialize['application/xml'] = function(obj){ - * return 'generated xml here'; - * }; - * - */ - - request.serialize = { - 'application/x-www-form-urlencoded': serialize, - 'application/json': JSON.stringify - }; - - /** - * Default parsers. - * - * superagent.parse['application/xml'] = function(str){ - * return { object parsed from str }; - * }; - * - */ - -request.parse = { - 'application/x-www-form-urlencoded': parseString, - 'application/json': JSON.parse -}; - -/** - * Parse the given header `str` into - * an object containing the mapped fields. - * - * @param {String} str - * @return {Object} - * @api private - */ - -function parseHeader(str) { - var lines = str.split(/\r?\n/); - var fields = {}; - var index; - var line; - var field; - var val; - - lines.pop(); // trailing CRLF - - for (var i = 0, len = lines.length; i < len; ++i) { - line = lines[i]; - index = line.indexOf(':'); - field = line.slice(0, index).toLowerCase(); - val = trim(line.slice(index + 1)); - fields[field] = val; - } - - return fields; -} - -/** - * Check if `mime` is json or has +json structured syntax suffix. - * - * @param {String} mime - * @return {Boolean} - * @api private - */ - -function isJSON(mime) { - return /[\/+]json\b/.test(mime); -} - -/** - * Return the mime type for the given `str`. - * - * @param {String} str - * @return {String} - * @api private - */ - -function type(str){ - return str.split(/ *; */).shift(); -}; - -/** - * Return header field parameters. - * - * @param {String} str - * @return {Object} - * @api private - */ - -function params(str){ - return reduce(str.split(/ *; */), function(obj, str){ - var parts = str.split(/ *= */) - , key = parts.shift() - , val = parts.shift(); - - if (key && val) obj[key] = val; - return obj; - }, {}); -}; - -/** - * Initialize a new `Response` with the given `xhr`. - * - * - set flags (.ok, .error, etc) - * - parse header - * - * Examples: - * - * Aliasing `superagent` as `request` is nice: - * - * request = superagent; - * - * We can use the promise-like API, or pass callbacks: - * - * request.get('/').end(function(res){}); - * request.get('/', function(res){}); - * - * Sending data can be chained: - * - * request - * .post('/user') - * .send({ name: 'tj' }) - * .end(function(res){}); - * - * Or passed to `.send()`: - * - * request - * .post('/user') - * .send({ name: 'tj' }, function(res){}); - * - * Or passed to `.post()`: - * - * request - * .post('/user', { name: 'tj' }) - * .end(function(res){}); - * - * Or further reduced to a single call for simple cases: - * - * request - * .post('/user', { name: 'tj' }, function(res){}); - * - * @param {XMLHTTPRequest} xhr - * @param {Object} options - * @api private - */ - -function Response(req, options) { - options = options || {}; - this.req = req; - this.xhr = this.req.xhr; - // responseText is accessible only if responseType is '' or 'text' and on older browsers - this.text = ((this.req.method !='HEAD' && (this.xhr.responseType === '' || this.xhr.responseType === 'text')) || typeof this.xhr.responseType === 'undefined') - ? this.xhr.responseText - : null; - this.statusText = this.req.xhr.statusText; - this.setStatusProperties(this.xhr.status); - this.header = this.headers = parseHeader(this.xhr.getAllResponseHeaders()); - // getAllResponseHeaders sometimes falsely returns "" for CORS requests, but - // getResponseHeader still works. so we get content-type even if getting - // other headers fails. - this.header['content-type'] = this.xhr.getResponseHeader('content-type'); - this.setHeaderProperties(this.header); - this.body = this.req.method != 'HEAD' - ? this.parseBody(this.text ? this.text : this.xhr.response) - : null; -} - -/** - * Get case-insensitive `field` value. - * - * @param {String} field - * @return {String} - * @api public - */ - -Response.prototype.get = function(field){ - return this.header[field.toLowerCase()]; -}; - -/** - * Set header related properties: - * - * - `.type` the content type without params - * - * A response of "Content-Type: text/plain; charset=utf-8" - * will provide you with a `.type` of "text/plain". - * - * @param {Object} header - * @api private - */ - -Response.prototype.setHeaderProperties = function(header){ - // content-type - var ct = this.header['content-type'] || ''; - this.type = type(ct); - - // params - var obj = params(ct); - for (var key in obj) this[key] = obj[key]; -}; - -/** - * Parse the given body `str`. - * - * Used for auto-parsing of bodies. Parsers - * are defined on the `superagent.parse` object. - * - * @param {String} str - * @return {Mixed} - * @api private - */ - -Response.prototype.parseBody = function(str){ - var parse = request.parse[this.type]; - if (!parse && isJSON(this.type)) { - parse = request.parse['application/json']; - } - return parse && str && (str.length || str instanceof Object) - ? parse(str) - : null; -}; - -/** - * Set flags such as `.ok` based on `status`. - * - * For example a 2xx response will give you a `.ok` of __true__ - * whereas 5xx will be __false__ and `.error` will be __true__. The - * `.clientError` and `.serverError` are also available to be more - * specific, and `.statusType` is the class of error ranging from 1..5 - * sometimes useful for mapping respond colors etc. - * - * "sugar" properties are also defined for common cases. Currently providing: - * - * - .noContent - * - .badRequest - * - .unauthorized - * - .notAcceptable - * - .notFound - * - * @param {Number} status - * @api private - */ - -Response.prototype.setStatusProperties = function(status){ - // handle IE9 bug: http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request - if (status === 1223) { - status = 204; - } - - var type = status / 100 | 0; - - // status / class - this.status = this.statusCode = status; - this.statusType = type; - - // basics - this.info = 1 == type; - this.ok = 2 == type; - this.clientError = 4 == type; - this.serverError = 5 == type; - this.error = (4 == type || 5 == type) - ? this.toError() - : false; - - // sugar - this.accepted = 202 == status; - this.noContent = 204 == status; - this.badRequest = 400 == status; - this.unauthorized = 401 == status; - this.notAcceptable = 406 == status; - this.notFound = 404 == status; - this.forbidden = 403 == status; -}; - -/** - * Return an `Error` representative of this response. - * - * @return {Error} - * @api public - */ - -Response.prototype.toError = function(){ - var req = this.req; - var method = req.method; - var url = req.url; - - var msg = 'cannot ' + method + ' ' + url + ' (' + this.status + ')'; - var err = new Error(msg); - err.status = this.status; - err.method = method; - err.url = url; - - return err; -}; - -/** - * Expose `Response`. - */ - -request.Response = Response; - -/** - * Initialize a new `Request` with the given `method` and `url`. - * - * @param {String} method - * @param {String} url - * @api public - */ - -function Request(method, url) { - var self = this; - this._query = this._query || []; - this.method = method; - this.url = url; - this.header = {}; // preserves header name case - this._header = {}; // coerces header names to lowercase - this.on('end', function(){ - var err = null; - var res = null; - - try { - res = new Response(self); - } catch(e) { - err = new Error('Parser is unable to parse the response'); - err.parse = true; - err.original = e; - // issue #675: return the raw response if the response parsing fails - err.rawResponse = self.xhr && self.xhr.responseText ? self.xhr.responseText : null; - // issue #876: return the http status code if the response parsing fails - err.statusCode = self.xhr && self.xhr.status ? self.xhr.status : null; - return self.callback(err); - } - - self.emit('response', res); - - if (err) { - return self.callback(err, res); - } - - if (res.status >= 200 && res.status < 300) { - return self.callback(err, res); - } - - var new_err = new Error(res.statusText || 'Unsuccessful HTTP response'); - new_err.original = err; - new_err.response = res; - new_err.status = res.status; - - self.callback(new_err, res); - }); -} - -/** - * Mixin `Emitter` and `requestBase`. - */ - -Emitter(Request.prototype); -for (var key in requestBase) { - Request.prototype[key] = requestBase[key]; -} - -/** - * Abort the request, and clear potential timeout. - * - * @return {Request} - * @api public - */ - -Request.prototype.abort = function(){ - if (this.aborted) return; - this.aborted = true; - this.xhr.abort(); - this.clearTimeout(); - this.emit('abort'); - return this; -}; - -/** - * Set Content-Type to `type`, mapping values from `request.types`. - * - * Examples: - * - * superagent.types.xml = 'application/xml'; - * - * request.post('/') - * .type('xml') - * .send(xmlstring) - * .end(callback); - * - * request.post('/') - * .type('application/xml') - * .send(xmlstring) - * .end(callback); - * - * @param {String} type - * @return {Request} for chaining - * @api public - */ - -Request.prototype.type = function(type){ - this.set('Content-Type', request.types[type] || type); - return this; -}; - -/** - * Set responseType to `val`. Presently valid responseTypes are 'blob' and - * 'arraybuffer'. - * - * Examples: - * - * req.get('/') - * .responseType('blob') - * .end(callback); - * - * @param {String} val - * @return {Request} for chaining - * @api public - */ - -Request.prototype.responseType = function(val){ - this._responseType = val; - return this; -}; - -/** - * Set Accept to `type`, mapping values from `request.types`. - * - * Examples: - * - * superagent.types.json = 'application/json'; - * - * request.get('/agent') - * .accept('json') - * .end(callback); - * - * request.get('/agent') - * .accept('application/json') - * .end(callback); - * - * @param {String} accept - * @return {Request} for chaining - * @api public - */ - -Request.prototype.accept = function(type){ - this.set('Accept', request.types[type] || type); - return this; -}; - -/** - * Set Authorization field value with `user` and `pass`. - * - * @param {String} user - * @param {String} pass - * @param {Object} options with 'type' property 'auto' or 'basic' (default 'basic') - * @return {Request} for chaining - * @api public - */ - -Request.prototype.auth = function(user, pass, options){ - if (!options) { - options = { - type: 'basic' - } - } - - switch (options.type) { - case 'basic': - var str = btoa(user + ':' + pass); - this.set('Authorization', 'Basic ' + str); - break; - - case 'auto': - this.username = user; - this.password = pass; - break; - } - return this; -}; - -/** -* Add query-string `val`. -* -* Examples: -* -* request.get('/shoes') -* .query('size=10') -* .query({ color: 'blue' }) -* -* @param {Object|String} val -* @return {Request} for chaining -* @api public -*/ - -Request.prototype.query = function(val){ - if ('string' != typeof val) val = serialize(val); - if (val) this._query.push(val); - return this; -}; - -/** - * Queue the given `file` as an attachment to the specified `field`, - * with optional `filename`. - * - * ``` js - * request.post('/upload') - * .attach(new Blob(['hey!'], { type: "text/html"})) - * .end(callback); - * ``` - * - * @param {String} field - * @param {Blob|File} file - * @param {String} filename - * @return {Request} for chaining - * @api public - */ - -Request.prototype.attach = function(field, file, filename){ - this._getFormData().append(field, file, filename || file.name); - return this; -}; - -Request.prototype._getFormData = function(){ - if (!this._formData) { - this._formData = new root.FormData(); - } - return this._formData; -}; - -/** - * Send `data` as the request body, defaulting the `.type()` to "json" when - * an object is given. - * - * Examples: - * - * // manual json - * request.post('/user') - * .type('json') - * .send('{"name":"tj"}') - * .end(callback) - * - * // auto json - * request.post('/user') - * .send({ name: 'tj' }) - * .end(callback) - * - * // manual x-www-form-urlencoded - * request.post('/user') - * .type('form') - * .send('name=tj') - * .end(callback) - * - * // auto x-www-form-urlencoded - * request.post('/user') - * .type('form') - * .send({ name: 'tj' }) - * .end(callback) - * - * // defaults to x-www-form-urlencoded - * request.post('/user') - * .send('name=tobi') - * .send('species=ferret') - * .end(callback) - * - * @param {String|Object} data - * @return {Request} for chaining - * @api public - */ - -Request.prototype.send = function(data){ - var obj = isObject(data); - var type = this._header['content-type']; - - // merge - if (obj && isObject(this._data)) { - for (var key in data) { - this._data[key] = data[key]; - } - } else if ('string' == typeof data) { - if (!type) this.type('form'); - type = this._header['content-type']; - if ('application/x-www-form-urlencoded' == type) { - this._data = this._data - ? this._data + '&' + data - : data; - } else { - this._data = (this._data || '') + data; - } - } else { - this._data = data; - } - - if (!obj || isHost(data)) return this; - if (!type) this.type('json'); - return this; -}; - -/** - * @deprecated - */ -Response.prototype.parse = function serialize(fn){ - if (root.console) { - console.warn("Client-side parse() method has been renamed to serialize(). This method is not compatible with superagent v2.0"); - } - this.serialize(fn); - return this; -}; - -Response.prototype.serialize = function serialize(fn){ - this._parser = fn; - return this; -}; - -/** - * Invoke the callback with `err` and `res` - * and handle arity check. - * - * @param {Error} err - * @param {Response} res - * @api private - */ - -Request.prototype.callback = function(err, res){ - var fn = this._callback; - this.clearTimeout(); - fn(err, res); -}; - -/** - * Invoke callback with x-domain error. - * - * @api private - */ - -Request.prototype.crossDomainError = function(){ - var err = new Error('Request has been terminated\nPossible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc.'); - err.crossDomain = true; - - err.status = this.status; - err.method = this.method; - err.url = this.url; - - this.callback(err); -}; - -/** - * Invoke callback with timeout error. - * - * @api private - */ - -Request.prototype.timeoutError = function(){ - var timeout = this._timeout; - var err = new Error('timeout of ' + timeout + 'ms exceeded'); - err.timeout = timeout; - this.callback(err); -}; - -/** - * Enable transmission of cookies with x-domain requests. - * - * Note that for this to work the origin must not be - * using "Access-Control-Allow-Origin" with a wildcard, - * and also must set "Access-Control-Allow-Credentials" - * to "true". - * - * @api public - */ - -Request.prototype.withCredentials = function(){ - this._withCredentials = true; - return this; -}; - -/** - * Initiate request, invoking callback `fn(res)` - * with an instanceof `Response`. - * - * @param {Function} fn - * @return {Request} for chaining - * @api public - */ - -Request.prototype.end = function(fn){ - var self = this; - var xhr = this.xhr = request.getXHR(); - var query = this._query.join('&'); - var timeout = this._timeout; - var data = this._formData || this._data; - - // store callback - this._callback = fn || noop; - - // state change - xhr.onreadystatechange = function(){ - if (4 != xhr.readyState) return; - - // In IE9, reads to any property (e.g. status) off of an aborted XHR will - // result in the error "Could not complete the operation due to error c00c023f" - var status; - try { status = xhr.status } catch(e) { status = 0; } - - if (0 == status) { - if (self.timedout) return self.timeoutError(); - if (self.aborted) return; - return self.crossDomainError(); - } - self.emit('end'); - }; - - // progress - var handleProgress = function(e){ - if (e.total > 0) { - e.percent = e.loaded / e.total * 100; - } - e.direction = 'download'; - self.emit('progress', e); - }; - if (this.hasListeners('progress')) { - xhr.onprogress = handleProgress; - } - try { - if (xhr.upload && this.hasListeners('progress')) { - xhr.upload.onprogress = handleProgress; - } - } catch(e) { - // Accessing xhr.upload fails in IE from a web worker, so just pretend it doesn't exist. - // Reported here: - // https://connect.microsoft.com/IE/feedback/details/837245/xmlhttprequest-upload-throws-invalid-argument-when-used-from-web-worker-context - } - - // timeout - if (timeout && !this._timer) { - this._timer = setTimeout(function(){ - self.timedout = true; - self.abort(); - }, timeout); - } - - // querystring - if (query) { - query = request.serializeObject(query); - this.url += ~this.url.indexOf('?') - ? '&' + query - : '?' + query; - } - - // initiate request - if (this.username && this.password) { - xhr.open(this.method, this.url, true, this.username, this.password); - } else { - xhr.open(this.method, this.url, true); - } - - // CORS - if (this._withCredentials) xhr.withCredentials = true; - - // body - if ('GET' != this.method && 'HEAD' != this.method && 'string' != typeof data && !isHost(data)) { - // serialize stuff - var contentType = this._header['content-type']; - var serialize = this._parser || request.serialize[contentType ? contentType.split(';')[0] : '']; - if (!serialize && isJSON(contentType)) serialize = request.serialize['application/json']; - if (serialize) data = serialize(data); - } - - // set header fields - for (var field in this.header) { - if (null == this.header[field]) continue; - xhr.setRequestHeader(field, this.header[field]); - } - - if (this._responseType) { - xhr.responseType = this._responseType; - } - - // send stuff - this.emit('request', this); - - // IE11 xhr.send(undefined) sends 'undefined' string as POST payload (instead of nothing) - // We need null here if data is undefined - xhr.send(typeof data !== 'undefined' ? data : null); - return this; -}; - - -/** - * Expose `Request`. - */ - -request.Request = Request; - -/** - * GET `url` with optional callback `fn(res)`. - * - * @param {String} url - * @param {Mixed|Function} data or fn - * @param {Function} fn - * @return {Request} - * @api public - */ - -request.get = function(url, data, fn){ - var req = request('GET', url); - if ('function' == typeof data) fn = data, data = null; - if (data) req.query(data); - if (fn) req.end(fn); - return req; -}; - -/** - * HEAD `url` with optional callback `fn(res)`. - * - * @param {String} url - * @param {Mixed|Function} data or fn - * @param {Function} fn - * @return {Request} - * @api public - */ - -request.head = function(url, data, fn){ - var req = request('HEAD', url); - if ('function' == typeof data) fn = data, data = null; - if (data) req.send(data); - if (fn) req.end(fn); - return req; -}; - -/** - * DELETE `url` with optional callback `fn(res)`. - * - * @param {String} url - * @param {Function} fn - * @return {Request} - * @api public - */ - -function del(url, fn){ - var req = request('DELETE', url); - if (fn) req.end(fn); - return req; -}; - -request['del'] = del; -request['delete'] = del; - -/** - * PATCH `url` with optional `data` and callback `fn(res)`. - * - * @param {String} url - * @param {Mixed} data - * @param {Function} fn - * @return {Request} - * @api public - */ - -request.patch = function(url, data, fn){ - var req = request('PATCH', url); - if ('function' == typeof data) fn = data, data = null; - if (data) req.send(data); - if (fn) req.end(fn); - return req; -}; - -/** - * POST `url` with optional `data` and callback `fn(res)`. - * - * @param {String} url - * @param {Mixed} data - * @param {Function} fn - * @return {Request} - * @api public - */ - -request.post = function(url, data, fn){ - var req = request('POST', url); - if ('function' == typeof data) fn = data, data = null; - if (data) req.send(data); - if (fn) req.end(fn); - return req; -}; - -/** - * PUT `url` with optional `data` and callback `fn(res)`. - * - * @param {String} url - * @param {Mixed|Function} data or fn - * @param {Function} fn - * @return {Request} - * @api public - */ - -request.put = function(url, data, fn){ - var req = request('PUT', url); - if ('function' == typeof data) fn = data, data = null; - if (data) req.send(data); - if (fn) req.end(fn); - return req; -}; - -},{"./is-object":15,"./request":17,"./request-base":16,"emitter":2,"reduce":12}],15:[function(require,module,exports){ -/** - * Check if `obj` is an object. - * - * @param {Object} obj - * @return {Boolean} - * @api private - */ - -function isObject(obj) { - return null != obj && 'object' == typeof obj; -} - -module.exports = isObject; - -},{}],16:[function(require,module,exports){ -/** - * Module of mixed-in functions shared between node and client code - */ -var isObject = require('./is-object'); - -/** - * Clear previous timeout. - * - * @return {Request} for chaining - * @api public - */ - -exports.clearTimeout = function _clearTimeout(){ - this._timeout = 0; - clearTimeout(this._timer); - return this; -}; - -/** - * Force given parser - * - * Sets the body parser no matter type. - * - * @param {Function} - * @api public - */ - -exports.parse = function parse(fn){ - this._parser = fn; - return this; -}; - -/** - * Set timeout to `ms`. - * - * @param {Number} ms - * @return {Request} for chaining - * @api public - */ - -exports.timeout = function timeout(ms){ - this._timeout = ms; - return this; -}; - -/** - * Faux promise support - * - * @param {Function} fulfill - * @param {Function} reject - * @return {Request} - */ - -exports.then = function then(fulfill, reject) { - return this.end(function(err, res) { - err ? reject(err) : fulfill(res); - }); -} - -/** - * Allow for extension - */ - -exports.use = function use(fn) { - fn(this); - return this; -} - - -/** - * Get request header `field`. - * Case-insensitive. - * - * @param {String} field - * @return {String} - * @api public - */ - -exports.get = function(field){ - return this._header[field.toLowerCase()]; -}; - -/** - * Get case-insensitive header `field` value. - * This is a deprecated internal API. Use `.get(field)` instead. - * - * (getHeader is no longer used internally by the superagent code base) - * - * @param {String} field - * @return {String} - * @api private - * @deprecated - */ - -exports.getHeader = exports.get; - -/** - * Set header `field` to `val`, or multiple fields with one object. - * Case-insensitive. - * - * Examples: - * - * req.get('/') - * .set('Accept', 'application/json') - * .set('X-API-Key', 'foobar') - * .end(callback); - * - * req.get('/') - * .set({ Accept: 'application/json', 'X-API-Key': 'foobar' }) - * .end(callback); - * - * @param {String|Object} field - * @param {String} val - * @return {Request} for chaining - * @api public - */ - -exports.set = function(field, val){ - if (isObject(field)) { - for (var key in field) { - this.set(key, field[key]); - } - return this; - } - this._header[field.toLowerCase()] = val; - this.header[field] = val; - return this; -}; - -/** - * Remove header `field`. - * Case-insensitive. - * - * Example: - * - * req.get('/') - * .unset('User-Agent') - * .end(callback); - * - * @param {String} field - */ -exports.unset = function(field){ - delete this._header[field.toLowerCase()]; - delete this.header[field]; - return this; -}; - -/** - * Write the field `name` and `val` for "multipart/form-data" - * request bodies. - * - * ``` js - * request.post('/upload') - * .field('foo', 'bar') - * .end(callback); - * ``` - * - * @param {String} name - * @param {String|Blob|File|Buffer|fs.ReadStream} val - * @return {Request} for chaining - * @api public - */ -exports.field = function(name, val) { - this._getFormData().append(name, val); - return this; -}; - -},{"./is-object":15}],17:[function(require,module,exports){ -// The node and browser modules expose versions of this with the -// appropriate constructor function bound as first argument -/** - * Issue a request: - * - * Examples: - * - * request('GET', '/users').end(callback) - * request('/users').end(callback) - * request('/users', callback) - * - * @param {String} method - * @param {String|Function} url or callback - * @return {Request} - * @api public - */ - -function request(RequestConstructor, method, url) { - // callback - if ('function' == typeof url) { - return new RequestConstructor('GET', method).end(url); - } - - // url first - if (2 == arguments.length) { - return new RequestConstructor('GET', method); - } - - return new RequestConstructor(method, url); -} - -module.exports = request; - -},{}],18:[function(require,module,exports){ -/*! https://mths.be/punycode v1.3.2 by @mathias, modified for URI.js */ - -var punycode = (function () { - - /** - * The `punycode` object. - * @name punycode - * @type Object - */ - var punycode, - - /** Highest positive signed 32-bit float value */ - maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 - - /** Bootstring parameters */ - base = 36, - tMin = 1, - tMax = 26, - skew = 38, - damp = 700, - initialBias = 72, - initialN = 128, // 0x80 - delimiter = '-', // '\x2D' - - /** Regular expressions */ - regexPunycode = /^xn--/, - regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars - regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators - - /** Error messages */ - errors = { - 'overflow': 'Overflow: input needs wider integers to process', - 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', - 'invalid-input': 'Invalid input' - }, - - /** Convenience shortcuts */ - baseMinusTMin = base - tMin, - floor = Math.floor, - stringFromCharCode = String.fromCharCode, - - /** Temporary variable */ - key; - - /*--------------------------------------------------------------------------*/ - - /** - * A generic error utility function. - * @private - * @param {String} type The error type. - * @returns {Error} Throws a `RangeError` with the applicable error message. - */ - function error(type) { - throw new RangeError(errors[type]); - } - - /** - * A generic `Array#map` utility function. - * @private - * @param {Array} array The array to iterate over. - * @param {Function} callback The function that gets called for every array - * item. - * @returns {Array} A new array of values returned by the callback function. - */ - function map(array, fn) { - var length = array.length; - var result = []; - while (length--) { - result[length] = fn(array[length]); - } - return result; - } - - /** - * A simple `Array#map`-like wrapper to work with domain name strings or email - * addresses. - * @private - * @param {String} domain The domain name or email address. - * @param {Function} callback The function that gets called for every - * character. - * @returns {Array} A new string of characters returned by the callback - * function. - */ - function mapDomain(string, fn) { - var parts = string.split('@'); - var result = ''; - if (parts.length > 1) { - // In email addresses, only the domain name should be punycoded. Leave - // the local part (i.e. everything up to `@`) intact. - result = parts[0] + '@'; - string = parts[1]; - } - // Avoid `split(regex)` for IE8 compatibility. See #17. - string = string.replace(regexSeparators, '\x2E'); - var labels = string.split('.'); - var encoded = map(labels, fn).join('.'); - return result + encoded; - } - - /** - * Creates an array containing the numeric code points of each Unicode - * character in the string. While JavaScript uses UCS-2 internally, - * this function will convert a pair of surrogate halves (each of which - * UCS-2 exposes as separate characters) into a single code point, - * matching UTF-16. - * @see `punycode.ucs2.encode` - * @see - * @memberOf punycode.ucs2 - * @name decode - * @param {String} string The Unicode input string (UCS-2). - * @returns {Array} The new array of code points. - */ - function ucs2decode(string) { - var output = [], - counter = 0, - length = string.length, - value, - extra; - while (counter < length) { - value = string.charCodeAt(counter++); - if (value >= 0xD800 && value <= 0xDBFF && counter < length) { - // high surrogate, and there is a next character - extra = string.charCodeAt(counter++); - if ((extra & 0xFC00) == 0xDC00) { // low surrogate - output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); - } else { - // unmatched surrogate; only append this code unit, in case the next - // code unit is the high surrogate of a surrogate pair - output.push(value); - counter--; - } - } else { - output.push(value); - } - } - return output; - } - - /** - * Creates a string based on an array of numeric code points. - * @see `punycode.ucs2.decode` - * @memberOf punycode.ucs2 - * @name encode - * @param {Array} codePoints The array of numeric code points. - * @returns {String} The new Unicode string (UCS-2). - */ - function ucs2encode(array) { - return map(array, function(value) { - var output = ''; - if (value > 0xFFFF) { - value -= 0x10000; - output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); - value = 0xDC00 | value & 0x3FF; - } - output += stringFromCharCode(value); - return output; - }).join(''); - } - - /** - * Converts a basic code point into a digit/integer. - * @see `digitToBasic()` - * @private - * @param {Number} codePoint The basic numeric code point value. - * @returns {Number} The numeric value of a basic code point (for use in - * representing integers) in the range `0` to `base - 1`, or `base` if - * the code point does not represent a value. - */ - function basicToDigit(codePoint) { - if (codePoint - 48 < 10) { - return codePoint - 22; - } - if (codePoint - 65 < 26) { - return codePoint - 65; - } - if (codePoint - 97 < 26) { - return codePoint - 97; - } - return base; - } - - /** - * Converts a digit/integer into a basic code point. - * @see `basicToDigit()` - * @private - * @param {Number} digit The numeric value of a basic code point. - * @returns {Number} The basic code point whose value (when used for - * representing integers) is `digit`, which needs to be in the range - * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is - * used; else, the lowercase form is used. The behavior is undefined - * if `flag` is non-zero and `digit` has no uppercase form. - */ - function digitToBasic(digit, flag) { - // 0..25 map to ASCII a..z or A..Z - // 26..35 map to ASCII 0..9 - return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); - } - - /** - * Bias adaptation function as per section 3.4 of RFC 3492. - * https://tools.ietf.org/html/rfc3492#section-3.4 - * @private - */ - function adapt(delta, numPoints, firstTime) { - var k = 0; - delta = firstTime ? floor(delta / damp) : delta >> 1; - delta += floor(delta / numPoints); - for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { - delta = floor(delta / baseMinusTMin); - } - return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); - } - - /** - * Converts a Punycode string of ASCII-only symbols to a string of Unicode - * symbols. - * @memberOf punycode - * @param {String} input The Punycode string of ASCII-only symbols. - * @returns {String} The resulting string of Unicode symbols. - */ - function decode(input) { - // Don't use UCS-2 - var output = [], - inputLength = input.length, - out, - i = 0, - n = initialN, - bias = initialBias, - basic, - j, - index, - oldi, - w, - k, - digit, - t, - /** Cached calculation results */ - baseMinusT; - - // Handle the basic code points: let `basic` be the number of input code - // points before the last delimiter, or `0` if there is none, then copy - // the first basic code points to the output. - - basic = input.lastIndexOf(delimiter); - if (basic < 0) { - basic = 0; - } - - for (j = 0; j < basic; ++j) { - // if it's not a basic code point - if (input.charCodeAt(j) >= 0x80) { - error('not-basic'); - } - output.push(input.charCodeAt(j)); - } - - // Main decoding loop: start just after the last delimiter if any basic code - // points were copied; start at the beginning otherwise. - - for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { - - // `index` is the index of the next character to be consumed. - // Decode a generalized variable-length integer into `delta`, - // which gets added to `i`. The overflow checking is easier - // if we increase `i` as we go, then subtract off its starting - // value at the end to obtain `delta`. - for (oldi = i, w = 1, k = base; /* no condition */; k += base) { - - if (index >= inputLength) { - error('invalid-input'); - } - - digit = basicToDigit(input.charCodeAt(index++)); - - if (digit >= base || digit > floor((maxInt - i) / w)) { - error('overflow'); - } - - i += digit * w; - t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); - - if (digit < t) { - break; - } - - baseMinusT = base - t; - if (w > floor(maxInt / baseMinusT)) { - error('overflow'); - } - - w *= baseMinusT; - - } - - out = output.length + 1; - bias = adapt(i - oldi, out, oldi == 0); - - // `i` was supposed to wrap around from `out` to `0`, - // incrementing `n` each time, so we'll fix that now: - if (floor(i / out) > maxInt - n) { - error('overflow'); - } - - n += floor(i / out); - i %= out; - - // Insert `n` at position `i` of the output - output.splice(i++, 0, n); - - } - - return ucs2encode(output); - } - - /** - * Converts a string of Unicode symbols (e.g. a domain name label) to a - * Punycode string of ASCII-only symbols. - * @memberOf punycode - * @param {String} input The string of Unicode symbols. - * @returns {String} The resulting Punycode string of ASCII-only symbols. - */ - function encode(input) { - var n, - delta, - handledCPCount, - basicLength, - bias, - j, - m, - q, - k, - t, - currentValue, - output = [], - /** `inputLength` will hold the number of code points in `input`. */ - inputLength, - /** Cached calculation results */ - handledCPCountPlusOne, - baseMinusT, - qMinusT; - - // Convert the input in UCS-2 to Unicode - input = ucs2decode(input); - - // Cache the length - inputLength = input.length; - - // Initialize the state - n = initialN; - delta = 0; - bias = initialBias; - - // Handle the basic code points - for (j = 0; j < inputLength; ++j) { - currentValue = input[j]; - if (currentValue < 0x80) { - output.push(stringFromCharCode(currentValue)); - } - } - - handledCPCount = basicLength = output.length; - - // `handledCPCount` is the number of code points that have been handled; - // `basicLength` is the number of basic code points. - - // Finish the basic string - if it is not empty - with a delimiter - if (basicLength) { - output.push(delimiter); - } - - // Main encoding loop: - while (handledCPCount < inputLength) { - - // All non-basic code points < n have been handled already. Find the next - // larger one: - for (m = maxInt, j = 0; j < inputLength; ++j) { - currentValue = input[j]; - if (currentValue >= n && currentValue < m) { - m = currentValue; - } - } - - // Increase `delta` enough to advance the decoder's state to , - // but guard against overflow - handledCPCountPlusOne = handledCPCount + 1; - if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { - error('overflow'); - } - - delta += (m - n) * handledCPCountPlusOne; - n = m; - - for (j = 0; j < inputLength; ++j) { - currentValue = input[j]; - - if (currentValue < n && ++delta > maxInt) { - error('overflow'); - } - - if (currentValue == n) { - // Represent delta as a generalized variable-length integer - for (q = delta, k = base; /* no condition */; k += base) { - t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); - if (q < t) { - break; - } - qMinusT = q - t; - baseMinusT = base - t; - output.push( - stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) - ); - q = floor(qMinusT / baseMinusT); - } - - output.push(stringFromCharCode(digitToBasic(q, 0))); - bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); - delta = 0; - ++handledCPCount; - } - } - - ++delta; - ++n; - - } - return output.join(''); - } - - /** - * Converts a Punycode string representing a domain name or an email address - * to Unicode. Only the Punycoded parts of the input will be converted, i.e. - * it doesn't matter if you call it on a string that has already been - * converted to Unicode. - * @memberOf punycode - * @param {String} input The Punycoded domain name or email address to - * convert to Unicode. - * @returns {String} The Unicode representation of the given Punycode - * string. - */ - function toUnicode(input) { - return mapDomain(input, function(string) { - return regexPunycode.test(string) - ? decode(string.slice(4).toLowerCase()) - : string; - }); - } - - /** - * Converts a Unicode string representing a domain name or an email address to - * Punycode. Only the non-ASCII parts of the domain name will be converted, - * i.e. it doesn't matter if you call it with a domain that's already in - * ASCII. - * @memberOf punycode - * @param {String} input The domain name or email address to convert, as a - * Unicode string. - * @returns {String} The Punycode representation of the given domain name or - * email address. - */ - function toASCII(input) { - return mapDomain(input, function(string) { - return regexNonASCII.test(string) - ? 'xn--' + encode(string) - : string; - }); - } - - /*--------------------------------------------------------------------------*/ - - /** Define the public API */ - punycode = { - /** - * A string representing the current Punycode.js version number. - * @memberOf punycode - * @type String - */ - version: '1.3.2', - /** - * An object of methods to convert from JavaScript's internal character - * representation (UCS-2) to Unicode code points, and back. - * @see - * @memberOf punycode - * @type Object - */ - ucs2: { - decode: ucs2decode, - encode: ucs2encode - }, - decode: decode, - encode: encode, - toASCII: toASCII, - toUnicode: toUnicode - }; - - return punycode; -}()); - -if (typeof COMPILED === "undefined" && typeof module !== "undefined") module.exports = punycode; -},{}],19:[function(require,module,exports){ -/// -require("./schemes/http"); -require("./schemes/urn"); -require("./schemes/mailto"); - -},{"./schemes/http":20,"./schemes/mailto":21,"./schemes/urn":22}],20:[function(require,module,exports){ -/// -if (typeof COMPILED === "undefined" && typeof URI === "undefined" && typeof require === "function") - var URI = require("../uri"); -URI.SCHEMES["http"] = URI.SCHEMES["https"] = { - domainHost: true, - parse: function (components, options) { - //report missing host - if (!components.host) { - components.error = components.error || "HTTP URIs must have a host."; - } - return components; - }, - serialize: function (components, options) { - //normalize the default port - if (components.port === (String(components.scheme).toLowerCase() !== "https" ? 80 : 443) || components.port === "") { - components.port = undefined; - } - //normalize the empty path - if (!components.path) { - components.path = "/"; - } - //NOTE: We do not parse query strings for HTTP URIs - //as WWW Form Url Encoded query strings are part of the HTML4+ spec, - //and not the HTTP spec. - return components; - } -}; - -},{"../uri":23}],21:[function(require,module,exports){ -/// -if (typeof COMPILED === "undefined" && typeof URI === "undefined" && typeof require === "function") { - var URI = require("../uri"), punycode = require("../punycode"); -} -(function () { - function merge() { - var sets = []; - for (var _i = 0; _i < arguments.length; _i++) { - sets[_i - 0] = arguments[_i]; - } - if (sets.length > 1) { - sets[0] = sets[0].slice(0, -1); - var xl = sets.length - 1; - for (var x = 1; x < xl; ++x) { - sets[x] = sets[x].slice(1, -1); - } - sets[xl] = sets[xl].slice(1); - return sets.join(''); - } - else { - return sets[0]; - } - } - function subexp(str) { - return "(?:" + str + ")"; - } - var O = {}, isIRI = URI.IRI_SUPPORT, - //RFC 3986 - UNRESERVED$$ = "[A-Za-z0-9\\-\\.\\_\\~" + (isIRI ? "\\xA0-\\u200D\\u2010-\\u2029\\u202F-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF" : "") + "]", HEXDIG$$ = "[0-9A-Fa-f]", PCT_ENCODED$ = subexp(subexp("%[EFef]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + subexp("%[89A-Fa-f]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + subexp("%" + HEXDIG$$ + HEXDIG$$)), - //RFC 5322, except these symbols as per RFC 6068: @ : / ? # [ ] & ; = - //ATEXT$$ = "[A-Za-z0-9\\!\\#\\$\\%\\&\\'\\*\\+\\-\\/\\=\\?\\^\\_\\`\\{\\|\\}\\~]", - //WSP$$ = "[\\x20\\x09]", - //OBS_QTEXT$$ = "[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]", //(%d1-8 / %d11-12 / %d14-31 / %d127) - //QTEXT$$ = merge("[\\x21\\x23-\\x5B\\x5D-\\x7E]", OBS_QTEXT$$), //%d33 / %d35-91 / %d93-126 / obs-qtext - //VCHAR$$ = "[\\x21-\\x7E]", - //WSP$$ = "[\\x20\\x09]", - //OBS_QP$ = subexp("\\\\" + merge("[\\x00\\x0D\\x0A]", OBS_QTEXT$$)), //%d0 / CR / LF / obs-qtext - //FWS$ = subexp(subexp(WSP$$ + "*" + "\\x0D\\x0A") + "?" + WSP$$ + "+"), - //QUOTED_PAIR$ = subexp(subexp("\\\\" + subexp(VCHAR$$ + "|" + WSP$$)) + "|" + OBS_QP$), - //QUOTED_STRING$ = subexp('\\"' + subexp(FWS$ + "?" + QCONTENT$) + "*" + FWS$ + "?" + '\\"'), - ATEXT$$ = "[A-Za-z0-9\\!\\$\\%\\'\\*\\+\\-\\^\\_\\`\\{\\|\\}\\~]", QTEXT$$ = "[\\!\\$\\%\\'\\(\\)\\*\\+\\,\\-\\.0-9\\<\\>A-Z\\x5E-\\x7E]", VCHAR$$ = merge(QTEXT$$, "[\\\"\\\\]"), DOT_ATOM_TEXT$ = subexp(ATEXT$$ + "+" + subexp("\\." + ATEXT$$ + "+") + "*"), QUOTED_PAIR$ = subexp("\\\\" + VCHAR$$), QCONTENT$ = subexp(QTEXT$$ + "|" + QUOTED_PAIR$), QUOTED_STRING$ = subexp('\\"' + QCONTENT$ + "*" + '\\"'), - //RFC 6068 - DTEXT_NO_OBS$$ = "[\\x21-\\x5A\\x5E-\\x7E]", SOME_DELIMS$$ = "[\\!\\$\\'\\(\\)\\*\\+\\,\\;\\:\\@]", QCHAR$ = subexp(UNRESERVED$$ + "|" + PCT_ENCODED$ + "|" + SOME_DELIMS$$), DOMAIN$ = subexp(DOT_ATOM_TEXT$ + "|" + "\\[" + DTEXT_NO_OBS$$ + "*" + "\\]"), LOCAL_PART$ = subexp(DOT_ATOM_TEXT$ + "|" + QUOTED_STRING$), ADDR_SPEC$ = subexp(LOCAL_PART$ + "\\@" + DOMAIN$), TO$ = subexp(ADDR_SPEC$ + subexp("\\," + ADDR_SPEC$) + "*"), HFNAME$ = subexp(QCHAR$ + "*"), HFVALUE$ = HFNAME$, HFIELD$ = subexp(HFNAME$ + "\\=" + HFVALUE$), HFIELDS2$ = subexp(HFIELD$ + subexp("\\&" + HFIELD$) + "*"), HFIELDS$ = subexp("\\?" + HFIELDS2$), MAILTO_URI = URI.VALIDATE_SUPPORT && new RegExp("^mailto\\:" + TO$ + "?" + HFIELDS$ + "?$"), UNRESERVED = new RegExp(UNRESERVED$$, "g"), PCT_ENCODED = new RegExp(PCT_ENCODED$, "g"), NOT_LOCAL_PART = new RegExp(merge("[^]", ATEXT$$, "[\\.]", '[\\"]', VCHAR$$), "g"), NOT_DOMAIN = new RegExp(merge("[^]", ATEXT$$, "[\\.]", "[\\[]", DTEXT_NO_OBS$$, "[\\]]"), "g"), NOT_HFNAME = new RegExp(merge("[^]", UNRESERVED$$, SOME_DELIMS$$), "g"), NOT_HFVALUE = NOT_HFNAME, TO = URI.VALIDATE_SUPPORT && new RegExp("^" + TO$ + "$"), HFIELDS = URI.VALIDATE_SUPPORT && new RegExp("^" + HFIELDS2$ + "$"); - function toUpperCase(str) { - return str.toUpperCase(); - } - function decodeUnreserved(str) { - var decStr = URI.pctDecChars(str); - return (!decStr.match(UNRESERVED) ? str : decStr); - } - function toArray(obj) { - return obj !== undefined && obj !== null ? (obj instanceof Array && !obj.callee ? obj : (typeof obj.length !== "number" || obj.split || obj.setInterval || obj.call ? [obj] : Array.prototype.slice.call(obj))) : []; - } - URI.SCHEMES["mailto"] = { - parse: function (components, options) { - if (URI.VALIDATE_SUPPORT && !components.error) { - if (components.path && !TO.test(components.path)) { - components.error = "Email address is not valid"; - } - else if (components.query && !HFIELDS.test(components.query)) { - components.error = "Header fields are invalid"; - } - } - var to = components.to = (components.path ? components.path.split(",") : []); - components.path = undefined; - if (components.query) { - var unknownHeaders = false, headers = {}; - var hfields = components.query.split("&"); - for (var x = 0, xl = hfields.length; x < xl; ++x) { - var hfield = hfields[x].split("="); - switch (hfield[0]) { - case "to": - var toAddrs = hfield[1].split(","); - for (var x_1 = 0, xl_1 = toAddrs.length; x_1 < xl_1; ++x_1) { - to.push(toAddrs[x_1]); - } - break; - case "subject": - components.subject = URI.unescapeComponent(hfield[1], options); - break; - case "body": - components.body = URI.unescapeComponent(hfield[1], options); - break; - default: - unknownHeaders = true; - headers[URI.unescapeComponent(hfield[0], options)] = URI.unescapeComponent(hfield[1], options); - break; - } - } - if (unknownHeaders) - components.headers = headers; - } - components.query = undefined; - for (var x = 0, xl = to.length; x < xl; ++x) { - var addr = to[x].split("@"); - addr[0] = URI.unescapeComponent(addr[0]); - if (typeof punycode !== "undefined" && !options.unicodeSupport) { - //convert Unicode IDN -> ASCII IDN - try { - addr[1] = punycode.toASCII(URI.unescapeComponent(addr[1], options).toLowerCase()); - } - catch (e) { - components.error = components.error || "Email address's domain name can not be converted to ASCII via punycode: " + e; - } - } - else { - addr[1] = URI.unescapeComponent(addr[1], options).toLowerCase(); - } - to[x] = addr.join("@"); - } - return components; - }, - serialize: function (components, options) { - var to = toArray(components.to); - if (to) { - for (var x = 0, xl = to.length; x < xl; ++x) { - var toAddr = String(to[x]); - var atIdx = toAddr.lastIndexOf("@"); - var localPart = toAddr.slice(0, atIdx); - var domain = toAddr.slice(atIdx + 1); - localPart = localPart.replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, toUpperCase).replace(NOT_LOCAL_PART, URI.pctEncChar); - if (typeof punycode !== "undefined") { - //convert IDN via punycode - try { - domain = (!options.iri ? punycode.toASCII(URI.unescapeComponent(domain, options).toLowerCase()) : punycode.toUnicode(domain)); - } - catch (e) { - components.error = components.error || "Email address's domain name can not be converted to " + (!options.iri ? "ASCII" : "Unicode") + " via punycode: " + e; - } - } - else { - domain = domain.replace(PCT_ENCODED, decodeUnreserved).toLowerCase().replace(PCT_ENCODED, toUpperCase).replace(NOT_DOMAIN, URI.pctEncChar); - } - to[x] = localPart + "@" + domain; - } - components.path = to.join(","); - } - var headers = components.headers = components.headers || {}; - if (components.subject) - headers["subject"] = components.subject; - if (components.body) - headers["body"] = components.body; - var fields = []; - for (var name_1 in headers) { - if (headers[name_1] !== O[name_1]) { - fields.push(name_1.replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, toUpperCase).replace(NOT_HFNAME, URI.pctEncChar) + - "=" + - headers[name_1].replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, toUpperCase).replace(NOT_HFVALUE, URI.pctEncChar)); - } - } - if (fields.length) { - components.query = fields.join("&"); - } - return components; - } - }; -})(); - -},{"../punycode":18,"../uri":23}],22:[function(require,module,exports){ -/// -if (typeof COMPILED === "undefined" && typeof URI === "undefined" && typeof require === "function") - var URI = require("../uri"); -(function () { - var pctEncChar = URI.pctEncChar, NID$ = "(?:[0-9A-Za-z][0-9A-Za-z\\-]{1,31})", PCT_ENCODED$ = "(?:\\%[0-9A-Fa-f]{2})", TRANS$$ = "[0-9A-Za-z\\(\\)\\+\\,\\-\\.\\:\\=\\@\\;\\$\\_\\!\\*\\'\\/\\?\\#]", NSS$ = "(?:(?:" + PCT_ENCODED$ + "|" + TRANS$$ + ")+)", URN_SCHEME = new RegExp("^urn\\:(" + NID$ + ")$"), URN_PATH = new RegExp("^(" + NID$ + ")\\:(" + NSS$ + ")$"), URN_PARSE = /^([^\:]+)\:(.*)/, URN_EXCLUDED = /[\x00-\x20\\\"\&\<\>\[\]\^\`\{\|\}\~\x7F-\xFF]/g, UUID = /^[0-9A-Fa-f]{8}(?:\-[0-9A-Fa-f]{4}){3}\-[0-9A-Fa-f]{12}$/; - //RFC 2141 - URI.SCHEMES["urn"] = { - parse: function (components, options) { - var matches = components.path.match(URN_PATH), scheme, schemeHandler; - if (!matches) { - if (!options.tolerant) { - components.error = components.error || "URN is not strictly valid."; - } - matches = components.path.match(URN_PARSE); - } - if (matches) { - scheme = "urn:" + matches[1].toLowerCase(); - schemeHandler = URI.SCHEMES[scheme]; - //in order to serialize properly, - //every URN must have a serializer that calls the URN serializer - if (!schemeHandler) { - //create fake scheme handler - schemeHandler = URI.SCHEMES[scheme] = { - parse: function (components, options) { - return components; - }, - serialize: URI.SCHEMES["urn"].serialize - }; - } - components.scheme = scheme; - components.path = matches[2]; - components = schemeHandler.parse(components, options); - } - else { - components.error = components.error || "URN can not be parsed."; - } - return components; - }, - serialize: function (components, options) { - var scheme = components.scheme || options.scheme, matches; - if (scheme && scheme !== "urn") { - var matches = scheme.match(URN_SCHEME); - if (!matches) { - matches = ["urn:" + scheme, scheme]; - } - components.scheme = "urn"; - components.path = matches[1] + ":" + (components.path ? components.path.replace(URN_EXCLUDED, pctEncChar) : ""); - } - return components; - } - }; - //RFC 4122 - URI.SCHEMES["urn:uuid"] = { - parse: function (components, options) { - if (!options.tolerant && (!components.path || !components.path.match(UUID))) { - components.error = components.error || "UUID is not valid."; - } - return components; - }, - serialize: function (components, options) { - //ensure UUID is valid - if (!options.tolerant && (!components.path || !components.path.match(UUID))) { - //invalid UUIDs can not have this scheme - components.scheme = undefined; - } - else { - //normalize UUID - components.path = (components.path || "").toLowerCase(); - } - return URI.SCHEMES["urn"].serialize(components, options); - } - }; -}()); - -},{"../uri":23}],23:[function(require,module,exports){ -/** - * URI.js - * - * @fileoverview An RFC 3986 compliant, scheme extendable URI parsing/validating/resolving library for JavaScript. - * @author Gary Court - * @version 2.0.0 - * @see http://github.com/garycourt/uri-js - * @license URI.js v2.0.0 (c) 2011 Gary Court. License: http://github.com/garycourt/uri-js - */ -/** - * Copyright 2011 Gary Court. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY GARY COURT ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARY COURT OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of Gary Court. - */ -/// -/// -/** - * Compiler switch for indicating code is compiled - * @define {boolean} - */ -var COMPILED = false; -/** - * Compiler switch for supporting IRI URIs - * @define {boolean} - */ -var URI__IRI_SUPPORT = true; -/** - * Compiler switch for supporting URI validation - * @define {boolean} - */ -var URI__VALIDATE_SUPPORT = true; -var URI = (function () { - function merge() { - var sets = []; - for (var _i = 0; _i < arguments.length; _i++) { - sets[_i - 0] = arguments[_i]; - } - if (sets.length > 1) { - sets[0] = sets[0].slice(0, -1); - var xl = sets.length - 1; - for (var x = 1; x < xl; ++x) { - sets[x] = sets[x].slice(1, -1); - } - sets[xl] = sets[xl].slice(1); - return sets.join(''); - } - else { - return sets[0]; - } - } - function subexp(str) { - return "(?:" + str + ")"; - } - function buildExps(isIRI) { - var ALPHA$$ = "[A-Za-z]", CR$ = "[\\x0D]", DIGIT$$ = "[0-9]", DQUOTE$$ = "[\\x22]", HEXDIG$$ = merge(DIGIT$$, "[A-Fa-f]"), LF$$ = "[\\x0A]", SP$$ = "[\\x20]", PCT_ENCODED$ = subexp(subexp("%[EFef]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + subexp("%[89A-Fa-f]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + subexp("%" + HEXDIG$$ + HEXDIG$$)), GEN_DELIMS$$ = "[\\:\\/\\?\\#\\[\\]\\@]", SUB_DELIMS$$ = "[\\!\\$\\&\\'\\(\\)\\*\\+\\,\\;\\=]", RESERVED$$ = merge(GEN_DELIMS$$, SUB_DELIMS$$), UCSCHAR$$ = isIRI ? "[\\xA0-\\u200D\\u2010-\\u2029\\u202F-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]" : "[]", IPRIVATE$$ = isIRI ? "[\\uE000-\\uF8FF]" : "[]", UNRESERVED$$ = merge(ALPHA$$, DIGIT$$, "[\\-\\.\\_\\~]", UCSCHAR$$), SCHEME$ = subexp(ALPHA$$ + merge(ALPHA$$, DIGIT$$, "[\\+\\-\\.]") + "*"), USERINFO$ = subexp(subexp(PCT_ENCODED$ + "|" + merge(UNRESERVED$$, SUB_DELIMS$$, "[\\:]")) + "*"), DEC_OCTET$ = subexp(subexp("25[0-5]") + "|" + subexp("2[0-4]" + DIGIT$$) + "|" + subexp("1" + DIGIT$$ + DIGIT$$) + "|" + subexp("[1-9]" + DIGIT$$) + "|" + DIGIT$$), IPV4ADDRESS$ = subexp(DEC_OCTET$ + "\\." + DEC_OCTET$ + "\\." + DEC_OCTET$ + "\\." + DEC_OCTET$), H16$ = subexp(HEXDIG$$ + "{1,4}"), LS32$ = subexp(subexp(H16$ + "\\:" + H16$) + "|" + IPV4ADDRESS$), IPV6ADDRESS$ = subexp(merge(UNRESERVED$$, SUB_DELIMS$$, "[\\:]") + "+"), IPVFUTURE$ = subexp("v" + HEXDIG$$ + "+\\." + merge(UNRESERVED$$, SUB_DELIMS$$, "[\\:]") + "+"), IP_LITERAL$ = subexp("\\[" + subexp(IPV6ADDRESS$ + "|" + IPVFUTURE$) + "\\]"), REG_NAME$ = subexp(subexp(PCT_ENCODED$ + "|" + merge(UNRESERVED$$, SUB_DELIMS$$)) + "*"), HOST$ = subexp(IP_LITERAL$ + "|" + IPV4ADDRESS$ + "(?!" + REG_NAME$ + ")" + "|" + REG_NAME$), PORT$ = subexp(DIGIT$$ + "*"), AUTHORITY$ = subexp(subexp(USERINFO$ + "@") + "?" + HOST$ + subexp("\\:" + PORT$) + "?"), PCHAR$ = subexp(PCT_ENCODED$ + "|" + merge(UNRESERVED$$, SUB_DELIMS$$, "[\\:\\@]")), SEGMENT$ = subexp(PCHAR$ + "*"), SEGMENT_NZ$ = subexp(PCHAR$ + "+"), SEGMENT_NZ_NC$ = subexp(subexp(PCT_ENCODED$ + "|" + merge(UNRESERVED$$, SUB_DELIMS$$, "[\\@]")) + "+"), PATH_ABEMPTY$ = subexp(subexp("\\/" + SEGMENT$) + "*"), PATH_ABSOLUTE$ = subexp("\\/" + subexp(SEGMENT_NZ$ + PATH_ABEMPTY$) + "?"), PATH_NOSCHEME$ = subexp(SEGMENT_NZ_NC$ + PATH_ABEMPTY$), PATH_ROOTLESS$ = subexp(SEGMENT_NZ$ + PATH_ABEMPTY$), PATH_EMPTY$ = "(?!" + PCHAR$ + ")", PATH$ = subexp(PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_NOSCHEME$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$), QUERY$ = subexp(subexp(PCHAR$ + "|" + merge("[\\/\\?]", IPRIVATE$$)) + "*"), FRAGMENT$ = subexp(subexp(PCHAR$ + "|[\\/\\?]") + "*"), HIER_PART$ = subexp(subexp("\\/\\/" + AUTHORITY$ + PATH_ABEMPTY$) + "|" + PATH_ABSOLUTE$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$), URI$ = subexp(SCHEME$ + "\\:" + HIER_PART$ + subexp("\\?" + QUERY$) + "?" + subexp("\\#" + FRAGMENT$) + "?"), RELATIVE_PART$ = subexp(subexp("\\/\\/" + AUTHORITY$ + PATH_ABEMPTY$) + "|" + PATH_ABSOLUTE$ + "|" + PATH_NOSCHEME$ + "|" + PATH_EMPTY$), RELATIVE$ = subexp(RELATIVE_PART$ + subexp("\\?" + QUERY$) + "?" + subexp("\\#" + FRAGMENT$) + "?"), URI_REFERENCE$ = subexp(URI$ + "|" + RELATIVE$), ABSOLUTE_URI$ = subexp(SCHEME$ + "\\:" + HIER_PART$ + subexp("\\?" + QUERY$) + "?"), GENERIC_REF$ = "^(" + SCHEME$ + ")\\:" + subexp(subexp("\\/\\/(" + subexp("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + subexp("\\:(" + PORT$ + ")") + "?)") + "?(" + PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$ + ")") + subexp("\\?(" + QUERY$ + ")") + "?" + subexp("\\#(" + FRAGMENT$ + ")") + "?$", RELATIVE_REF$ = "^(){0}" + subexp(subexp("\\/\\/(" + subexp("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + subexp("\\:(" + PORT$ + ")") + "?)") + "?(" + PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_NOSCHEME$ + "|" + PATH_EMPTY$ + ")") + subexp("\\?(" + QUERY$ + ")") + "?" + subexp("\\#(" + FRAGMENT$ + ")") + "?$", ABSOLUTE_REF$ = "^(" + SCHEME$ + ")\\:" + subexp(subexp("\\/\\/(" + subexp("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + subexp("\\:(" + PORT$ + ")") + "?)") + "?(" + PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$ + ")") + subexp("\\?(" + QUERY$ + ")") + "?$", SAMEDOC_REF$ = "^" + subexp("\\#(" + FRAGMENT$ + ")") + "?$", AUTHORITY_REF$ = "^" + subexp("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + subexp("\\:(" + PORT$ + ")") + "?$"; - return { - URI_REF: URI__VALIDATE_SUPPORT && new RegExp("(" + GENERIC_REF$ + ")|(" + RELATIVE_REF$ + ")"), - NOT_SCHEME: new RegExp(merge("[^]", ALPHA$$, DIGIT$$, "[\\+\\-\\.]"), "g"), - NOT_USERINFO: new RegExp(merge("[^\\%\\:]", UNRESERVED$$, SUB_DELIMS$$), "g"), - NOT_HOST: new RegExp(merge("[^\\%]", UNRESERVED$$, SUB_DELIMS$$), "g"), - NOT_PATH: new RegExp(merge("[^\\%\\/\\:\\@]", UNRESERVED$$, SUB_DELIMS$$), "g"), - NOT_PATH_NOSCHEME: new RegExp(merge("[^\\%\\/\\@]", UNRESERVED$$, SUB_DELIMS$$), "g"), - NOT_QUERY: new RegExp(merge("[^\\%]", UNRESERVED$$, SUB_DELIMS$$, "[\\:\\@\\/\\?]", IPRIVATE$$), "g"), - NOT_FRAGMENT: new RegExp(merge("[^\\%]", UNRESERVED$$, SUB_DELIMS$$, "[\\:\\@\\/\\?]"), "g"), - ESCAPE: new RegExp(merge("[^]", UNRESERVED$$, SUB_DELIMS$$), "g"), - UNRESERVED: new RegExp(UNRESERVED$$, "g"), - OTHER_CHARS: new RegExp(merge("[^\\%]", UNRESERVED$$, RESERVED$$), "g"), - PCT_ENCODED: new RegExp(PCT_ENCODED$, "g") - }; - } - var URI_PROTOCOL = buildExps(false), IRI_PROTOCOL = URI__IRI_SUPPORT ? buildExps(true) : undefined, URI_PARSE = /^(?:([^:\/?#]+):)?(?:\/\/((?:([^\/?#@]*)@)?([^\/?#:]*)(?:\:(\d*))?))?([^?#]*)(?:\?([^#]*))?(?:#((?:.|\n)*))?/i, RDS1 = /^\.\.?\//, RDS2 = /^\/\.(\/|$)/, RDS3 = /^\/\.\.(\/|$)/, RDS4 = /^\.\.?$/, RDS5 = /^\/?(?:.|\n)*?(?=\/|$)/, NO_MATCH_IS_UNDEFINED = ("").match(/(){0}/)[1] === undefined; - function pctEncChar(chr) { - var c = chr.charCodeAt(0), e; - if (c < 16) - e = "%0" + c.toString(16).toUpperCase(); - else if (c < 128) - e = "%" + c.toString(16).toUpperCase(); - else if (c < 2048) - e = "%" + ((c >> 6) | 192).toString(16).toUpperCase() + "%" + ((c & 63) | 128).toString(16).toUpperCase(); - else - e = "%" + ((c >> 12) | 224).toString(16).toUpperCase() + "%" + (((c >> 6) & 63) | 128).toString(16).toUpperCase() + "%" + ((c & 63) | 128).toString(16).toUpperCase(); - return e; - } - function pctDecChars(str) { - var newStr = "", i = 0, il = str.length, c, c2, c3; - while (i < il) { - c = parseInt(str.substr(i + 1, 2), 16); - if (c < 128) { - newStr += String.fromCharCode(c); - i += 3; - } - else if (c >= 194 && c < 224) { - if ((il - i) >= 6) { - c2 = parseInt(str.substr(i + 4, 2), 16); - newStr += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); - } - else { - newStr += str.substr(i, 6); - } - i += 6; - } - else if (c >= 224) { - if ((il - i) >= 9) { - c2 = parseInt(str.substr(i + 4, 2), 16); - c3 = parseInt(str.substr(i + 7, 2), 16); - newStr += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); - } - else { - newStr += str.substr(i, 9); - } - i += 9; - } - else { - newStr += str.substr(i, 3); - i += 3; - } - } - return newStr; - } - function typeOf(o) { - return o === undefined ? "undefined" : (o === null ? "null" : Object.prototype.toString.call(o).split(" ").pop().split("]").shift().toLowerCase()); - } - function toUpperCase(str) { - return str.toUpperCase(); - } - var SCHEMES = {}; - function _normalizeComponentEncoding(components, protocol) { - function decodeUnreserved(str) { - var decStr = pctDecChars(str); - return (!decStr.match(protocol.UNRESERVED) ? str : decStr); - } - if (components.scheme) - components.scheme = String(components.scheme).replace(protocol.PCT_ENCODED, decodeUnreserved).toLowerCase().replace(protocol.NOT_SCHEME, ""); - if (components.userinfo !== undefined) - components.userinfo = String(components.userinfo).replace(protocol.PCT_ENCODED, decodeUnreserved).replace(protocol.NOT_USERINFO, pctEncChar).replace(protocol.PCT_ENCODED, toUpperCase); - if (components.host !== undefined) - components.host = String(components.host).replace(protocol.PCT_ENCODED, decodeUnreserved).toLowerCase().replace(protocol.NOT_HOST, pctEncChar).replace(protocol.PCT_ENCODED, toUpperCase); - if (components.path !== undefined) - components.path = String(components.path).replace(protocol.PCT_ENCODED, decodeUnreserved).replace((components.scheme ? protocol.NOT_PATH : protocol.NOT_PATH_NOSCHEME), pctEncChar).replace(protocol.PCT_ENCODED, toUpperCase); - if (components.query !== undefined) - components.query = String(components.query).replace(protocol.PCT_ENCODED, decodeUnreserved).replace(protocol.NOT_QUERY, pctEncChar).replace(protocol.PCT_ENCODED, toUpperCase); - if (components.fragment !== undefined) - components.fragment = String(components.fragment).replace(protocol.PCT_ENCODED, decodeUnreserved).replace(protocol.NOT_FRAGMENT, pctEncChar).replace(protocol.PCT_ENCODED, toUpperCase); - return components; - } - ; - function parse(uriString, options) { - if (options === void 0) { options = {}; } - var protocol = (URI__IRI_SUPPORT && options.iri !== false ? IRI_PROTOCOL : URI_PROTOCOL), matches, parseError = false, components = {}, schemeHandler; - if (options.reference === "suffix") - uriString = (options.scheme ? options.scheme + ":" : "") + "//" + uriString; - if (URI__VALIDATE_SUPPORT) { - matches = uriString.match(protocol.URI_REF); - if (matches) { - if (matches[1]) { - //generic URI - matches = matches.slice(1, 10); - } - else { - //relative URI - matches = matches.slice(10, 19); - } - } - if (!matches) { - parseError = true; - if (!options.tolerant) - components.error = components.error || "URI is not strictly valid."; - matches = uriString.match(URI_PARSE); - } - } - else { - matches = uriString.match(URI_PARSE); - } - if (matches) { - if (NO_MATCH_IS_UNDEFINED) { - //store each component - components.scheme = matches[1]; - //components.authority = matches[2]; - components.userinfo = matches[3]; - components.host = matches[4]; - components.port = parseInt(matches[5], 10); - components.path = matches[6] || ""; - components.query = matches[7]; - components.fragment = matches[8]; - //fix port number - if (isNaN(components.port)) { - components.port = matches[5]; - } - } - else { - //store each component - components.scheme = matches[1] || undefined; - //components.authority = (uriString.indexOf("//") !== -1 ? matches[2] : undefined); - components.userinfo = (uriString.indexOf("@") !== -1 ? matches[3] : undefined); - components.host = (uriString.indexOf("//") !== -1 ? matches[4] : undefined); - components.port = parseInt(matches[5], 10); - components.path = matches[6] || ""; - components.query = (uriString.indexOf("?") !== -1 ? matches[7] : undefined); - components.fragment = (uriString.indexOf("#") !== -1 ? matches[8] : undefined); - //fix port number - if (isNaN(components.port)) { - components.port = (uriString.match(/\/\/(?:.|\n)*\:(?:\/|\?|\#|$)/) ? matches[4] : undefined); - } - } - //determine reference type - if (components.scheme === undefined && components.userinfo === undefined && components.host === undefined && components.port === undefined && !components.path && components.query === undefined) { - components.reference = "same-document"; - } - else if (components.scheme === undefined) { - components.reference = "relative"; - } - else if (components.fragment === undefined) { - components.reference = "absolute"; - } - else { - components.reference = "uri"; - } - //check for reference errors - if (options.reference && options.reference !== "suffix" && options.reference !== components.reference) { - components.error = components.error || "URI is not a " + options.reference + " reference."; - } - //find scheme handler - schemeHandler = SCHEMES[(options.scheme || components.scheme || "").toLowerCase()]; - //check if scheme can't handle IRIs - if (URI__IRI_SUPPORT && typeof punycode !== "undefined" && !options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport)) { - //if host component is a domain name - if (components.host && (options.domainHost || (schemeHandler && schemeHandler.domainHost))) { - //convert Unicode IDN -> ASCII IDN - try { - components.host = punycode.toASCII(components.host.replace(protocol.PCT_ENCODED, pctDecChars).toLowerCase()); - } - catch (e) { - components.error = components.error || "Host's domain name can not be converted to ASCII via punycode: " + e; - } - } - //convert IRI -> URI - _normalizeComponentEncoding(components, URI_PROTOCOL); - } - else { - //normalize encodings - _normalizeComponentEncoding(components, protocol); - } - //perform scheme specific parsing - if (schemeHandler && schemeHandler.parse) { - schemeHandler.parse(components, options); - } - } - else { - parseError = true; - components.error = components.error || "URI can not be parsed."; - } - return components; - } - ; - function _recomposeAuthority(components, options) { - var uriTokens = []; - if (components.userinfo !== undefined) { - uriTokens.push(components.userinfo); - uriTokens.push("@"); - } - if (components.host !== undefined) { - uriTokens.push(components.host); - } - if (typeof components.port === "number") { - uriTokens.push(":"); - uriTokens.push(components.port.toString(10)); - } - return uriTokens.length ? uriTokens.join("") : undefined; - } - ; - function removeDotSegments(input) { - var output = [], s; - while (input.length) { - if (input.match(RDS1)) { - input = input.replace(RDS1, ""); - } - else if (input.match(RDS2)) { - input = input.replace(RDS2, "/"); - } - else if (input.match(RDS3)) { - input = input.replace(RDS3, "/"); - output.pop(); - } - else if (input === "." || input === "..") { - input = ""; - } - else { - s = input.match(RDS5)[0]; - input = input.slice(s.length); - output.push(s); - } - } - return output.join(""); - } - ; - function serialize(components, options) { - if (options === void 0) { options = {}; } - var protocol = (URI__IRI_SUPPORT && options.iri ? IRI_PROTOCOL : URI_PROTOCOL), uriTokens = [], schemeHandler, authority, s; - //find scheme handler - schemeHandler = SCHEMES[(options.scheme || components.scheme || "").toLowerCase()]; - //perform scheme specific serialization - if (schemeHandler && schemeHandler.serialize) - schemeHandler.serialize(components, options); - //if host component is a domain name - if (URI__IRI_SUPPORT && typeof punycode !== "undefined" && components.host && (options.domainHost || (schemeHandler && schemeHandler.domainHost))) { - //convert IDN via punycode - try { - components.host = (!options.iri ? punycode.toASCII(components.host.replace(protocol.PCT_ENCODED, pctDecChars).toLowerCase()) : punycode.toUnicode(components.host)); - } - catch (e) { - components.error = components.error || "Host's domain name can not be converted to " + (!options.iri ? "ASCII" : "Unicode") + " via punycode: " + e; - } - } - //normalize encoding - _normalizeComponentEncoding(components, protocol); - if (options.reference !== "suffix" && components.scheme) { - uriTokens.push(components.scheme); - uriTokens.push(":"); - } - authority = _recomposeAuthority(components, options); - if (authority !== undefined) { - if (options.reference !== "suffix") { - uriTokens.push("//"); - } - uriTokens.push(authority); - if (components.path && components.path.charAt(0) !== "/") { - uriTokens.push("/"); - } - } - if (components.path !== undefined) { - s = components.path; - if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) { - s = removeDotSegments(s); - } - if (authority === undefined) { - s = s.replace(/^\/\//, "/%2F"); //don't allow the path to start with "//" - } - uriTokens.push(s); - } - if (components.query !== undefined) { - uriTokens.push("?"); - uriTokens.push(components.query); - } - if (components.fragment !== undefined) { - uriTokens.push("#"); - uriTokens.push(components.fragment); - } - return uriTokens.join(''); //merge tokens into a string - } - ; - function resolveComponents(base, relative, options, skipNormalization) { - if (options === void 0) { options = {}; } - var target = {}; - if (!skipNormalization) { - base = parse(serialize(base, options), options); //normalize base components - relative = parse(serialize(relative, options), options); //normalize relative components - } - options = options || {}; - if (!options.tolerant && relative.scheme) { - target.scheme = relative.scheme; - //target.authority = relative.authority; - target.userinfo = relative.userinfo; - target.host = relative.host; - target.port = relative.port; - target.path = removeDotSegments(relative.path); - target.query = relative.query; - } - else { - if (relative.userinfo !== undefined || relative.host !== undefined || relative.port !== undefined) { - //target.authority = relative.authority; - target.userinfo = relative.userinfo; - target.host = relative.host; - target.port = relative.port; - target.path = removeDotSegments(relative.path); - target.query = relative.query; - } - else { - if (!relative.path) { - target.path = base.path; - if (relative.query !== undefined) { - target.query = relative.query; - } - else { - target.query = base.query; - } - } - else { - if (relative.path.charAt(0) === "/") { - target.path = removeDotSegments(relative.path); - } - else { - if ((base.userinfo !== undefined || base.host !== undefined || base.port !== undefined) && !base.path) { - target.path = "/" + relative.path; - } - else if (!base.path) { - target.path = relative.path; - } - else { - target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative.path; - } - target.path = removeDotSegments(target.path); - } - target.query = relative.query; - } - //target.authority = base.authority; - target.userinfo = base.userinfo; - target.host = base.host; - target.port = base.port; - } - target.scheme = base.scheme; - } - target.fragment = relative.fragment; - return target; - } - ; - function resolve(baseURI, relativeURI, options) { - return serialize(resolveComponents(parse(baseURI, options), parse(relativeURI, options), options, true), options); - } - ; - function normalize(uri, options) { - if (typeof uri === "string") { - uri = serialize(parse(uri, options), options); - } - else if (typeOf(uri) === "object") { - uri = parse(serialize(uri, options), options); - } - return uri; - } - ; - function equal(uriA, uriB, options) { - if (typeof uriA === "string") { - uriA = serialize(parse(uriA, options), options); - } - else if (typeOf(uriA) === "object") { - uriA = serialize(uriA, options); - } - if (typeof uriB === "string") { - uriB = serialize(parse(uriB, options), options); - } - else if (typeOf(uriB) === "object") { - uriB = serialize(uriB, options); - } - return uriA === uriB; - } - ; - function escapeComponent(str, options) { - return str && str.toString().replace((!URI__IRI_SUPPORT || !options || !options.iri ? URI_PROTOCOL.ESCAPE : IRI_PROTOCOL.ESCAPE), pctEncChar); - } - ; - function unescapeComponent(str, options) { - return str && str.toString().replace((!URI__IRI_SUPPORT || !options || !options.iri ? URI_PROTOCOL.PCT_ENCODED : IRI_PROTOCOL.PCT_ENCODED), pctDecChars); - } - ; - return { - IRI_SUPPORT: URI__IRI_SUPPORT, - VALIDATE_SUPPORT: URI__VALIDATE_SUPPORT, - pctEncChar: pctEncChar, - pctDecChars: pctDecChars, - SCHEMES: SCHEMES, - parse: parse, - _recomposeAuthority: _recomposeAuthority, - removeDotSegments: removeDotSegments, - serialize: serialize, - resolveComponents: resolveComponents, - resolve: resolve, - normalize: normalize, - equal: equal, - escapeComponent: escapeComponent, - unescapeComponent: unescapeComponent - }; -})(); -if (!COMPILED && typeof module !== "undefined" && typeof require === "function") { - var punycode = require("./punycode"); - module.exports = URI; - require("./schemes"); -} - -},{"./punycode":18,"./schemes":19}]},{},[1])(1) -}); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJpbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9jb21wb25lbnQtZW1pdHRlci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9uYXRpdmUtcHJvbWlzZS1vbmx5L2xpYi9ucG8uc3JjLmpzIiwibm9kZV9tb2R1bGVzL3BhdGgtYnJvd3NlcmlmeS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9wYXRoLWxvYWRlci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9wYXRoLWxvYWRlci9saWIvbG9hZGVycy9maWxlLWJyb3dzZXIuanMiLCJub2RlX21vZHVsZXMvcGF0aC1sb2FkZXIvbGliL2xvYWRlcnMvaHR0cC5qcyIsIm5vZGVfbW9kdWxlcy9wcm9jZXNzL2Jyb3dzZXIuanMiLCJub2RlX21vZHVsZXMvcXVlcnlzdHJpbmctZXMzL2RlY29kZS5qcyIsIm5vZGVfbW9kdWxlcy9xdWVyeXN0cmluZy1lczMvZW5jb2RlLmpzIiwibm9kZV9tb2R1bGVzL3F1ZXJ5c3RyaW5nLWVzMy9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9yZWR1Y2UtY29tcG9uZW50L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3NsYXNoL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3N1cGVyYWdlbnQvbGliL2NsaWVudC5qcyIsIm5vZGVfbW9kdWxlcy9zdXBlcmFnZW50L2xpYi9pcy1vYmplY3QuanMiLCJub2RlX21vZHVsZXMvc3VwZXJhZ2VudC9saWIvcmVxdWVzdC1iYXNlLmpzIiwibm9kZV9tb2R1bGVzL3N1cGVyYWdlbnQvbGliL3JlcXVlc3QuanMiLCJub2RlX21vZHVsZXMvdXJpLWpzL2J1aWxkL3B1bnljb2RlLmpzIiwibm9kZV9tb2R1bGVzL3VyaS1qcy9idWlsZC9zY2hlbWVzLmpzIiwibm9kZV9tb2R1bGVzL3VyaS1qcy9idWlsZC9zY2hlbWVzL2h0dHAuanMiLCJub2RlX21vZHVsZXMvdXJpLWpzL2J1aWxkL3NjaGVtZXMvbWFpbHRvLmpzIiwibm9kZV9tb2R1bGVzL3VyaS1qcy9idWlsZC9zY2hlbWVzL3Vybi5qcyIsIm5vZGVfbW9kdWxlcy91cmktanMvYnVpbGQvdXJpLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyMkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDaktBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDclhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ2hPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcmpDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiLypcbiAqIFRoZSBNSVQgTGljZW5zZSAoTUlUKVxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxNCBKZXJlbXkgV2hpdGxvY2tcbiAqXG4gKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4gKiBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4gKiBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG4gKiB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4gKiBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbiAqIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4gKlxuICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbiAqIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICpcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1JcbiAqIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuICogRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4gKiBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4gKiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuICogT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuICogVEhFIFNPRlRXQVJFLlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBWYXJpb3VzIHV0aWxpdGllcyBmb3IgSlNPTiBSZWZlcmVuY2VzICooaHR0cDovL3Rvb2xzLmlldGYub3JnL2h0bWwvZHJhZnQtcGJyeWFuLXp5cC1qc29uLXJlZi0wMykqIGFuZFxuICogSlNPTiBQb2ludGVycyAqKGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmM2OTAxKSouXG4gKlxuICogQG1vZHVsZSBKc29uUmVmc1xuICovXG5cbnZhciBwYXRoID0gcmVxdWlyZSgncGF0aCcpO1xudmFyIFBhdGhMb2FkZXIgPSByZXF1aXJlKCdwYXRoLWxvYWRlcicpO1xudmFyIHFzID0gcmVxdWlyZSgncXVlcnlzdHJpbmcnKTtcbnZhciBzbGFzaCA9IHJlcXVpcmUoJ3NsYXNoJyk7XG52YXIgVVJJID0gcmVxdWlyZSgndXJpLWpzJyk7XG5cbnZhciBiYWRQdHJUb2tlblJlZ2V4ID0gL34oPzpbXjAxXXwkKS9nO1xudmFyIHJlbW90ZUNhY2hlID0ge307XG52YXIgcmVtb3RlVHlwZXMgPSBbJ3JlbGF0aXZlJywgJ3JlbW90ZSddO1xudmFyIHJlbW90ZVVyaVR5cGVzID0gWydhYnNvbHV0ZScsICd1cmknXTtcbnZhciB1cmlEZXRhaWxzQ2FjaGUgPSB7fTtcblxuLy8gTG9hZCBwcm9taXNlcyBwb2x5ZmlsbCBpZiBuZWNlc3Nhcnlcbi8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuaWYgKHR5cGVvZiBQcm9taXNlID09PSAndW5kZWZpbmVkJykge1xuICByZXF1aXJlKCduYXRpdmUtcHJvbWlzZS1vbmx5Jyk7XG59XG5cbi8qIEludGVybmFsIEZ1bmN0aW9ucyAqL1xuXG4vLyBUaGlzIGlzIGEgdmVyeSBzaW1wbGlzdGljIGNsb25lIGZ1bmN0aW9uIHRoYXQgZG9lcyBub3QgdGFrZSBpbnRvIGFjY291bnQgbm9uLUpTT04gdHlwZXMuICBGb3IgdGhlc2UgdHlwZXMgdGhlXG4vLyBvcmlnaW5hbCB2YWx1ZSBpcyB1c2VkIGFzIHRoZSBjbG9uZS4gIFNvIHdoaWxlIGl0J3Mgbm90IGEgY29tcGxldGUgZGVlcCBjbG9uZSwgZm9yIHRoZSBuZWVkcyBvZiB0aGlzIHByb2plY3Rcbi8vIHRoaXMgc2hvdWxkIGJlIHN1ZmZpY2llbnQuXG5mdW5jdGlvbiBjbG9uZSAob2JqKSB7XG4gIHZhciBjbG9uZWQ7XG5cbiAgaWYgKGlzVHlwZShvYmosICdBcnJheScpKSB7XG4gICAgY2xvbmVkID0gW107XG5cbiAgICBvYmouZm9yRWFjaChmdW5jdGlvbiAodmFsdWUsIGluZGV4KSB7XG4gICAgICBjbG9uZWRbaW5kZXhdID0gY2xvbmUodmFsdWUpO1xuICAgIH0pO1xuICB9IGVsc2UgaWYgKGlzVHlwZShvYmosICdPYmplY3QnKSkge1xuICAgIGNsb25lZCA9IHt9O1xuXG4gICAgT2JqZWN0LmtleXMob2JqKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgIGNsb25lZFtrZXldID0gY2xvbmUob2JqW2tleV0pO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIGNsb25lZCA9IG9iajtcbiAgfVxuXG4gIHJldHVybiBjbG9uZWQ7XG59XG5cbmZ1bmN0aW9uIGNvbWJpbmVRdWVyeVBhcmFtcyAocXMxLCBxczIpIHtcbiAgdmFyIGNvbWJpbmVkID0ge307XG5cbiAgZnVuY3Rpb24gbWVyZ2VRdWVyeVBhcmFtcyAob2JqKSB7XG4gICAgT2JqZWN0LmtleXMob2JqKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgIGNvbWJpbmVkW2tleV0gPSBvYmpba2V5XTtcbiAgICB9KTtcbiAgfVxuXG4gIG1lcmdlUXVlcnlQYXJhbXMocXMucGFyc2UocXMxIHx8ICcnKSk7XG4gIG1lcmdlUXVlcnlQYXJhbXMocXMucGFyc2UocXMyIHx8ICcnKSk7XG5cbiAgcmV0dXJuIE9iamVjdC5rZXlzKGNvbWJpbmVkKS5sZW5ndGggPT09IDAgPyB1bmRlZmluZWQgOiBxcy5zdHJpbmdpZnkoY29tYmluZWQpO1xufVxuXG5mdW5jdGlvbiBjb21iaW5lVVJJcyAodTEsIHUyKSB7XG4gIC8vIENvbnZlcnQgV2luZG93cyBwYXRoc1xuICBpZiAoaXNUeXBlKHUxLCAnU3RyaW5nJykpIHtcbiAgICB1MSA9IHNsYXNoKHUxKTtcbiAgfVxuXG4gIGlmIChpc1R5cGUodTIsICdTdHJpbmcnKSkge1xuICAgIHUyID0gc2xhc2godTIpO1xuICB9XG5cbiAgdmFyIHUyRGV0YWlscyA9IHBhcnNlVVJJKGlzVHlwZSh1MiwgJ1VuZGVmaW5lZCcpID8gJycgOiB1Mik7XG4gIHZhciB1MURldGFpbHM7XG4gIHZhciBjb21iaW5lZERldGFpbHM7XG5cbiAgaWYgKHJlbW90ZVVyaVR5cGVzLmluZGV4T2YodTJEZXRhaWxzLnJlZmVyZW5jZSkgPiAtMSkge1xuICAgIGNvbWJpbmVkRGV0YWlscyA9IHUyRGV0YWlscztcbiAgfSBlbHNlIHtcbiAgICB1MURldGFpbHMgPSBpc1R5cGUodTEsICdVbmRlZmluZWQnKSA/IHVuZGVmaW5lZCA6IHBhcnNlVVJJKHUxKTtcblxuICAgIGlmICghaXNUeXBlKHUxRGV0YWlscywgJ1VuZGVmaW5lZCcpKSB7XG4gICAgICBjb21iaW5lZERldGFpbHMgPSB1MURldGFpbHM7XG5cbiAgICAgIC8vIEpvaW4gdGhlIHBhdGhzXG4gICAgICBjb21iaW5lZERldGFpbHMucGF0aCA9IHNsYXNoKHBhdGguam9pbih1MURldGFpbHMucGF0aCwgdTJEZXRhaWxzLnBhdGgpKTtcblxuICAgICAgLy8gSm9pbiBxdWVyeSBwYXJhbWV0ZXJzXG4gICAgICBjb21iaW5lZERldGFpbHMucXVlcnkgPSBjb21iaW5lUXVlcnlQYXJhbXModTFEZXRhaWxzLnF1ZXJ5LCB1MkRldGFpbHMucXVlcnkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb21iaW5lZERldGFpbHMgPSB1MkRldGFpbHM7XG4gICAgfVxuICB9XG5cbiAgLy8gUmVtb3ZlIHRoZSBmcmFnbWVudFxuICBjb21iaW5lZERldGFpbHMuZnJhZ21lbnQgPSB1bmRlZmluZWQ7XG5cbiAgLy8gRm9yIHJlbGF0aXZlIFVSSXMsIGFkZCBiYWNrIHRoZSAnLi4nIHNpbmNlIGl0IHdhcyByZW1vdmVkIGFib3ZlXG4gIHJldHVybiAocmVtb3RlVXJpVHlwZXMuaW5kZXhPZihjb21iaW5lZERldGFpbHMucmVmZXJlbmNlKSA9PT0gLTEgJiZcbiAgICAgICAgICBjb21iaW5lZERldGFpbHMucGF0aC5pbmRleE9mKCcuLi8nKSA9PT0gMCA/ICcuLi8nIDogJycpICsgVVJJLnNlcmlhbGl6ZShjb21iaW5lZERldGFpbHMpO1xufVxuXG5mdW5jdGlvbiBmaW5kQW5jZXN0b3JzIChvYmosIHBhdGgpIHtcbiAgdmFyIGFuY2VzdG9ycyA9IFtdO1xuICB2YXIgbm9kZTtcblxuICBpZiAocGF0aC5sZW5ndGggPiAwKSB7XG4gICAgbm9kZSA9IG9iajtcblxuICAgIHBhdGguc2xpY2UoMCwgcGF0aC5sZW5ndGggLSAxKS5mb3JFYWNoKGZ1bmN0aW9uIChzZWcpIHtcbiAgICAgIGlmIChzZWcgaW4gbm9kZSkge1xuICAgICAgICBub2RlID0gbm9kZVtzZWddO1xuXG4gICAgICAgIGFuY2VzdG9ycy5wdXNoKG5vZGUpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIGFuY2VzdG9ycztcbn1cblxuZnVuY3Rpb24gcHJvY2Vzc1N1YkRvY3VtZW50IChtb2RlLCBkb2MsIHN1YkRvY1BhdGgsIHJlZkRldGFpbHMsIG9wdGlvbnMsIHBhcmVudHMsIHBhcmVudFB0cnMsIGFsbFJlZnMsIGluZGlyZWN0KSB7XG4gIHZhciByZWZWYWx1ZTtcbiAgdmFyIHJPcHRpb25zO1xuXG4gIGlmIChzdWJEb2NQYXRoLmxlbmd0aCA+IDApIHtcbiAgICB0cnkge1xuICAgICAgcmVmVmFsdWUgPSBmaW5kVmFsdWUoZG9jLCBzdWJEb2NQYXRoKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIC8vIFdlIG9ubHkgbWFyayBtaXNzaW5nIHJlbW90ZSByZWZlcmVuY2VzIGFzIG1pc3NpbmcgYmVjYXVzZSBsb2NhbCByZWZlcmVuY2VzIGNhbiBoYXZlIGRlZmVycmVkIHZhbHVlc1xuICAgICAgaWYgKG1vZGUgPT09ICdyZW1vdGUnKSB7XG4gICAgICAgIHJlZkRldGFpbHMuZXJyb3IgPSBlcnIubWVzc2FnZTtcbiAgICAgICAgcmVmRGV0YWlscy5taXNzaW5nID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgcmVmVmFsdWUgPSBkb2M7XG4gIH1cblxuICBpZiAoIWlzVHlwZShyZWZWYWx1ZSwgJ1VuZGVmaW5lZCcpKSB7XG4gICAgcmVmRGV0YWlscy52YWx1ZSA9IHJlZlZhbHVlO1xuICB9XG5cbiAgaWYgKGlzVHlwZShyZWZWYWx1ZSwgJ0FycmF5JykgfHwgaXNUeXBlKHJlZlZhbHVlLCAnT2JqZWN0JykpIHtcbiAgICByT3B0aW9ucyA9IGNsb25lKG9wdGlvbnMpO1xuXG4gICAgaWYgKG1vZGUgPT09ICdsb2NhbCcpIHtcbiAgICAgIGRlbGV0ZSByT3B0aW9ucy5zdWJEb2NQYXRoO1xuXG4gICAgICAvLyBUcmF2ZXJzZSB0aGUgZGVyZWZlcmVuY2VkIHZhbHVlXG4gICAgICBkb2MgPSByZWZWYWx1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgck9wdGlvbnMucmVsYXRpdmVCYXNlID0gcGF0aC5kaXJuYW1lKHBhcmVudHNbcGFyZW50cy5sZW5ndGggLSAxXSk7XG5cbiAgICAgIGlmIChzdWJEb2NQYXRoLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBkZWxldGUgck9wdGlvbnMuc3ViRG9jUGF0aDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJPcHRpb25zLnN1YkRvY1BhdGggPSBzdWJEb2NQYXRoO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmaW5kUmVmc1JlY3Vyc2l2ZShkb2MsIHJPcHRpb25zLCBwYXJlbnRzLCBwYXJlbnRQdHJzLCBhbGxSZWZzLCBpbmRpcmVjdCk7XG4gIH1cbn1cblxuLy8gU2hvdWxkIHRoaXMgYmUgaXRzIG93biBleHBvcnRlZCBBUEk/XG5mdW5jdGlvbiBmaW5kUmVmc1JlY3Vyc2l2ZSAob2JqLCBvcHRpb25zLCBwYXJlbnRzLCBwYXJlbnRQdHJzLCBhbGxSZWZzLCBpbmRpcmVjdCkge1xuICB2YXIgYWxsVGFza3MgPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgdmFyIHBhcmVudFBhdGggPSBwYXJlbnRQdHJzLmxlbmd0aCA/IHBhdGhGcm9tUHRyKHBhcmVudFB0cnNbcGFyZW50UHRycy5sZW5ndGggLSAxXSkgOiBbXTtcbiAgdmFyIHJlZnMgPSBmaW5kUmVmcyhvYmosIG9wdGlvbnMpO1xuICB2YXIgc3ViRG9jUGF0aCA9IG9wdGlvbnMuc3ViRG9jUGF0aCB8fCBbXTtcbiAgdmFyIHN1YkRvY1B0ciA9IHBhdGhUb1B0cihzdWJEb2NQYXRoKTtcbiAgdmFyIGFuY2VzdG9yUHRycyA9IFsnIyddO1xuXG4gIHBhcmVudHMuZm9yRWFjaChmdW5jdGlvbiAocGFyZW50LCBpbmRleCkge1xuICAgIGlmIChwYXJlbnQuY2hhckF0KDApICE9PSAnIycpIHtcbiAgICAgIGFuY2VzdG9yUHRycy5wdXNoKHBhcmVudFB0cnNbaW5kZXhdKTtcbiAgICB9XG4gIH0pO1xuXG4gIC8vIFJldmVyc2UgdGhlIG9yZGVyIHNvIHdlIHNlYXJjaCB0aGVtIGluIHRoZSBwcm9wZXIgb3JkZXJcbiAgYW5jZXN0b3JQdHJzLnJldmVyc2UoKTtcblxuICBpZiAoKHBhcmVudHNbcGFyZW50cy5sZW5ndGggLSAxXSB8fCAnJykuY2hhckF0KDApICE9PSAnIycpIHtcbiAgICBhbGxSZWZzLmRvY3VtZW50c1twYXRoVG9QdHIocGFyZW50UGF0aCldID0gb2JqO1xuICB9XG5cbiAgT2JqZWN0LmtleXMocmVmcykuZm9yRWFjaChmdW5jdGlvbiAocmVmUHRyKSB7XG4gICAgdmFyIHJlZkRldGFpbHMgPSByZWZzW3JlZlB0cl07XG4gICAgdmFyIGxvY2F0aW9uO1xuICAgIHZhciBwYXJlbnRJbmRleDtcbiAgICB2YXIgcmVmRnVsbFBhdGg7XG4gICAgdmFyIHJlZkZ1bGxQdHI7XG5cbiAgICAvLyBJZiB0aGVyZSBhcmUgbm8gcGFyZW50cywgdHJlYXQgdGhlIHJlZmVyZW5jZSBwb2ludGVyIGFzLWlzLiAgT3RoZXJ3aXNlLCB0aGUgcmVmZXJlbmNlIGlzIGEgcmVmZXJlbmNlIHdpdGhpbiBhXG4gICAgLy8gcmVtb3RlIGRvY3VtZW50IGFuZCBpdHMgc3ViIGRvY3VtZW50IHBhdGggcHJlZml4IG11c3QgYmUgcmVtb3ZlZC5cbiAgICBpZiAocGFyZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJlZkZ1bGxQYXRoID0gcGFyZW50UGF0aC5jb25jYXQocGF0aEZyb21QdHIocmVmUHRyKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlZkZ1bGxQYXRoID0gcGFyZW50UGF0aC5jb25jYXQocGF0aEZyb21QdHIocmVmUHRyKS5zbGljZShwYXJlbnRzLmxlbmd0aCA9PT0gMCA/IDAgOiBzdWJEb2NQYXRoLmxlbmd0aCkpO1xuICAgIH1cblxuICAgIHJlZkZ1bGxQdHIgPSBwYXRoVG9QdHIocmVmRnVsbFBhdGgpO1xuXG4gICAgLy8gSXQgaXMgcG9zc2libGUgdG8gcHJvY2VzcyB0aGUgc2FtZSByZWZlcmVuY2UgbW9yZSB0aGFuIG9uY2UgaW4gdGhlIGV2ZW50IG9mIGhpZXJhcmNoaWNhbCByZWZlcmVuY2VzIHNvIHdlIGF2b2lkXG4gICAgLy8gcHJvY2Vzc2luZyBhIHJlZmVyZW5jZSBpZiB3ZSd2ZSBhbHJlYWR5IGRvbmUgc28uXG4gICAgaWYgKCFpc1R5cGUoYWxsUmVmc1tyZWZGdWxsUHRyXSwgJ1VuZGVmaW5lZCcpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gUmVjb3JkIHRoZSByZWZlcmVuY2UgbWV0YWRhdGFcbiAgICBhbGxSZWZzLnJlZnNbcmVmRnVsbFB0cl0gPSByZWZzW3JlZlB0cl07XG5cbiAgICAvLyBEbyBub3QgcHJvY2VzcyBpbnZhbGlkIHJlZmVyZW5jZXNcbiAgICBpZiAoaXNUeXBlKHJlZkRldGFpbHMuZXJyb3IsICdVbmRlZmluZWQnKSAmJiByZWZEZXRhaWxzLnR5cGUgIT09ICdpbnZhbGlkJykge1xuICAgICAgaWYgKHJlbW90ZVR5cGVzLmluZGV4T2YocmVmRGV0YWlscy50eXBlKSA+IC0xKSB7XG4gICAgICAgIGxvY2F0aW9uID0gY29tYmluZVVSSXMob3B0aW9ucy5yZWxhdGl2ZUJhc2UsIHJlZkRldGFpbHMudXJpKTtcbiAgICAgICAgcGFyZW50SW5kZXggPSBwYXJlbnRzLmluZGV4T2YobG9jYXRpb24pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9jYXRpb24gPSByZWZEZXRhaWxzLnVyaTtcbiAgICAgICAgcGFyZW50SW5kZXggPSBwYXJlbnRQdHJzLmluZGV4T2YobG9jYXRpb24pO1xuICAgICAgfVxuXG4gICAgICAvLyBSZWNvcmQgYW5jZXN0b3IgcGF0aHNcbiAgICAgIHJlZkRldGFpbHMuYW5jZXN0b3JQdHJzID0gYW5jZXN0b3JQdHJzO1xuXG4gICAgICAvLyBSZWNvcmQgaWYgdGhlIHJlZmVyZW5jZSBpcyBpbmRpcmVjdCBiYXNlZCBvbiBpdHMgcGFyZW50XG4gICAgICByZWZEZXRhaWxzLmluZGlyZWN0ID0gaW5kaXJlY3Q7XG5cbiAgICAgIC8vIE9ubHkgcHJvY2VzcyBub24tY2lyY3VsYXIgcmVmZXJlbmNlcyBmdXJ0aGVyXG4gICAgICBpZiAocGFyZW50SW5kZXggPT09IC0xKSB7XG4gICAgICAgIGlmIChyZW1vdGVUeXBlcy5pbmRleE9mKHJlZkRldGFpbHMudHlwZSkgPiAtMSkge1xuICAgICAgICAgIGFsbFRhc2tzID0gYWxsVGFza3NcbiAgICAgICAgICAgIC50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGdldFJlbW90ZURvY3VtZW50KGxvY2F0aW9uLCBvcHRpb25zKVxuICAgICAgICAgICAgICAgIC50aGVuKGZ1bmN0aW9uIChkb2MpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBwcm9jZXNzU3ViRG9jdW1lbnQoJ3JlbW90ZScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNUeXBlKHJlZkRldGFpbHMudXJpRGV0YWlscy5mcmFnbWVudCwgJ1VuZGVmaW5lZCcpID9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbXSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aEZyb21QdHIoZGVjb2RlVVJJKHJlZkRldGFpbHMudXJpRGV0YWlscy5mcmFnbWVudCkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWZEZXRhaWxzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRzLmNvbmNhdChsb2NhdGlvbiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudFB0cnMuY29uY2F0KHJlZkZ1bGxQdHIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxSZWZzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRpcmVjdCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZnVuY3Rpb24gKGVycikge1xuICAgICAgICAgICAgICAgICAgcmVmRGV0YWlscy5lcnJvciA9IGVyci5tZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgcmVmRGV0YWlscy5taXNzaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmIChyZWZGdWxsUHRyLmluZGV4T2YobG9jYXRpb24gKyAnLycpICE9PSAwICYmIHJlZkZ1bGxQdHIgIT09IGxvY2F0aW9uICYmXG4gICAgICAgICAgICAgIHN1YkRvY1B0ci5pbmRleE9mKGxvY2F0aW9uICsgJy8nKSAhPT0gMCAmJiBzdWJEb2NQdHIgIT09IGxvY2F0aW9uKSB7XG4gICAgICAgICAgICBpZiAobG9jYXRpb24uaW5kZXhPZihzdWJEb2NQdHIgKyAnLycpICE9PSAwKSB7XG4gICAgICAgICAgICAgIGFsbFRhc2tzID0gYWxsVGFza3NcbiAgICAgICAgICAgICAgICAudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gcHJvY2Vzc1N1YkRvY3VtZW50KCdsb2NhbCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9iaixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aEZyb21QdHIobG9jYXRpb24pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWZEZXRhaWxzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRzLmNvbmNhdChsb2NhdGlvbiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudFB0cnMuY29uY2F0KHJlZkZ1bGxQdHIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxSZWZzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRpcmVjdCB8fCAobG9jYXRpb24uaW5kZXhPZihzdWJEb2NQdHIgKyAnLycpID09PSAtMSAmJiBsb2NhdGlvbiAhPT0gc3ViRG9jUHRyKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlZkRldGFpbHMuY2lyY3VsYXIgPSB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gTWFyayBzZWVuIGFuY2VzdG9ycyBhcyBjaXJjdWxhclxuICAgICAgICBwYXJlbnRQdHJzLnNsaWNlKHBhcmVudEluZGV4KS5mb3JFYWNoKGZ1bmN0aW9uIChwYXJlbnRQdHIpIHtcbiAgICAgICAgICBhbGxSZWZzLnJlZnNbcGFyZW50UHRyXS5jaXJjdWxhciA9IHRydWU7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJlZkRldGFpbHMuY2lyY3VsYXIgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgfSk7XG5cbiAgYWxsVGFza3MgPSBhbGxUYXNrc1xuICAgIC50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIElkZW50aWZ5IGluZGlyZWN0LCBsb2NhbCBjaXJjdWxhciByZWZlcmVuY2VzIChJc3N1ZSA4MilcbiAgICAgIHZhciBjaXJjdWxhcnMgPSBbXTtcbiAgICAgIHZhciBwcm9jZXNzZWRSZWZQdHJzID0gW107XG4gICAgICB2YXIgcHJvY2Vzc2VkUmVmcyA9IFtdO1xuXG4gICAgICBmdW5jdGlvbiB3YWxrUmVmcyAocGFyZW50UHRycywgcGFyZW50UmVmcywgcmVmUHRyLCByZWYpIHtcbiAgICAgICAgT2JqZWN0LmtleXMoYWxsUmVmcy5yZWZzKS5mb3JFYWNoKGZ1bmN0aW9uIChkUmVmUHRyKSB7XG4gICAgICAgICAgdmFyIGRSZWZEZXRhaWxzID0gYWxsUmVmcy5yZWZzW2RSZWZQdHJdO1xuXG4gICAgICAgICAgLy8gRG8gbm90IHByb2Nlc3MgYWxyZWFkeSBwcm9jZXNzZWQgcmVmZXJlbmNlcyBvciByZWZlcmVuY2VzIHRoYXQgYXJlIG5vdCBhIG5lc3RlZCByZWZlcmVuY2VzXG4gICAgICAgICAgaWYgKHByb2Nlc3NlZFJlZnMuaW5kZXhPZihyZWYpID09PSAtMSAmJiBwcm9jZXNzZWRSZWZQdHJzLmluZGV4T2YocmVmUHRyKSA9PT0gLTEgJiZcbiAgICAgICAgICAgICAgY2lyY3VsYXJzLmluZGV4T2YocmVmKSA9PT0gLTEgJiYgZFJlZlB0ciAhPT0gcmVmUHRyICYmIGRSZWZQdHIuaW5kZXhPZihyZWYgKyAnLycpID09PSAwKSB7XG4gICAgICAgICAgICBpZiAocGFyZW50UmVmcy5pbmRleE9mKHJlZikgPiAtMSkge1xuICAgICAgICAgICAgICBwYXJlbnRSZWZzLmZvckVhY2goZnVuY3Rpb24gKHBhcmVudFJlZikge1xuICAgICAgICAgICAgICAgIGlmIChjaXJjdWxhcnMuaW5kZXhPZihyZWYpID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgY2lyY3VsYXJzLnB1c2gocGFyZW50UmVmKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgd2Fsa1JlZnMocGFyZW50UHRycy5jb25jYXQocmVmUHRyKSwgcGFyZW50UmVmcy5jb25jYXQocmVmKSwgZFJlZlB0ciwgZFJlZkRldGFpbHMudXJpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcHJvY2Vzc2VkUmVmUHRycy5wdXNoKHJlZlB0cik7XG4gICAgICAgICAgICBwcm9jZXNzZWRSZWZzLnB1c2gocmVmKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBPYmplY3Qua2V5cyhhbGxSZWZzLnJlZnMpLmZvckVhY2goZnVuY3Rpb24gKHJlZlB0cikge1xuICAgICAgICB2YXIgcmVmRGV0YWlscyA9IGFsbFJlZnMucmVmc1tyZWZQdHJdO1xuXG4gICAgICAgIC8vIE9ubHkgcHJvY2VzcyBsb2NhbCwgbm9uLWNpcmN1bGFyIHJlZmVyZW5jZXNcbiAgICAgICAgaWYgKHJlZkRldGFpbHMudHlwZSA9PT0gJ2xvY2FsJyAmJiAhcmVmRGV0YWlscy5jaXJjdWxhciAmJiBjaXJjdWxhcnMuaW5kZXhPZihyZWZEZXRhaWxzLnVyaSkgPT09IC0xKSB7XG4gICAgICAgICAgd2Fsa1JlZnMoW10sIFtdLCByZWZQdHIsIHJlZkRldGFpbHMudXJpKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIE9iamVjdC5rZXlzKGFsbFJlZnMucmVmcykuZm9yRWFjaChmdW5jdGlvbiAocmVmUHRyKSB7XG4gICAgICAgIHZhciByZWZEZXRhaWxzID0gYWxsUmVmcy5yZWZzW3JlZlB0cl07XG5cbiAgICAgICAgaWYgKGNpcmN1bGFycy5pbmRleE9mKHJlZkRldGFpbHMudXJpKSA+IC0xKSB7XG4gICAgICAgICAgcmVmRGV0YWlscy5jaXJjdWxhciA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pXG4gICAgLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIGFsbFJlZnM7XG4gICAgfSk7XG5cbiAgcmV0dXJuIGFsbFRhc2tzO1xufVxuXG5mdW5jdGlvbiBmaW5kVmFsdWUgKG9iaiwgcGF0aCkge1xuICB2YXIgdmFsdWUgPSBvYmo7XG5cbiAgcGF0aC5mb3JFYWNoKGZ1bmN0aW9uIChzZWcpIHtcbiAgICBzZWcgPSBkZWNvZGVVUkkoc2VnKTtcblxuICAgIGlmIChzZWcgaW4gdmFsdWUpIHtcbiAgICAgIHZhbHVlID0gdmFsdWVbc2VnXTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgRXJyb3IoJ0pTT04gUG9pbnRlciBwb2ludHMgdG8gbWlzc2luZyBsb2NhdGlvbjogJyArIHBhdGhUb1B0cihwYXRoKSk7XG4gICAgfVxuICB9KTtcblxuICByZXR1cm4gdmFsdWU7XG59XG5cbmZ1bmN0aW9uIGdldEV4dHJhUmVmS2V5cyAocmVmKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhyZWYpLmZpbHRlcihmdW5jdGlvbiAoa2V5KSB7XG4gICAgcmV0dXJuIGtleSAhPT0gJyRyZWYnO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0UmVmVHlwZSAocmVmRGV0YWlscykge1xuICB2YXIgdHlwZTtcblxuICAvLyBDb252ZXJ0IHRoZSBVUkkgcmVmZXJlbmNlIHRvIG9uZSBvZiBvdXIgdHlwZXNcbiAgc3dpdGNoIChyZWZEZXRhaWxzLnVyaURldGFpbHMucmVmZXJlbmNlKSB7XG4gIGNhc2UgJ2Fic29sdXRlJzpcbiAgY2FzZSAndXJpJzpcbiAgICB0eXBlID0gJ3JlbW90ZSc7XG4gICAgYnJlYWs7XG4gIGNhc2UgJ3NhbWUtZG9jdW1lbnQnOlxuICAgIHR5cGUgPSAnbG9jYWwnO1xuICAgIGJyZWFrO1xuICBkZWZhdWx0OlxuICAgIHR5cGUgPSByZWZEZXRhaWxzLnVyaURldGFpbHMucmVmZXJlbmNlO1xuICB9XG5cbiAgcmV0dXJuIHR5cGU7XG59XG5cbmZ1bmN0aW9uIGdldFJlbW90ZURvY3VtZW50ICh1cmwsIG9wdGlvbnMpIHtcbiAgdmFyIGNhY2hlRW50cnkgPSByZW1vdGVDYWNoZVt1cmxdO1xuICB2YXIgYWxsVGFza3MgPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgdmFyIGxvYWRlck9wdGlvbnMgPSBjbG9uZShvcHRpb25zLmxvYWRlck9wdGlvbnMgfHwge30pO1xuXG4gIGlmIChpc1R5cGUoY2FjaGVFbnRyeSwgJ1VuZGVmaW5lZCcpKSB7XG4gICAgLy8gSWYgdGhlcmUgaXMgbm8gY29udGVudCBwcm9jZXNzb3IsIGRlZmF1bHQgdG8gcHJvY2Vzc2luZyB0aGUgcmF3IHJlc3BvbnNlIGFzIEpTT05cbiAgICBpZiAoaXNUeXBlKGxvYWRlck9wdGlvbnMucHJvY2Vzc0NvbnRlbnQsICdVbmRlZmluZWQnKSkge1xuICAgICAgbG9hZGVyT3B0aW9ucy5wcm9jZXNzQ29udGVudCA9IGZ1bmN0aW9uIChyZXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrKHVuZGVmaW5lZCwgSlNPTi5wYXJzZShyZXMudGV4dCkpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBBdHRlbXB0IHRvIGxvYWQgdGhlIHJlc291cmNlIHVzaW5nIHBhdGgtbG9hZGVyXG4gICAgYWxsVGFza3MgPSBQYXRoTG9hZGVyLmxvYWQoZGVjb2RlVVJJKHVybCksIGxvYWRlck9wdGlvbnMpO1xuXG4gICAgLy8gVXBkYXRlIHRoZSBjYWNoZVxuICAgIGFsbFRhc2tzID0gYWxsVGFza3NcbiAgICAgIC50aGVuKGZ1bmN0aW9uIChyZXMpIHtcbiAgICAgICAgcmVtb3RlQ2FjaGVbdXJsXSA9IHtcbiAgICAgICAgICB2YWx1ZTogcmVzXG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZnVuY3Rpb24gKGVycikge1xuICAgICAgICByZW1vdGVDYWNoZVt1cmxdID0ge1xuICAgICAgICAgIGVycm9yOiBlcnJcbiAgICAgICAgfTtcblxuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICAvLyBSZXR1cm4gdGhlIGNhY2hlZCB2ZXJzaW9uXG4gICAgYWxsVGFza3MgPSBhbGxUYXNrcy50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBjYWNoZUVudHJ5LnZhbHVlO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gUmV0dXJuIGEgY2xvbmVkIHZlcnNpb24gdG8gYXZvaWQgdXBkYXRpbmcgdGhlIGNhY2hlXG4gIGFsbFRhc2tzID0gYWxsVGFza3MudGhlbihmdW5jdGlvbiAocmVzKSB7XG4gICAgcmV0dXJuIGNsb25lKHJlcyk7XG4gIH0pO1xuXG4gIHJldHVybiBhbGxUYXNrcztcbn1cblxuZnVuY3Rpb24gaXNSZWZMaWtlIChvYmosIHRocm93V2l0aERldGFpbHMpIHtcbiAgdmFyIHJlZkxpa2UgPSB0cnVlO1xuXG4gIHRyeSB7XG4gICAgaWYgKCFpc1R5cGUob2JqLCAnT2JqZWN0JykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignb2JqIGlzIG5vdCBhbiBPYmplY3QnKTtcbiAgICB9IGVsc2UgaWYgKCFpc1R5cGUob2JqLiRyZWYsICdTdHJpbmcnKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdvYmouJHJlZiBpcyBub3QgYSBTdHJpbmcnKTtcbiAgICB9XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGlmICh0aHJvd1dpdGhEZXRhaWxzKSB7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuXG4gICAgcmVmTGlrZSA9IGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuIHJlZkxpa2U7XG59XG5cbmZ1bmN0aW9uIGlzVHlwZSAob2JqLCB0eXBlKSB7XG4gIC8vIEEgUGhhbnRvbUpTIGJ1ZyAoaHR0cHM6Ly9naXRodWIuY29tL2FyaXlhL3BoYW50b21qcy9pc3N1ZXMvMTE3MjIpIHByb2hpYml0cyB1cyBmcm9tIHVzaW5nIHRoZSBzYW1lIGFwcHJvYWNoIGZvclxuICAvLyB1bmRlZmluZWQgY2hlY2tpbmcgdGhhdCB3ZSB1c2UgZm9yIG90aGVyIHR5cGVzLlxuICBpZiAodHlwZSA9PT0gJ1VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gdHlwZW9mIG9iaiA9PT0gJ3VuZGVmaW5lZCc7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvYmopID09PSAnW29iamVjdCAnICsgdHlwZSArICddJztcbiAgfVxufVxuXG5mdW5jdGlvbiBtYWtlUmVmRmlsdGVyIChvcHRpb25zKSB7XG4gIHZhciByZWZGaWx0ZXI7XG4gIHZhciB2YWxpZFR5cGVzO1xuXG4gIGlmIChpc1R5cGUob3B0aW9ucy5maWx0ZXIsICdBcnJheScpIHx8IGlzVHlwZShvcHRpb25zLmZpbHRlciwgJ1N0cmluZycpKSB7XG4gICAgdmFsaWRUeXBlcyA9IGlzVHlwZShvcHRpb25zLmZpbHRlciwgJ1N0cmluZycpID8gW29wdGlvbnMuZmlsdGVyXSA6IG9wdGlvbnMuZmlsdGVyO1xuICAgIHJlZkZpbHRlciA9IGZ1bmN0aW9uIChyZWZEZXRhaWxzKSB7XG4gICAgICAvLyBDaGVjayB0aGUgZXhhY3QgdHlwZSBvciBmb3IgaW52YWxpZCBVUklzLCBjaGVjayBpdHMgb3JpZ2luYWwgdHlwZVxuICAgICAgcmV0dXJuIHZhbGlkVHlwZXMuaW5kZXhPZihyZWZEZXRhaWxzLnR5cGUpID4gLTEgfHwgdmFsaWRUeXBlcy5pbmRleE9mKGdldFJlZlR5cGUocmVmRGV0YWlscykpID4gLTE7XG4gICAgfTtcbiAgfSBlbHNlIGlmIChpc1R5cGUob3B0aW9ucy5maWx0ZXIsICdGdW5jdGlvbicpKSB7XG4gICAgcmVmRmlsdGVyID0gb3B0aW9ucy5maWx0ZXI7XG4gIH0gZWxzZSBpZiAoaXNUeXBlKG9wdGlvbnMuZmlsdGVyLCAnVW5kZWZpbmVkJykpIHtcbiAgICByZWZGaWx0ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChyZWZEZXRhaWxzLCBwYXRoKSB7XG4gICAgcmV0dXJuIChyZWZEZXRhaWxzLnR5cGUgIT09ICdpbnZhbGlkJyB8fCBvcHRpb25zLmluY2x1ZGVJbnZhbGlkID09PSB0cnVlKSAmJiByZWZGaWx0ZXIocmVmRGV0YWlscywgcGF0aCk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1ha2VTdWJEb2NQYXRoIChvcHRpb25zKSB7XG4gIHZhciBzdWJEb2NQYXRoO1xuXG4gIGlmIChpc1R5cGUob3B0aW9ucy5zdWJEb2NQYXRoLCAnQXJyYXknKSkge1xuICAgIHN1YkRvY1BhdGggPSBvcHRpb25zLnN1YkRvY1BhdGg7XG4gIH0gZWxzZSBpZiAoaXNUeXBlKG9wdGlvbnMuc3ViRG9jUGF0aCwgJ1N0cmluZycpKSB7XG4gICAgc3ViRG9jUGF0aCA9IHBhdGhGcm9tUHRyKG9wdGlvbnMuc3ViRG9jUGF0aCk7XG4gIH0gZWxzZSBpZiAoaXNUeXBlKG9wdGlvbnMuc3ViRG9jUGF0aCwgJ1VuZGVmaW5lZCcpKSB7XG4gICAgc3ViRG9jUGF0aCA9IFtdO1xuICB9XG5cbiAgcmV0dXJuIHN1YkRvY1BhdGg7XG59XG5cbmZ1bmN0aW9uIHBhcnNlVVJJICh1cmkpIHtcbiAgLy8gV2UgZGVjb2RlIGZpcnN0IHRvIGF2b2lkIGRvdWJseSBlbmNvZGluZ1xuICByZXR1cm4gVVJJLnBhcnNlKGVuY29kZVVSSShkZWNvZGVVUkkodXJpKSkpO1xufVxuXG5mdW5jdGlvbiBzZXRWYWx1ZSAob2JqLCByZWZQYXRoLCB2YWx1ZSkge1xuICBmaW5kVmFsdWUob2JqLCByZWZQYXRoLnNsaWNlKDAsIHJlZlBhdGgubGVuZ3RoIC0gMSkpW2RlY29kZVVSSShyZWZQYXRoW3JlZlBhdGgubGVuZ3RoIC0gMV0pXSA9IHZhbHVlO1xufVxuXG5mdW5jdGlvbiB3YWxrIChhbmNlc3RvcnMsIG5vZGUsIHBhdGgsIGZuKSB7XG4gIHZhciBwcm9jZXNzQ2hpbGRyZW4gPSB0cnVlO1xuXG4gIGZ1bmN0aW9uIHdhbGtJdGVtIChpdGVtLCBzZWdtZW50KSB7XG4gICAgcGF0aC5wdXNoKHNlZ21lbnQpO1xuICAgIHdhbGsoYW5jZXN0b3JzLCBpdGVtLCBwYXRoLCBmbik7XG4gICAgcGF0aC5wb3AoKTtcbiAgfVxuXG4gIC8vIENhbGwgdGhlIGl0ZXJhdGVlXG4gIGlmIChpc1R5cGUoZm4sICdGdW5jdGlvbicpKSB7XG4gICAgcHJvY2Vzc0NoaWxkcmVuID0gZm4oYW5jZXN0b3JzLCBub2RlLCBwYXRoKTtcbiAgfVxuXG4gIC8vIFdlIGRvIG5vdCBwcm9jZXNzIGNpcmN1bGFyIG9iamVjdHMgYWdhaW5cbiAgaWYgKGFuY2VzdG9ycy5pbmRleE9mKG5vZGUpID09PSAtMSkge1xuICAgIGFuY2VzdG9ycy5wdXNoKG5vZGUpO1xuXG4gICAgaWYgKHByb2Nlc3NDaGlsZHJlbiAhPT0gZmFsc2UpIHtcbiAgICAgIGlmIChpc1R5cGUobm9kZSwgJ0FycmF5JykpIHtcbiAgICAgICAgbm9kZS5mb3JFYWNoKGZ1bmN0aW9uIChtZW1iZXIsIGluZGV4KSB7XG4gICAgICAgICAgd2Fsa0l0ZW0obWVtYmVyLCBpbmRleC50b1N0cmluZygpKTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2UgaWYgKGlzVHlwZShub2RlLCAnT2JqZWN0JykpIHtcbiAgICAgICAgT2JqZWN0LmtleXMobm9kZSkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgd2Fsa0l0ZW0obm9kZVtrZXldLCBrZXkpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBhbmNlc3RvcnMucG9wKCk7XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlT3B0aW9ucyAob3B0aW9ucywgb2JqKSB7XG4gIGlmIChpc1R5cGUob3B0aW9ucywgJ1VuZGVmaW5lZCcpKSB7XG4gICAgLy8gRGVmYXVsdCB0byBhbiBlbXB0eSBvcHRpb25zIG9iamVjdFxuICAgIG9wdGlvbnMgPSB7fTtcbiAgfSBlbHNlIHtcbiAgICAvLyBDbG9uZSB0aGUgb3B0aW9ucyBzbyB3ZSBkbyBub3QgYWx0ZXIgdGhlIG9uZXMgcGFzc2VkIGluXG4gICAgb3B0aW9ucyA9IGNsb25lKG9wdGlvbnMpO1xuICB9XG5cbiAgaWYgKCFpc1R5cGUob3B0aW9ucywgJ09iamVjdCcpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignb3B0aW9ucyBtdXN0IGJlIGFuIE9iamVjdCcpO1xuICB9IGVsc2UgaWYgKCFpc1R5cGUob3B0aW9ucy5maWx0ZXIsICdVbmRlZmluZWQnKSAmJlxuICAgICAgICAgICAgICFpc1R5cGUob3B0aW9ucy5maWx0ZXIsICdBcnJheScpICYmXG4gICAgICAgICAgICAgIWlzVHlwZShvcHRpb25zLmZpbHRlciwgJ0Z1bmN0aW9uJykgJiZcbiAgICAgICAgICAgICAhaXNUeXBlKG9wdGlvbnMuZmlsdGVyLCAnU3RyaW5nJykpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdvcHRpb25zLmZpbHRlciBtdXN0IGJlIGFuIEFycmF5LCBhIEZ1bmN0aW9uIG9mIGEgU3RyaW5nJyk7XG4gIH0gZWxzZSBpZiAoIWlzVHlwZShvcHRpb25zLmluY2x1ZGVJbnZhbGlkLCAnVW5kZWZpbmVkJykgJiZcbiAgICAgICAgICAgICAhaXNUeXBlKG9wdGlvbnMuaW5jbHVkZUludmFsaWQsICdCb29sZWFuJykpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdvcHRpb25zLmluY2x1ZGVJbnZhbGlkIG11c3QgYmUgYSBCb29sZWFuJyk7XG4gIH0gZWxzZSBpZiAoIWlzVHlwZShvcHRpb25zLnJlZlByZVByb2Nlc3NvciwgJ1VuZGVmaW5lZCcpICYmXG4gICAgICAgICAgICAgIWlzVHlwZShvcHRpb25zLnJlZlByZVByb2Nlc3NvciwgJ0Z1bmN0aW9uJykpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdvcHRpb25zLnJlZlByZVByb2Nlc3NvciBtdXN0IGJlIGEgRnVuY3Rpb24nKTtcbiAgfSBlbHNlIGlmICghaXNUeXBlKG9wdGlvbnMucmVmUG9zdFByb2Nlc3NvciwgJ1VuZGVmaW5lZCcpICYmXG4gICAgICAgICAgICAgIWlzVHlwZShvcHRpb25zLnJlZlBvc3RQcm9jZXNzb3IsICdGdW5jdGlvbicpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignb3B0aW9ucy5yZWZQb3N0UHJvY2Vzc29yIG11c3QgYmUgYSBGdW5jdGlvbicpO1xuICB9IGVsc2UgaWYgKCFpc1R5cGUob3B0aW9ucy5zdWJEb2NQYXRoLCAnVW5kZWZpbmVkJykgJiZcbiAgICAgICAgICAgICAhaXNUeXBlKG9wdGlvbnMuc3ViRG9jUGF0aCwgJ0FycmF5JykgJiZcbiAgICAgICAgICAgICAhaXNQdHIob3B0aW9ucy5zdWJEb2NQYXRoKSkge1xuICAgIC8vIElmIGEgcG9pbnRlciBpcyBwcm92aWRlZCwgdGhyb3cgYW4gZXJyb3IgaWYgaXQncyBub3QgdGhlIHByb3BlciB0eXBlXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignb3B0aW9ucy5zdWJEb2NQYXRoIG11c3QgYmUgYW4gQXJyYXkgb2YgcGF0aCBzZWdtZW50cyBvciBhIHZhbGlkIEpTT04gUG9pbnRlcicpO1xuICB9XG5cbiAgb3B0aW9ucy5maWx0ZXIgPSBtYWtlUmVmRmlsdGVyKG9wdGlvbnMpO1xuXG4gIC8vIFNldCB0aGUgc3ViRG9jUGF0aCB0byBhdm9pZCBldmVyeW9uZSBlbHNlIGhhdmluZyB0byBjb21wdXRlIGl0XG4gIG9wdGlvbnMuc3ViRG9jUGF0aCA9IG1ha2VTdWJEb2NQYXRoKG9wdGlvbnMpO1xuXG4gIGlmICghaXNUeXBlKG9iaiwgJ1VuZGVmaW5lZCcpKSB7XG4gICAgdHJ5IHtcbiAgICAgIGZpbmRWYWx1ZShvYmosIG9wdGlvbnMuc3ViRG9jUGF0aCk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBlcnIubWVzc2FnZSA9IGVyci5tZXNzYWdlLnJlcGxhY2UoJ0pTT04gUG9pbnRlcicsICdvcHRpb25zLnN1YkRvY1BhdGgnKTtcblxuICAgICAgdGhyb3cgZXJyO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBvcHRpb25zO1xufVxuXG4vKiBNb2R1bGUgTWVtYmVycyAqL1xuXG4vKlxuICogRWFjaCBvZiB0aGUgZnVuY3Rpb25zIGJlbG93IGFyZSBkZWZpbmVkIGFzIGZ1bmN0aW9uIHN0YXRlbWVudHMgYW5kICp0aGVuKiBleHBvcnRlZCBpbiB0d28gc3RlcHMgaW5zdGVhZCBvZiBvbmUgZHVlXG4gKiB0byBhIGJ1ZyBpbiBqc2RvYyAoaHR0cHM6Ly9naXRodWIuY29tL2pzZG9jMm1kL2pzZG9jLXBhcnNlL2lzc3Vlcy8xOCkgdGhhdCBjYXVzZXMgb3VyIGRvY3VtZW50YXRpb24gdG8gYmVcbiAqIGdlbmVyYXRlZCBpbXByb3Blcmx5LiAgVGhlIGltcGFjdCB0byB0aGUgdXNlciBpcyBzaWduaWZpY2FudCBlbm91Z2ggZm9yIHVzIHRvIHdhcnJhbnQgd29ya2luZyBhcm91bmQgaXQgdW50aWwgdGhpc1xuICogaXMgZml4ZWQuXG4gKi9cblxuLyoqXG4gKiBUaGUgb3B0aW9ucyB1c2VkIGZvciB2YXJpb3VzIEpzb25SZWZzIEFQSXMuXG4gKlxuICogQHR5cGVkZWYge29iamVjdH0gSnNvblJlZnNPcHRpb25zXG4gKlxuICogQHBhcmFtIHtzdHJpbmd8c3RyaW5nW118ZnVuY3Rpb259IFtmaWx0ZXI9ZnVuY3Rpb24gKCkge3JldHVybiB0cnVlO31dIC0gVGhlIGZpbHRlciB0byB1c2Ugd2hlbiBnYXRoZXJpbmcgSlNPTlxuICogUmVmZXJlbmNlcyAqKElmIHRoaXMgdmFsdWUgaXMgYSBzaW5nbGUgc3RyaW5nIG9yIGFuIGFycmF5IG9mIHN0cmluZ3MsIHRoZSB2YWx1ZShzKSBhcmUgZXhwZWN0ZWQgdG8gYmUgdGhlIGB0eXBlKHMpYFxuICogeW91IGFyZSBpbnRlcmVzdGVkIGluIGNvbGxlY3RpbmcgYXMgZGVzY3JpYmVkIGluIHtAbGluayBtb2R1bGU6SnNvblJlZnMuZ2V0UmVmRGV0YWlsc30uICBJZiBpdCBpcyBhIGZ1bmN0aW9uLCBpdCBpc1xuICogZXhwZWN0ZWQgdGhhdCB0aGUgZnVuY3Rpb24gYmVoYXZlcyBsaWtlIHtAbGluayBtb2R1bGU6SnNvblJlZnN+UmVmRGV0YWlsc0ZpbHRlcn0uKSpcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW2luY2x1ZGVJbnZhbGlkPWZhbHNlXSAtIFdoZXRoZXIgb3Igbm90IHRvIGluY2x1ZGUgaW52YWxpZCBKU09OIFJlZmVyZW5jZSBkZXRhaWxzICooVGhpcyB3aWxsIG1ha2VcbiAqIGl0IHNvIHRoYXQgb2JqZWN0cyB0aGF0IGFyZSBsaWtlIEpTT04gUmVmZXJlbmNlIG9iamVjdHMsIGFzIGluIHRoZXkgYXJlIGFuIGBPYmplY3RgIGFuZCB0aGUgaGF2ZSBhIGAkcmVmYCBwcm9wZXJ0eSxcbiAqIGJ1dCBmYWlsIHZhbGlkYXRpb24gd2lsbCBiZSBpbmNsdWRlZC4gIFRoaXMgaXMgdmVyeSB1c2VmdWwgZm9yIHdoZW4geW91IHdhbnQgdG8ga25vdyBpZiB5b3UgaGF2ZSBpbnZhbGlkIEpTT05cbiAqIFJlZmVyZW5jZSBkZWZpbml0aW9ucy4gIFRoaXMgd2lsbCBub3QgbWVhbiB0aGF0IEFQSXMgd2lsbCBwcm9jZXNzIGludmFsaWQgSlNPTiBSZWZlcmVuY2VzIGJ1dCB0aGUgcmVhc29ucyBhcyB0byB3aHlcbiAqIHRoZSBKU09OIFJlZmVyZW5jZXMgYXJlIGludmFsaWQgd2lsbCBiZSBpbmNsdWRlZCBpbiB0aGUgcmV0dXJuZWQgbWV0YWRhdGEuKSpcbiAqIEBwYXJhbSB7b2JqZWN0fSBbbG9hZGVyT3B0aW9uc10gLSBUaGUgb3B0aW9ucyB0byBwYXNzIHRvXG4gKiB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL3doaXRsb2NramMvcGF0aC1sb2FkZXIvYmxvYi9tYXN0ZXIvZG9jcy9BUEkubWQjbW9kdWxlX1BhdGhMb2FkZXIubG9hZHxQYXRoTG9hZGVyfmxvYWR9XG4gKiBAcGFyYW0ge21vZHVsZTpKc29uUmVmc35SZWZQcmVQcm9jZXNzb3J9IFtyZWZQcmVQcm9jZXNzb3JdIC0gVGhlIGNhbGxiYWNrIHVzZWQgdG8gcHJlLXByb2Nlc3MgYSBKU09OIFJlZmVyZW5jZSBsaWtlXG4gKiBvYmplY3QgKihUaGlzIGlzIGNhbGxlZCBwcmlvciB0byB2YWxpZGF0aW5nIHRoZSBKU09OIFJlZmVyZW5jZSBsaWtlIG9iamVjdCBhbmQgZ2V0dGluZyBpdHMgZGV0YWlscykqXG4gKiBAcGFyYW0ge21vZHVsZTpKc29uUmVmc35SZWZQb3N0UHJvY2Vzc29yfSBbcmVmUG9zdFByb2Nlc3Nvcl0gLSBUaGUgY2FsbGJhY2sgdXNlZCB0byBwb3N0LXByb2Nlc3MgdGhlIEpTT04gUmVmZXJlbmNlXG4gKiBtZXRhZGF0YSAqKFRoaXMgaXMgY2FsbGVkIHByaW9yIGZpbHRlcmluZyB0aGUgcmVmZXJlbmNlcykqXG4gKiBAcGFyYW0ge3N0cmluZ30gW29wdGlvbnMucmVsYXRpdmVCYXNlXSAtIFRoZSBiYXNlIGxvY2F0aW9uIHRvIHVzZSB3aGVuIHJlc29sdmluZyByZWxhdGl2ZSByZWZlcmVuY2VzICooT25seSB1c2VmdWxcbiAqIGZvciBBUElzIHRoYXQgZG8gcmVtb3RlIHJlZmVyZW5jZSByZXNvbHV0aW9uLiAgSWYgdGhpcyB2YWx1ZSBpcyBub3QgZGVmaW5lZCxcbiAqIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vd2hpdGxvY2tqYy9wYXRoLWxvYWRlcnxwYXRoLWxvYWRlcn0gd2lsbCB1c2UgYHdpbmRvdy5sb2NhdGlvbi5ocmVmYCBmb3IgdGhlIGJyb3dzZXIgYW5kXG4gKiBgcHJvY2Vzcy5jd2QoKWAgZm9yIE5vZGUuanMuKSpcbiAqIEBwYXJhbSB7c3RyaW5nfHN0cmluZ1tdfSBbb3B0aW9ucy5zdWJEb2NQYXRoPVtdXSAtIFRoZSBKU09OIFBvaW50ZXIgb3IgYXJyYXkgb2YgcGF0aCBzZWdtZW50cyB0byB0aGUgc3ViIGRvY3VtZW50XG4gKiBsb2NhdGlvbiB0byBzZWFyY2ggZnJvbVxuICovXG5cbi8qKlxuICogU2ltcGxlIGZ1bmN0aW9uIHVzZWQgdG8gZmlsdGVyIG91dCBKU09OIFJlZmVyZW5jZXMuXG4gKlxuICogQHR5cGVkZWYge2Z1bmN0aW9ufSBSZWZEZXRhaWxzRmlsdGVyXG4gKlxuICogQHBhcmFtIHttb2R1bGU6SnNvblJlZnN+VW5yZXNvbHZlZFJlZkRldGFpbHN9IHJlZkRldGFpbHMgLSBUaGUgSlNPTiBSZWZlcmVuY2UgZGV0YWlscyB0byB0ZXN0XG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBwYXRoIC0gVGhlIHBhdGggdG8gdGhlIEpTT04gUmVmZXJlbmNlXG4gKlxuICogQHJldHVybnMge2Jvb2xlYW59IHdoZXRoZXIgdGhlIEpTT04gUmVmZXJlbmNlIHNob3VsZCBiZSBmaWx0ZXJlZCAqKG91dCkqIG9yIG5vdFxuICovXG5cbi8qKlxuICogU2ltcGxlIGZ1bmN0aW9uIHVzZWQgdG8gcHJlLXByb2Nlc3MgYSBKU09OIFJlZmVyZW5jZSBsaWtlIG9iamVjdC5cbiAqXG4gKiBAdHlwZWRlZiB7ZnVuY3Rpb259IFJlZlByZVByb2Nlc3NvclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBvYmogLSBUaGUgSlNPTiBSZWZlcmVuY2UgbGlrZSBvYmplY3RcbiAqIEBwYXJhbSB7c3RyaW5nW119IHBhdGggLSBUaGUgcGF0aCB0byB0aGUgSlNPTiBSZWZlcmVuY2UgbGlrZSBvYmplY3RcbiAqXG4gKiBAcmV0dXJucyB7b2JqZWN0fSB0aGUgcHJvY2Vzc2VkIEpTT04gUmVmZXJlbmNlIGxpa2Ugb2JqZWN0XG4gKi9cblxuLyoqXG4gKiBTaW1wbGUgZnVuY3Rpb24gdXNlZCB0byBwb3N0LXByb2Nlc3MgYSBKU09OIFJlZmVyZW5jZSBkZXRhaWxzLlxuICpcbiAqIEB0eXBlZGVmIHtmdW5jdGlvbn0gUmVmUG9zdFByb2Nlc3NvclxuICpcbiAqIEBwYXJhbSB7bW9kdWxlOkpzb25SZWZzflVucmVzb2x2ZWRSZWZEZXRhaWxzfSByZWZEZXRhaWxzIC0gVGhlIEpTT04gUmVmZXJlbmNlIGRldGFpbHMgdG8gdGVzdFxuICogQHBhcmFtIHtzdHJpbmdbXX0gcGF0aCAtIFRoZSBwYXRoIHRvIHRoZSBKU09OIFJlZmVyZW5jZVxuICpcbiAqIEByZXR1cm5zIHtvYmplY3R9IHRoZSBwcm9jZXNzZWQgSlNPTiBSZWZlcmVuY2UgZGV0YWlscyBvYmplY3RcbiAqL1xuXG4vKipcbiAqIERldGFpbGVkIGluZm9ybWF0aW9uIGFib3V0IHJlc29sdmVkIEpTT04gUmVmZXJlbmNlcy5cbiAqXG4gKiBAdHlwZWRlZiB7bW9kdWxlOkpzb25SZWZzflVucmVzb2x2ZWRSZWZEZXRhaWxzfSBSZXNvbHZlZFJlZkRldGFpbHNcbiAqXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtjaXJjdWxhcl0gLSBXaGV0aGVyIG9yIG5vdCB0aGUgSlNPTiBSZWZlcmVuY2UgaXMgY2lyY3VsYXIgKihXaWxsIG5vdCBiZSBzZXQgaWYgdGhlIEpTT05cbiAqIFJlZmVyZW5jZSBpcyBub3QgY2lyY3VsYXIpKlxuICogQHByb3BlcnR5IHtib29sZWFufSBbbWlzc2luZ10gLSBXaGV0aGVyIG9yIG5vdCB0aGUgcmVmZXJlbmNlZCB2YWx1ZSB3YXMgbWlzc2luZyBvciBub3QgKihXaWxsIG5vdCBiZSBzZXQgaWYgdGhlXG4gKiByZWZlcmVuY2VkIHZhbHVlIGlzIG5vdCBtaXNzaW5nKSpcbiAqIEBwcm9wZXJ0eSB7Kn0gW3ZhbHVlXSAtIFRoZSByZWZlcmVuY2VkIHZhbHVlICooV2lsbCBub3QgYmUgc2V0IGlmIHRoZSByZWZlcmVuY2VkIHZhbHVlIGlzIG1pc3NpbmcpKlxuICovXG5cbi8qKlxuICogVGhlIHJlc3VsdHMgb2YgcmVzb2x2aW5nIHRoZSBKU09OIFJlZmVyZW5jZXMgb2YgYW4gYXJyYXkvb2JqZWN0LlxuICpcbiAqIEB0eXBlZGVmIHtvYmplY3R9IFJlc29sdmVkUmVmc1Jlc3VsdHNcbiAqXG4gKiBAcHJvcGVydHkge21vZHVsZTpKc29uUmVmc35SZXNvbHZlZFJlZkRldGFpbHN9IHJlZnMgLSBBbiBvYmplY3Qgd2hvc2Uga2V5cyBhcmUgSlNPTiBQb2ludGVycyAqKGZyYWdtZW50IHZlcnNpb24pKlxuICogdG8gd2hlcmUgdGhlIEpTT04gUmVmZXJlbmNlIGlzIGRlZmluZWQgYW5kIHdob3NlIHZhbHVlcyBhcmUge0BsaW5rIG1vZHVsZTpKc29uUmVmc35SZXNvbHZlZFJlZkRldGFpbHN9XG4gKiBAcHJvcGVydHkge29iamVjdH0gcmVzb2x2ZWQgLSBUaGUgYXJyYXkvb2JqZWN0IHdpdGggaXRzIEpTT04gUmVmZXJlbmNlcyBmdWxseSByZXNvbHZlZFxuICovXG5cbi8qKlxuICogQW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIHJldHJpZXZlZCBkb2N1bWVudCBhbmQgZGV0YWlsZWQgaW5mb3JtYXRpb24gYWJvdXQgaXRzIEpTT04gUmVmZXJlbmNlcy5cbiAqXG4gKiBAdHlwZWRlZiB7bW9kdWxlOkpzb25SZWZzflJlc29sdmVkUmVmc1Jlc3VsdHN9IFJldHJpZXZlZFJlZnNSZXN1bHRzXG4gKlxuICogQHByb3BlcnR5IHtvYmplY3R9IHZhbHVlIC0gVGhlIHJldHJpZXZlZCBkb2N1bWVudFxuICovXG5cbi8qKlxuICogQW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIHJldHJpZXZlZCBkb2N1bWVudCwgdGhlIGRvY3VtZW50IHdpdGggaXRzIHJlZmVyZW5jZXMgcmVzb2x2ZWQgYW5kICBkZXRhaWxlZCBpbmZvcm1hdGlvblxuICogYWJvdXQgaXRzIEpTT04gUmVmZXJlbmNlcy5cbiAqXG4gKiBAdHlwZWRlZiB7b2JqZWN0fSBSZXRyaWV2ZWRSZXNvbHZlZFJlZnNSZXN1bHRzXG4gKlxuICogQHByb3BlcnR5IHttb2R1bGU6SnNvblJlZnN+VW5yZXNvbHZlZFJlZkRldGFpbHN9IHJlZnMgLSBBbiBvYmplY3Qgd2hvc2Uga2V5cyBhcmUgSlNPTiBQb2ludGVycyAqKGZyYWdtZW50IHZlcnNpb24pKlxuICogdG8gd2hlcmUgdGhlIEpTT04gUmVmZXJlbmNlIGlzIGRlZmluZWQgYW5kIHdob3NlIHZhbHVlcyBhcmUge0BsaW5rIG1vZHVsZTpKc29uUmVmc35VbnJlc29sdmVkUmVmRGV0YWlsc31cbiAqIEBwcm9wZXJ0eSB7UmVzb2x2ZWRSZWZzUmVzdWx0c30gLSBBbiBvYmplY3Qgd2hvc2Uga2V5cyBhcmUgSlNPTiBQb2ludGVycyAqKGZyYWdtZW50IHZlcnNpb24pKlxuICogdG8gd2hlcmUgdGhlIEpTT04gUmVmZXJlbmNlIGlzIGRlZmluZWQgYW5kIHdob3NlIHZhbHVlcyBhcmUge0BsaW5rIG1vZHVsZTpKc29uUmVmc35SZXNvbHZlZFJlZkRldGFpbHN9XG4gKiBAcHJvcGVydHkge29iamVjdH0gdmFsdWUgLSBUaGUgcmV0cmlldmVkIGRvY3VtZW50XG4gKi9cblxuLyoqXG4gKiBEZXRhaWxlZCBpbmZvcm1hdGlvbiBhYm91dCB1bnJlc29sdmVkIEpTT04gUmVmZXJlbmNlcy5cbiAqXG4gKiBAdHlwZWRlZiB7b2JqZWN0fSBVbnJlc29sdmVkUmVmRGV0YWlsc1xuICpcbiAqIEBwcm9wZXJ0eSB7b2JqZWN0fSBkZWYgLSBUaGUgSlNPTiBSZWZlcmVuY2UgZGVmaW5pdGlvblxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtlcnJvcl0gLSBUaGUgZXJyb3IgaW5mb3JtYXRpb24gZm9yIGludmFsaWQgSlNPTiBSZWZlcmVuY2UgZGVmaW5pdGlvbiAqKE9ubHkgcHJlc2VudCB3aGVuIHRoZVxuICogSlNPTiBSZWZlcmVuY2UgZGVmaW5pdGlvbiBpcyBpbnZhbGlkIG9yIHRoZXJlIHdhcyBhIHByb2JsZW0gcmV0cmlldmluZyBhIHJlbW90ZSByZWZlcmVuY2UgZHVyaW5nIHJlc29sdXRpb24pKlxuICogQHByb3BlcnR5IHtzdHJpbmd9IHVyaSAtIFRoZSBVUkkgcG9ydGlvbiBvZiB0aGUgSlNPTiBSZWZlcmVuY2VcbiAqIEBwcm9wZXJ0eSB7b2JqZWN0fSB1cmlEZXRhaWxzIC0gRGV0YWlsZWQgaW5mb3JtYXRpb24gYWJvdXQgdGhlIFVSSSBhcyBwcm92aWRlZCBieVxuICoge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9nYXJ5Y291cnQvdXJpLWpzfFVSSS5wYXJzZX0uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gdHlwZSAtIFRoZSBKU09OIFJlZmVyZW5jZSB0eXBlICooVGhpcyB2YWx1ZSBjYW4gYmUgb25lIG9mIHRoZSBmb2xsb3dpbmc6IGBpbnZhbGlkYCwgYGxvY2FsYCxcbiAqIGByZWxhdGl2ZWAgb3IgYHJlbW90ZWAuKSpcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbd2FybmluZ10gLSBUaGUgd2FybmluZyBpbmZvcm1hdGlvbiAqKE9ubHkgcHJlc2VudCB3aGVuIHRoZSBKU09OIFJlZmVyZW5jZSBkZWZpbml0aW9uIHByb2R1Y2VzIGFcbiAqIHdhcm5pbmcpKlxuICovXG5cbi8qKlxuICogQ2xlYXJzIHRoZSBpbnRlcm5hbCBjYWNoZSBvZiByZW1vdGUgZG9jdW1lbnRzLCByZWZlcmVuY2UgZGV0YWlscywgZXRjLlxuICpcbiAqIEBhbGlhcyBtb2R1bGU6SnNvblJlZnMuY2xlYXJDYWNoZVxuICovXG5mdW5jdGlvbiBjbGVhckNhY2hlICgpIHtcbiAgcmVtb3RlQ2FjaGUgPSB7fTtcbn1cblxuLyoqXG4gKiBUYWtlcyBhbiBhcnJheSBvZiBwYXRoIHNlZ21lbnRzIGFuZCBkZWNvZGVzIHRoZSBKU09OIFBvaW50ZXIgdG9rZW5zIGluIHRoZW0uXG4gKlxuICogQHBhcmFtIHtzdHJpbmdbXX0gcGF0aCAtIFRoZSBhcnJheSBvZiBwYXRoIHNlZ21lbnRzXG4gKlxuICogQHJldHVybnMge3N0cmluZ30gdGhlIGFycmF5IG9mIHBhdGggc2VnbWVudHMgd2l0aCB0aGVpciBKU09OIFBvaW50ZXIgdG9rZW5zIGRlY29kZWRcbiAqXG4gKiBAdGhyb3dzIHtFcnJvcn0gaWYgdGhlIHBhdGggaXMgbm90IGFuIGBBcnJheWBcbiAqXG4gKiBAc2VlIHtAbGluayBodHRwczovL3Rvb2xzLmlldGYub3JnL2h0bWwvcmZjNjkwMSNzZWN0aW9uLTN9XG4gKlxuICogQGFsaWFzIG1vZHVsZTpKc29uUmVmcy5kZWNvZGVQYXRoXG4gKi9cbmZ1bmN0aW9uIGRlY29kZVBhdGggKHBhdGgpIHtcbiAgaWYgKCFpc1R5cGUocGF0aCwgJ0FycmF5JykpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdwYXRoIG11c3QgYmUgYW4gYXJyYXknKTtcbiAgfVxuXG4gIHJldHVybiBwYXRoLm1hcChmdW5jdGlvbiAoc2VnKSB7XG4gICAgaWYgKCFpc1R5cGUoc2VnLCAnU3RyaW5nJykpIHtcbiAgICAgIHNlZyA9IEpTT04uc3RyaW5naWZ5KHNlZyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRlY29kZVVSSShzZWcucmVwbGFjZSgvfjEvZywgJy8nKS5yZXBsYWNlKC9+MC9nLCAnficpKTtcbiAgfSk7XG59XG5cbi8qKlxuICogVGFrZXMgYW4gYXJyYXkgb2YgcGF0aCBzZWdtZW50cyBhbmQgZW5jb2RlcyB0aGUgc3BlY2lhbCBKU09OIFBvaW50ZXIgY2hhcmFjdGVycyBpbiB0aGVtLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nW119IHBhdGggLSBUaGUgYXJyYXkgb2YgcGF0aCBzZWdtZW50c1xuICpcbiAqIEByZXR1cm5zIHtzdHJpbmd9IHRoZSBhcnJheSBvZiBwYXRoIHNlZ21lbnRzIHdpdGggdGhlaXIgSlNPTiBQb2ludGVyIHRva2VucyBlbmNvZGVkXG4gKlxuICogQHRocm93cyB7RXJyb3J9IGlmIHRoZSBwYXRoIGlzIG5vdCBhbiBgQXJyYXlgXG4gKlxuICogQHNlZSB7QGxpbmsgaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzY5MDEjc2VjdGlvbi0zfVxuICpcbiAqIEBhbGlhcyBtb2R1bGU6SnNvblJlZnMuZW5jb2RlUGF0aFxuICovXG5mdW5jdGlvbiBlbmNvZGVQYXRoIChwYXRoKSB7XG4gIGlmICghaXNUeXBlKHBhdGgsICdBcnJheScpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncGF0aCBtdXN0IGJlIGFuIGFycmF5Jyk7XG4gIH1cblxuICByZXR1cm4gcGF0aC5tYXAoZnVuY3Rpb24gKHNlZykge1xuICAgIGlmICghaXNUeXBlKHNlZywgJ1N0cmluZycpKSB7XG4gICAgICBzZWcgPSBKU09OLnN0cmluZ2lmeShzZWcpO1xuICAgIH1cblxuICAgIHJldHVybiBzZWcucmVwbGFjZSgvfi9nLCAnfjAnKS5yZXBsYWNlKC9cXC8vZywgJ34xJyk7XG4gIH0pO1xufVxuXG4vKipcbiAqIEZpbmRzIEpTT04gUmVmZXJlbmNlcyBkZWZpbmVkIHdpdGhpbiB0aGUgcHJvdmlkZWQgYXJyYXkvb2JqZWN0LlxuICpcbiAqIEBwYXJhbSB7YXJyYXl8b2JqZWN0fSBvYmogLSBUaGUgc3RydWN0dXJlIHRvIGZpbmQgSlNPTiBSZWZlcmVuY2VzIHdpdGhpblxuICogQHBhcmFtIHttb2R1bGU6SnNvblJlZnN+SnNvblJlZnNPcHRpb25zfSBbb3B0aW9uc10gLSBUaGUgSnNvblJlZnMgb3B0aW9uc1xuICpcbiAqIEByZXR1cm5zIHtvYmplY3R9IGFuIG9iamVjdCB3aG9zZSBrZXlzIGFyZSBKU09OIFBvaW50ZXJzICooZnJhZ21lbnQgdmVyc2lvbikqIHRvIHdoZXJlIHRoZSBKU09OIFJlZmVyZW5jZSBpcyBkZWZpbmVkXG4gKiBhbmQgd2hvc2UgdmFsdWVzIGFyZSB7QGxpbmsgbW9kdWxlOkpzb25SZWZzflVucmVzb2x2ZWRSZWZEZXRhaWxzfS5cbiAqXG4gKiBAdGhyb3dzIHtFcnJvcn0gd2hlbiB0aGUgaW5wdXQgYXJndW1lbnRzIGZhaWwgdmFsaWRhdGlvbiBvciBpZiBgb3B0aW9ucy5zdWJEb2NQYXRoYCBwb2ludHMgdG8gYW4gaW52YWxpZCBsb2NhdGlvblxuICpcbiAqIEBhbGlhcyBtb2R1bGU6SnNvblJlZnMuZmluZFJlZnNcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gRmluZGluZyBhbGwgdmFsaWQgcmVmZXJlbmNlc1xuICogdmFyIGFsbFJlZnMgPSBKc29uUmVmcy5maW5kUmVmcyhvYmopO1xuICogLy8gRmluZGluZyBhbGwgcmVtb3RlIHJlZmVyZW5jZXNcbiAqIHZhciByZW1vdGVSZWZzID0gSnNvblJlZnMuZmluZFJlZnMob2JqLCB7ZmlsdGVyOiBbJ3JlbGF0aXZlJywgJ3JlbW90ZSddfSk7XG4gKiAvLyBGaW5kaW5nIGFsbCBpbnZhbGlkIHJlZmVyZW5jZXNcbiAqIHZhciBpbnZhbGlkUmVmcyA9IEpzb25SZWZzLmZpbmRSZWZzKG9iaiwge2ZpbHRlcjogJ2ludmFsaWQnLCBpbmNsdWRlSW52YWxpZDogdHJ1ZX0pO1xuICovXG5mdW5jdGlvbiBmaW5kUmVmcyAob2JqLCBvcHRpb25zKSB7XG4gIHZhciByZWZzID0ge307XG5cbiAgLy8gVmFsaWRhdGUgdGhlIHByb3ZpZGVkIGRvY3VtZW50XG4gIGlmICghaXNUeXBlKG9iaiwgJ0FycmF5JykgJiYgIWlzVHlwZShvYmosICdPYmplY3QnKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ29iaiBtdXN0IGJlIGFuIEFycmF5IG9yIGFuIE9iamVjdCcpO1xuICB9XG5cbiAgLy8gVmFsaWRhdGUgb3B0aW9uc1xuICBvcHRpb25zID0gdmFsaWRhdGVPcHRpb25zKG9wdGlvbnMsIG9iaik7XG5cbiAgLy8gV2FsayB0aGUgZG9jdW1lbnQgKG9yIHN1YiBkb2N1bWVudCkgYW5kIGZpbmQgYWxsIEpTT04gUmVmZXJlbmNlc1xuICB3YWxrKGZpbmRBbmNlc3RvcnMob2JqLCBvcHRpb25zLnN1YkRvY1BhdGgpLFxuICAgICAgIGZpbmRWYWx1ZShvYmosIG9wdGlvbnMuc3ViRG9jUGF0aCksXG4gICAgICAgY2xvbmUob3B0aW9ucy5zdWJEb2NQYXRoKSxcbiAgICAgICBmdW5jdGlvbiAoYW5jZXN0b3JzLCBub2RlLCBwYXRoKSB7XG4gICAgICAgICB2YXIgcHJvY2Vzc0NoaWxkcmVuID0gdHJ1ZTtcbiAgICAgICAgIHZhciByZWZEZXRhaWxzO1xuXG4gICAgICAgICBpZiAoaXNSZWZMaWtlKG5vZGUpKSB7XG4gICAgICAgICAgIC8vIFByZS1wcm9jZXNzIHRoZSBub2RlIHdoZW4gbmVjZXNzYXJ5XG4gICAgICAgICAgIGlmICghaXNUeXBlKG9wdGlvbnMucmVmUHJlUHJvY2Vzc29yLCAnVW5kZWZpbmVkJykpIHtcbiAgICAgICAgICAgICBub2RlID0gb3B0aW9ucy5yZWZQcmVQcm9jZXNzb3IoY2xvbmUobm9kZSksIHBhdGgpO1xuICAgICAgICAgICB9XG5cbiAgICAgICAgICAgcmVmRGV0YWlscyA9IGdldFJlZkRldGFpbHMobm9kZSk7XG5cbiAgICAgICAgICAgLy8gUG9zdC1wcm9jZXNzIHRoZSByZWZlcmVuY2UgZGV0YWlsc1xuICAgICAgICAgICBpZiAoIWlzVHlwZShvcHRpb25zLnJlZlBvc3RQcm9jZXNzb3IsICdVbmRlZmluZWQnKSkge1xuICAgICAgICAgICAgIHJlZkRldGFpbHMgPSBvcHRpb25zLnJlZlBvc3RQcm9jZXNzb3IocmVmRGV0YWlscywgcGF0aCk7XG4gICAgICAgICAgIH1cblxuICAgICAgICAgICBpZiAob3B0aW9ucy5maWx0ZXIocmVmRGV0YWlscywgcGF0aCkpIHtcbiAgICAgICAgICAgICByZWZzW3BhdGhUb1B0cihwYXRoKV0gPSByZWZEZXRhaWxzO1xuICAgICAgICAgICB9XG5cbiAgICAgICAgICAgLy8gV2hlbmV2ZXIgYSBKU09OIFJlZmVyZW5jZSBoYXMgZXh0cmEgY2hpbGRyZW4sIGl0cyBjaGlsZHJlbiBzaG91bGQgbm90IGJlIHByb2Nlc3NlZC5cbiAgICAgICAgICAgLy8gICBTZWU6IGh0dHA6Ly90b29scy5pZXRmLm9yZy9odG1sL2RyYWZ0LXBicnlhbi16eXAtanNvbi1yZWYtMDMjc2VjdGlvbi0zXG4gICAgICAgICAgIGlmIChnZXRFeHRyYVJlZktleXMobm9kZSkubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgIHByb2Nlc3NDaGlsZHJlbiA9IGZhbHNlO1xuICAgICAgICAgICB9XG4gICAgICAgICB9XG5cbiAgICAgICAgIHJldHVybiBwcm9jZXNzQ2hpbGRyZW47XG4gICAgICAgfSk7XG5cbiAgcmV0dXJuIHJlZnM7XG59XG5cbi8qKlxuICogRmluZHMgSlNPTiBSZWZlcmVuY2VzIGRlZmluZWQgd2l0aGluIHRoZSBkb2N1bWVudCBhdCB0aGUgcHJvdmlkZWQgbG9jYXRpb24uXG4gKlxuICogVGhpcyBBUEkgaXMgaWRlbnRpY2FsIHRvIHtAbGluayBtb2R1bGU6SnNvblJlZnMuZmluZFJlZnN9IGV4Y2VwdCB0aGlzIEFQSSB3aWxsIHJldHJpZXZlIGEgcmVtb3RlIGRvY3VtZW50IGFuZCB0aGVuXG4gKiByZXR1cm4gdGhlIHJlc3VsdCBvZiB7QGxpbmsgbW9kdWxlOkpzb25SZWZzLmZpbmRSZWZzfSBvbiB0aGUgcmV0cmlldmVkIGRvY3VtZW50LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBsb2NhdGlvbiAtIFRoZSBsb2NhdGlvbiB0byByZXRyaWV2ZSAqKENhbiBiZSByZWxhdGl2ZSBvciBhYnNvbHV0ZSwganVzdCBtYWtlIHN1cmUgeW91IGxvb2sgYXQgdGhlXG4gKiB7QGxpbmsgbW9kdWxlOkpzb25SZWZzfkpzb25SZWZzT3B0aW9uc3xvcHRpb25zIGRvY3VtZW50YXRpb259IHRvIHNlZSBob3cgcmVsYXRpdmUgcmVmZXJlbmNlcyBhcmUgaGFuZGxlZC4pKlxuICogQHBhcmFtIHttb2R1bGU6SnNvblJlZnN+SnNvblJlZnNPcHRpb25zfSBbb3B0aW9uc10gLSBUaGUgSnNvblJlZnMgb3B0aW9uc1xuICpcbiAqIEByZXR1cm5zIHtQcm9taXNlfSBhIHByb21pc2UgdGhhdCByZXNvbHZlcyBhIHtAbGluayBtb2R1bGU6SnNvblJlZnN+UmV0cmlldmVkUmVmc1Jlc3VsdHN9IGFuZCByZWplY3RzIHdpdGggYW5cbiAqIGBFcnJvcmAgd2hlbiB0aGUgaW5wdXQgYXJndW1lbnRzIGZhaWwgdmFsaWRhdGlvbiwgd2hlbiBgb3B0aW9ucy5zdWJEb2NQYXRoYCBwb2ludHMgdG8gYW4gaW52YWxpZCBsb2NhdGlvbiBvciB3aGVuXG4gKiAgdGhlIGxvY2F0aW9uIGFyZ3VtZW50IHBvaW50cyB0byBhbiB1bmxvYWRhYmxlIHJlc291cmNlXG4gKlxuICogQGFsaWFzIG1vZHVsZTpKc29uUmVmcy5maW5kUmVmc0F0XG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIEV4YW1wbGUgdGhhdCBvbmx5IHJlc29sdmVzIHJlZmVyZW5jZXMgd2l0aGluIGEgc3ViIGRvY3VtZW50XG4gKiBKc29uUmVmcy5maW5kUmVmc0F0KCdodHRwOi8vcGV0c3RvcmUuc3dhZ2dlci5pby92Mi9zd2FnZ2VyLmpzb24nLCB7XG4gKiAgICAgc3ViRG9jUGF0aDogJyMvZGVmaW5pdGlvbnMnXG4gKiAgIH0pXG4gKiAgIC50aGVuKGZ1bmN0aW9uIChyZXMpIHtcbiAqICAgICAgLy8gRG8gc29tZXRoaW5nIHdpdGggdGhlIHJlc3BvbnNlXG4gKiAgICAgIC8vXG4gKiAgICAgIC8vIHJlcy5yZWZzOiBKU09OIFJlZmVyZW5jZSBsb2NhdGlvbnMgYW5kIGRldGFpbHNcbiAqICAgICAgLy8gcmVzLnZhbHVlOiBUaGUgcmV0cmlldmVkIGRvY3VtZW50XG4gKiAgIH0sIGZ1bmN0aW9uIChlcnIpIHtcbiAqICAgICBjb25zb2xlLmxvZyhlcnIuc3RhY2spO1xuICogICB9KTtcbiAqL1xuZnVuY3Rpb24gZmluZFJlZnNBdCAobG9jYXRpb24sIG9wdGlvbnMpIHtcbiAgdmFyIGFsbFRhc2tzID0gUHJvbWlzZS5yZXNvbHZlKCk7XG5cbiAgYWxsVGFza3MgPSBhbGxUYXNrc1xuICAgIC50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFZhbGlkYXRlIHRoZSBwcm92aWRlZCBsb2NhdGlvblxuICAgICAgaWYgKCFpc1R5cGUobG9jYXRpb24sICdTdHJpbmcnKSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdsb2NhdGlvbiBtdXN0IGJlIGEgc3RyaW5nJyk7XG4gICAgICB9XG5cbiAgICAgIC8vIFZhbGlkYXRlIG9wdGlvbnNcbiAgICAgIG9wdGlvbnMgPSB2YWxpZGF0ZU9wdGlvbnMob3B0aW9ucyk7XG5cbiAgICAgIC8vIENvbWJpbmUgdGhlIGxvY2F0aW9uIGFuZCB0aGUgb3B0aW9uYWwgcmVsYXRpdmUgYmFzZVxuICAgICAgbG9jYXRpb24gPSBjb21iaW5lVVJJcyhvcHRpb25zLnJlbGF0aXZlQmFzZSwgbG9jYXRpb24pO1xuXG4gICAgICByZXR1cm4gZ2V0UmVtb3RlRG9jdW1lbnQobG9jYXRpb24sIG9wdGlvbnMpO1xuICAgIH0pXG4gICAgLnRoZW4oZnVuY3Rpb24gKHJlcykge1xuICAgICAgdmFyIGNhY2hlRW50cnkgPSBjbG9uZShyZW1vdGVDYWNoZVtsb2NhdGlvbl0pO1xuICAgICAgdmFyIGNPcHRpb25zID0gY2xvbmUob3B0aW9ucyk7XG4gICAgICB2YXIgdXJpRGV0YWlscyA9IHBhcnNlVVJJKGxvY2F0aW9uKTtcblxuICAgICAgaWYgKGlzVHlwZShjYWNoZUVudHJ5LnJlZnMsICdVbmRlZmluZWQnKSkge1xuICAgICAgICAvLyBEbyBub3QgZmlsdGVyIGFueSByZWZlcmVuY2VzIHNvIHRoZSBjYWNoZSBpcyBjb21wbGV0ZVxuICAgICAgICBkZWxldGUgY09wdGlvbnMuZmlsdGVyO1xuICAgICAgICBkZWxldGUgY09wdGlvbnMuc3ViRG9jUGF0aDtcblxuICAgICAgICBjT3B0aW9ucy5pbmNsdWRlSW52YWxpZCA9IHRydWU7XG5cbiAgICAgICAgcmVtb3RlQ2FjaGVbbG9jYXRpb25dLnJlZnMgPSBmaW5kUmVmcyhyZXMsIGNPcHRpb25zKTtcbiAgICAgIH1cblxuICAgICAgLy8gQWRkIHRoZSBmaWx0ZXIgb3B0aW9ucyBiYWNrXG4gICAgICBpZiAoIWlzVHlwZShvcHRpb25zLmZpbHRlciwgJ1VuZGVmaW5lZCcpKSB7XG4gICAgICAgIGNPcHRpb25zLmZpbHRlciA9IG9wdGlvbnMuZmlsdGVyO1xuICAgICAgfVxuXG4gICAgICBpZiAoIWlzVHlwZSh1cmlEZXRhaWxzLmZyYWdtZW50LCAnVW5kZWZpbmVkJykpIHtcbiAgICAgICAgY09wdGlvbnMuc3ViRG9jUGF0aCA9IHBhdGhGcm9tUHRyKGRlY29kZVVSSSh1cmlEZXRhaWxzLmZyYWdtZW50KSk7XG4gICAgICB9IGVsc2UgaWYgKCFpc1R5cGUodXJpRGV0YWlscy5zdWJEb2NQYXRoLCAnVW5kZWZpbmVkJykpIHtcbiAgICAgICAgY09wdGlvbnMuc3ViRG9jUGF0aCA9IG9wdGlvbnMuc3ViRG9jUGF0aDtcbiAgICAgIH1cblxuICAgICAgLy8gVGhpcyB3aWxsIHVzZSB0aGUgY2FjaGUgc28gZG9uJ3Qgd29ycnkgYWJvdXQgY2FsbGluZyBpdCB0d2ljZVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgcmVmczogZmluZFJlZnMocmVzLCBjT3B0aW9ucyksXG4gICAgICAgIHZhbHVlOiByZXNcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgcmV0dXJuIGFsbFRhc2tzO1xufVxuXG4vKipcbiAqIFJldHVybnMgZGV0YWlsZWQgaW5mb3JtYXRpb24gYWJvdXQgdGhlIEpTT04gUmVmZXJlbmNlLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBvYmogLSBUaGUgSlNPTiBSZWZlcmVuY2UgZGVmaW5pdGlvblxuICpcbiAqIEByZXR1cm5zIHttb2R1bGU6SnNvblJlZnN+VW5yZXNvbHZlZFJlZkRldGFpbHN9IHRoZSBkZXRhaWxlZCBpbmZvcm1hdGlvblxuICpcbiAqIEBhbGlhcyBtb2R1bGU6SnNvblJlZnMuZ2V0UmVmRGV0YWlsc1xuICovXG5mdW5jdGlvbiBnZXRSZWZEZXRhaWxzIChvYmopIHtcbiAgdmFyIGRldGFpbHMgPSB7XG4gICAgZGVmOiBvYmpcbiAgfTtcbiAgdmFyIGNhY2hlS2V5O1xuICB2YXIgZXh0cmFLZXlzO1xuICB2YXIgdXJpRGV0YWlscztcblxuICB0cnkge1xuICAgIGlmIChpc1JlZkxpa2Uob2JqLCB0cnVlKSkge1xuICAgICAgY2FjaGVLZXkgPSBvYmouJHJlZjtcbiAgICAgIHVyaURldGFpbHMgPSB1cmlEZXRhaWxzQ2FjaGVbY2FjaGVLZXldO1xuXG4gICAgICBpZiAoaXNUeXBlKHVyaURldGFpbHMsICdVbmRlZmluZWQnKSkge1xuICAgICAgICB1cmlEZXRhaWxzID0gdXJpRGV0YWlsc0NhY2hlW2NhY2hlS2V5XSA9IHBhcnNlVVJJKGNhY2hlS2V5KTtcbiAgICAgIH1cblxuICAgICAgZGV0YWlscy51cmkgPSBjYWNoZUtleTtcbiAgICAgIGRldGFpbHMudXJpRGV0YWlscyA9IHVyaURldGFpbHM7XG5cbiAgICAgIGlmIChpc1R5cGUodXJpRGV0YWlscy5lcnJvciwgJ1VuZGVmaW5lZCcpKSB7XG4gICAgICAgIGRldGFpbHMudHlwZSA9IGdldFJlZlR5cGUoZGV0YWlscyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkZXRhaWxzLmVycm9yID0gZGV0YWlscy51cmlEZXRhaWxzLmVycm9yO1xuICAgICAgICBkZXRhaWxzLnR5cGUgPSAnaW52YWxpZCc7XG4gICAgICB9XG5cbiAgICAgIC8vIElkZW50aWZ5IHdhcm5pbmdcbiAgICAgIGV4dHJhS2V5cyA9IGdldEV4dHJhUmVmS2V5cyhvYmopO1xuXG4gICAgICBpZiAoZXh0cmFLZXlzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgZGV0YWlscy53YXJuaW5nID0gJ0V4dHJhIEpTT04gUmVmZXJlbmNlIHByb3BlcnRpZXMgd2lsbCBiZSBpZ25vcmVkOiAnICsgZXh0cmFLZXlzLmpvaW4oJywgJyk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGRldGFpbHMudHlwZSA9ICdpbnZhbGlkJztcbiAgICB9XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGRldGFpbHMuZXJyb3IgPSBlcnIubWVzc2FnZTtcbiAgICBkZXRhaWxzLnR5cGUgPSAnaW52YWxpZCc7XG4gIH1cblxuICByZXR1cm4gZGV0YWlscztcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHdoZXRoZXIgdGhlIGFyZ3VtZW50IHJlcHJlc2VudHMgYSBKU09OIFBvaW50ZXIuXG4gKlxuICogQSBzdHJpbmcgaXMgYSBKU09OIFBvaW50ZXIgaWYgdGhlIGZvbGxvd2luZyBhcmUgYWxsIHRydWU6XG4gKlxuICogICAqIFRoZSBzdHJpbmcgaXMgb2YgdHlwZSBgU3RyaW5nYFxuICogICAqIFRoZSBzdHJpbmcgbXVzdCBiZSBlbXB0eSwgYCNgIG9yIHN0YXJ0IHdpdGggYSBgL2Agb3IgYCMvYFxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwdHIgLSBUaGUgc3RyaW5nIHRvIGNoZWNrXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFt0aHJvd1dpdGhEZXRhaWxzPWZhbHNlXSAtIFdoZXRoZXIgb3Igbm90IHRvIHRocm93IGFuIGBFcnJvcmAgd2l0aCB0aGUgZGV0YWlscyBhcyB0byB3aHkgdGhlIHZhbHVlXG4gKiBwcm92aWRlZCBpcyBpbnZhbGlkXG4gKlxuICogQHJldHVybnMge2Jvb2xlYW59IHRoZSByZXN1bHQgb2YgdGhlIGNoZWNrXG4gKlxuICogQHRocm93cyB7ZXJyb3J9IHdoZW4gdGhlIHByb3ZpZGVkIHZhbHVlIGlzIGludmFsaWQgYW5kIHRoZSBgdGhyb3dXaXRoRGV0YWlsc2AgYXJndW1lbnQgaXMgYHRydWVgXG4gKlxuICogQGFsaWFzIG1vZHVsZTpKc29uUmVmcy5pc1B0clxuICpcbiAqIEBzZWUge0BsaW5rIGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmM2OTAxI3NlY3Rpb24tM31cbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gU2VwYXJhdGluZyB0aGUgZGlmZmVyZW50IHdheXMgdG8gaW52b2tlIGlzUHRyIGZvciBkZW1vbnN0cmF0aW9uIHB1cnBvc2VzXG4gKiBpZiAoaXNQdHIoc3RyKSkge1xuICogICAvLyBIYW5kbGUgYSB2YWxpZCBKU09OIFBvaW50ZXJcbiAqIH0gZWxzZSB7XG4gKiAgIC8vIEdldCB0aGUgcmVhc29uIGFzIHRvIHdoeSB0aGUgdmFsdWUgaXMgbm90IGEgSlNPTiBQb2ludGVyIHNvIHlvdSBjYW4gZml4L3JlcG9ydCBpdFxuICogICB0cnkge1xuICogICAgIGlzUHRyKHN0ciwgdHJ1ZSk7XG4gKiAgIH0gY2F0Y2ggKGVycikge1xuICogICAgIC8vIFRoZSBlcnJvciBtZXNzYWdlIGNvbnRhaW5zIHRoZSBkZXRhaWxzIGFzIHRvIHdoeSB0aGUgcHJvdmlkZWQgdmFsdWUgaXMgbm90IGEgSlNPTiBQb2ludGVyXG4gKiAgIH1cbiAqIH1cbiAqL1xuZnVuY3Rpb24gaXNQdHIgKHB0ciwgdGhyb3dXaXRoRGV0YWlscykge1xuICB2YXIgdmFsaWQgPSB0cnVlO1xuICB2YXIgZmlyc3RDaGFyO1xuXG4gIHRyeSB7XG4gICAgaWYgKGlzVHlwZShwdHIsICdTdHJpbmcnKSkge1xuICAgICAgaWYgKHB0ciAhPT0gJycpIHtcbiAgICAgICAgZmlyc3RDaGFyID0gcHRyLmNoYXJBdCgwKTtcblxuICAgICAgICBpZiAoWycjJywgJy8nXS5pbmRleE9mKGZpcnN0Q2hhcikgPT09IC0xKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdwdHIgbXVzdCBzdGFydCB3aXRoIGEgLyBvciAjLycpO1xuICAgICAgICB9IGVsc2UgaWYgKGZpcnN0Q2hhciA9PT0gJyMnICYmIHB0ciAhPT0gJyMnICYmIHB0ci5jaGFyQXQoMSkgIT09ICcvJykge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcigncHRyIG11c3Qgc3RhcnQgd2l0aCBhIC8gb3IgIy8nKTtcbiAgICAgICAgfSBlbHNlIGlmIChwdHIubWF0Y2goYmFkUHRyVG9rZW5SZWdleCkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3B0ciBoYXMgaW52YWxpZCB0b2tlbihzKScpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigncHRyIGlzIG5vdCBhIFN0cmluZycpO1xuICAgIH1cbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgaWYgKHRocm93V2l0aERldGFpbHMgPT09IHRydWUpIHtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG5cbiAgICB2YWxpZCA9IGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuIHZhbGlkO1xufVxuXG4vKipcbiAqIFJldHVybnMgd2hldGhlciB0aGUgYXJndW1lbnQgcmVwcmVzZW50cyBhIEpTT04gUmVmZXJlbmNlLlxuICpcbiAqIEFuIG9iamVjdCBpcyBhIEpTT04gUmVmZXJlbmNlIG9ubHkgaWYgdGhlIGZvbGxvd2luZyBhcmUgYWxsIHRydWU6XG4gKlxuICogICAqIFRoZSBvYmplY3QgaXMgb2YgdHlwZSBgT2JqZWN0YFxuICogICAqIFRoZSBvYmplY3QgaGFzIGEgYCRyZWZgIHByb3BlcnR5XG4gKiAgICogVGhlIGAkcmVmYCBwcm9wZXJ0eSBpcyBhIHZhbGlkIFVSSSAqKFdlIGRvIG5vdCByZXF1aXJlIDEwMCUgc3RyaWN0IFVSSXMgYW5kIHdpbGwgaGFuZGxlIHVuZXNjYXBlZCBzcGVjaWFsXG4gKiAgICAgY2hhcmFjdGVycy4pKlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBvYmogLSBUaGUgb2JqZWN0IHRvIGNoZWNrXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFt0aHJvd1dpdGhEZXRhaWxzPWZhbHNlXSAtIFdoZXRoZXIgb3Igbm90IHRvIHRocm93IGFuIGBFcnJvcmAgd2l0aCB0aGUgZGV0YWlscyBhcyB0byB3aHkgdGhlIHZhbHVlXG4gKiBwcm92aWRlZCBpcyBpbnZhbGlkXG4gKlxuICogQHJldHVybnMge2Jvb2xlYW59IHRoZSByZXN1bHQgb2YgdGhlIGNoZWNrXG4gKlxuICogQHRocm93cyB7ZXJyb3J9IHdoZW4gdGhlIHByb3ZpZGVkIHZhbHVlIGlzIGludmFsaWQgYW5kIHRoZSBgdGhyb3dXaXRoRGV0YWlsc2AgYXJndW1lbnQgaXMgYHRydWVgXG4gKlxuICogQGFsaWFzIG1vZHVsZTpKc29uUmVmcy5pc1JlZlxuICpcbiAqIEBzZWUge0BsaW5rIGh0dHA6Ly90b29scy5pZXRmLm9yZy9odG1sL2RyYWZ0LXBicnlhbi16eXAtanNvbi1yZWYtMDMjc2VjdGlvbi0zfVxuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBTZXBhcmF0aW5nIHRoZSBkaWZmZXJlbnQgd2F5cyB0byBpbnZva2UgaXNSZWYgZm9yIGRlbW9uc3RyYXRpb24gcHVycG9zZXNcbiAqIGlmIChpc1JlZihvYmopKSB7XG4gKiAgIC8vIEhhbmRsZSBhIHZhbGlkIEpTT04gUmVmZXJlbmNlXG4gKiB9IGVsc2Uge1xuICogICAvLyBHZXQgdGhlIHJlYXNvbiBhcyB0byB3aHkgdGhlIHZhbHVlIGlzIG5vdCBhIEpTT04gUmVmZXJlbmNlIHNvIHlvdSBjYW4gZml4L3JlcG9ydCBpdFxuICogICB0cnkge1xuICogICAgIGlzUmVmKHN0ciwgdHJ1ZSk7XG4gKiAgIH0gY2F0Y2ggKGVycikge1xuICogICAgIC8vIFRoZSBlcnJvciBtZXNzYWdlIGNvbnRhaW5zIHRoZSBkZXRhaWxzIGFzIHRvIHdoeSB0aGUgcHJvdmlkZWQgdmFsdWUgaXMgbm90IGEgSlNPTiBSZWZlcmVuY2VcbiAqICAgfVxuICogfVxuICovXG5mdW5jdGlvbiBpc1JlZiAob2JqLCB0aHJvd1dpdGhEZXRhaWxzKSB7XG4gIHJldHVybiBpc1JlZkxpa2Uob2JqLCB0aHJvd1dpdGhEZXRhaWxzKSAmJiBnZXRSZWZEZXRhaWxzKG9iaiwgdGhyb3dXaXRoRGV0YWlscykudHlwZSAhPT0gJ2ludmFsaWQnO1xufVxuXG4vKipcbiAqIFJldHVybnMgYW4gYXJyYXkgb2YgcGF0aCBzZWdtZW50cyBmb3IgdGhlIHByb3ZpZGVkIEpTT04gUG9pbnRlci5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcHRyIC0gVGhlIEpTT04gUG9pbnRlclxuICpcbiAqIEByZXR1cm5zIHtzdHJpbmdbXX0gdGhlIHBhdGggc2VnbWVudHNcbiAqXG4gKiBAdGhyb3dzIHtFcnJvcn0gaWYgdGhlIHByb3ZpZGVkIGBwdHJgIGFyZ3VtZW50IGlzIG5vdCBhIEpTT04gUG9pbnRlclxuICpcbiAqIEBhbGlhcyBtb2R1bGU6SnNvblJlZnMucGF0aEZyb21QdHJcbiAqL1xuZnVuY3Rpb24gcGF0aEZyb21QdHIgKHB0cikge1xuICBpZiAoIWlzUHRyKHB0cikpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3B0ciBtdXN0IGJlIGEgSlNPTiBQb2ludGVyJyk7XG4gIH1cblxuICB2YXIgc2VnbWVudHMgPSBwdHIuc3BsaXQoJy8nKTtcblxuICAvLyBSZW1vdmUgdGhlIGZpcnN0IHNlZ21lbnRcbiAgc2VnbWVudHMuc2hpZnQoKTtcblxuICByZXR1cm4gZGVjb2RlUGF0aChzZWdtZW50cyk7XG59XG5cbi8qKlxuICogUmV0dXJucyBhIEpTT04gUG9pbnRlciBmb3IgdGhlIHByb3ZpZGVkIGFycmF5IG9mIHBhdGggc2VnbWVudHMuXG4gKlxuICogKipOb3RlOioqIElmIGEgcGF0aCBzZWdtZW50IGluIGBwYXRoYCBpcyBub3QgYSBgU3RyaW5nYCwgaXQgd2lsbCBiZSBjb252ZXJ0ZWQgdG8gb25lIHVzaW5nIGBKU09OLnN0cmluZ2lmeWAuXG4gKlxuICogQHBhcmFtIHtzdHJpbmdbXX0gcGF0aCAtIFRoZSBhcnJheSBvZiBwYXRoIHNlZ21lbnRzXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtoYXNoUHJlZml4PXRydWVdIC0gV2hldGhlciBvciBub3QgY3JlYXRlIGEgaGFzaC1wcmVmaXhlZCBKU09OIFBvaW50ZXJcbiAqXG4gKiBAcmV0dXJucyB7c3RyaW5nfSB0aGUgY29ycmVzcG9uZGluZyBKU09OIFBvaW50ZXJcbiAqXG4gKiBAdGhyb3dzIHtFcnJvcn0gaWYgdGhlIGBwYXRoYCBhcmd1bWVudCBpcyBub3QgYW4gYXJyYXlcbiAqXG4gKiBAYWxpYXMgbW9kdWxlOkpzb25SZWZzLnBhdGhUb1B0clxuICovXG5mdW5jdGlvbiBwYXRoVG9QdHIgKHBhdGgsIGhhc2hQcmVmaXgpIHtcbiAgaWYgKCFpc1R5cGUocGF0aCwgJ0FycmF5JykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3BhdGggbXVzdCBiZSBhbiBBcnJheScpO1xuICB9XG5cbiAgLy8gRW5jb2RlIGVhY2ggc2VnbWVudCBhbmQgcmV0dXJuXG4gIHJldHVybiAoaGFzaFByZWZpeCAhPT0gZmFsc2UgPyAnIycgOiAnJykgKyAocGF0aC5sZW5ndGggPiAwID8gJy8nIDogJycpICsgZW5jb2RlUGF0aChwYXRoKS5qb2luKCcvJyk7XG59XG5cbi8qKlxuICogRmluZHMgSlNPTiBSZWZlcmVuY2VzIGRlZmluZWQgd2l0aGluIHRoZSBwcm92aWRlZCBhcnJheS9vYmplY3QgYW5kIHJlc29sdmVzIHRoZW0uXG4gKlxuICogQHBhcmFtIHthcnJheXxvYmplY3R9IG9iaiAtIFRoZSBzdHJ1Y3R1cmUgdG8gZmluZCBKU09OIFJlZmVyZW5jZXMgd2l0aGluXG4gKiBAcGFyYW0ge21vZHVsZTpKc29uUmVmc35Kc29uUmVmc09wdGlvbnN9IFtvcHRpb25zXSAtIFRoZSBKc29uUmVmcyBvcHRpb25zXG4gKlxuICogQHJldHVybnMge1Byb21pc2V9IGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIGEge0BsaW5rIG1vZHVsZTpKc29uUmVmc35SZXNvbHZlZFJlZnNSZXN1bHRzfSBhbmQgcmVqZWN0cyB3aXRoIGFuXG4gKiBgRXJyb3JgIHdoZW4gdGhlIGlucHV0IGFyZ3VtZW50cyBmYWlsIHZhbGlkYXRpb24sIHdoZW4gYG9wdGlvbnMuc3ViRG9jUGF0aGAgcG9pbnRzIHRvIGFuIGludmFsaWQgbG9jYXRpb24gb3Igd2hlblxuICogIHRoZSBsb2NhdGlvbiBhcmd1bWVudCBwb2ludHMgdG8gYW4gdW5sb2FkYWJsZSByZXNvdXJjZVxuICpcbiAqIEBhbGlhcyBtb2R1bGU6SnNvblJlZnMucmVzb2x2ZVJlZnNcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gRXhhbXBsZSB0aGF0IG9ubHkgcmVzb2x2ZXMgcmVsYXRpdmUgYW5kIHJlbW90ZSByZWZlcmVuY2VzXG4gKiBKc29uUmVmcy5yZXNvbHZlUmVmcyhzd2FnZ2VyT2JqLCB7XG4gKiAgICAgZmlsdGVyOiBbJ3JlbGF0aXZlJywgJ3JlbW90ZSddXG4gKiAgIH0pXG4gKiAgIC50aGVuKGZ1bmN0aW9uIChyZXMpIHtcbiAqICAgICAgLy8gRG8gc29tZXRoaW5nIHdpdGggdGhlIHJlc3BvbnNlXG4gKiAgICAgIC8vXG4gKiAgICAgIC8vIHJlcy5yZWZzOiBKU09OIFJlZmVyZW5jZSBsb2NhdGlvbnMgYW5kIGRldGFpbHNcbiAqICAgICAgLy8gcmVzLnJlc29sdmVkOiBUaGUgZG9jdW1lbnQgd2l0aCB0aGUgYXBwcm9wcmlhdGUgSlNPTiBSZWZlcmVuY2VzIHJlc29sdmVkXG4gKiAgIH0sIGZ1bmN0aW9uIChlcnIpIHtcbiAqICAgICBjb25zb2xlLmxvZyhlcnIuc3RhY2spO1xuICogICB9KTtcbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZVJlZnMgKG9iaiwgb3B0aW9ucykge1xuICB2YXIgYWxsVGFza3MgPSBQcm9taXNlLnJlc29sdmUoKTtcblxuICBhbGxUYXNrcyA9IGFsbFRhc2tzXG4gICAgLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgLy8gVmFsaWRhdGUgdGhlIHByb3ZpZGVkIGRvY3VtZW50XG4gICAgICBpZiAoIWlzVHlwZShvYmosICdBcnJheScpICYmICFpc1R5cGUob2JqLCAnT2JqZWN0JykpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignb2JqIG11c3QgYmUgYW4gQXJyYXkgb3IgYW4gT2JqZWN0Jyk7XG4gICAgICB9XG5cbiAgICAgIC8vIFZhbGlkYXRlIG9wdGlvbnNcbiAgICAgIG9wdGlvbnMgPSB2YWxpZGF0ZU9wdGlvbnMob3B0aW9ucywgb2JqKTtcblxuICAgICAgLy8gQ2xvbmUgdGhlIGlucHV0IHNvIHdlIGRvIG5vdCBhbHRlciBpdFxuICAgICAgb2JqID0gY2xvbmUob2JqKTtcbiAgICB9KVxuICAgIC50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBmaW5kUmVmc1JlY3Vyc2l2ZShvYmosIG9wdGlvbnMsIFtdLCBbXSwge1xuICAgICAgICBkb2N1bWVudHM6IHt9LFxuICAgICAgICByZWZzOiB7fVxuICAgICAgfSk7XG4gICAgfSlcbiAgICAudGhlbihmdW5jdGlvbiAoYWxsUmVmcykge1xuICAgICAgdmFyIGRlZmVycmVkUmVmcyA9IHt9O1xuICAgICAgdmFyIHJlZnMgPSB7fTtcblxuICAgICAgZnVuY3Rpb24gcGF0aFNvcnRlciAocDEsIHAyKSB7XG4gICAgICAgIHJldHVybiBwYXRoRnJvbVB0cihwMSkubGVuZ3RoIC0gcGF0aEZyb21QdHIocDIpLmxlbmd0aDtcbiAgICAgIH1cblxuICAgICAgLy8gUmVzb2x2ZSBhbGwgcmVmZXJlbmNlcyB3aXRoIGEga25vd24gdmFsdWVcbiAgICAgIE9iamVjdC5rZXlzKGFsbFJlZnMucmVmcykuc29ydChwYXRoU29ydGVyKS5mb3JFYWNoKGZ1bmN0aW9uIChyZWZQdHIpIHtcbiAgICAgICAgdmFyIHJlZkRldGFpbHMgPSBhbGxSZWZzLnJlZnNbcmVmUHRyXTtcblxuICAgICAgICAvLyBSZWNvcmQgYWxsIGRpcmVjdCByZWZlcmVuY2VzXG4gICAgICAgIGlmICghcmVmRGV0YWlscy5pbmRpcmVjdCkge1xuICAgICAgICAgIHJlZnNbcmVmUHRyXSA9IHJlZkRldGFpbHM7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEZWxldGUgaGVscGVyIHByb3BlcnR5XG4gICAgICAgIGRlbGV0ZSByZWZEZXRhaWxzLmluZGlyZWN0O1xuXG4gICAgICAgIGlmIChpc1R5cGUocmVmRGV0YWlscy5lcnJvciwgJ1VuZGVmaW5lZCcpICYmIHJlZkRldGFpbHMudHlwZSAhPT0gJ2ludmFsaWQnKSB7XG4gICAgICAgICAgaWYgKGlzVHlwZShyZWZEZXRhaWxzLnZhbHVlLCAnVW5kZWZpbmVkJykgJiYgcmVmRGV0YWlscy5jaXJjdWxhcikge1xuICAgICAgICAgICAgcmVmRGV0YWlscy52YWx1ZSA9IHJlZkRldGFpbHMuZGVmO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIFdlIGRlZmVyIHByb2Nlc3NpbmcgYWxsIHJlZmVyZW5jZXMgd2l0aG91dCBhIHZhbHVlIHVudGlsIGxhdGVyXG4gICAgICAgICAgaWYgKGlzVHlwZShyZWZEZXRhaWxzLnZhbHVlLCAnVW5kZWZpbmVkJykpIHtcbiAgICAgICAgICAgIGRlZmVycmVkUmVmc1tyZWZQdHJdID0gcmVmRGV0YWlscztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHJlZlB0ciA9PT0gJyMnKSB7XG4gICAgICAgICAgICAgIG9iaiA9IHJlZkRldGFpbHMudmFsdWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBzZXRWYWx1ZShvYmosIHBhdGhGcm9tUHRyKHJlZlB0ciksIHJlZkRldGFpbHMudmFsdWUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEZWxldGUgaGVscGVyIHByb3BlcnR5XG4gICAgICAgICAgICBkZWxldGUgcmVmRGV0YWlscy5hbmNlc3RvclB0cnM7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIERlbGV0ZSBoZWxwZXIgcHJvcGVydHlcbiAgICAgICAgICBkZWxldGUgcmVmRGV0YWlscy5hbmNlc3RvclB0cnM7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICAvLyBSZXNvbHZlIGFsbCBkZWZlcnJlZCByZWZlcmVuY2VzXG4gICAgICBPYmplY3Qua2V5cyhkZWZlcnJlZFJlZnMpLmZvckVhY2goZnVuY3Rpb24gKHJlZlB0cikge1xuICAgICAgICB2YXIgcmVmRGV0YWlscyA9IGRlZmVycmVkUmVmc1tyZWZQdHJdO1xuXG4gICAgICAgIC8vIEF0dGVtcHQgdG8gcmVzb2x2ZSB0aGUgdmFsdWUgYWdhaW5zdCBhbGwgaWYgaXRzIGFuY2VzdG9ycyBpbiBvcmRlclxuICAgICAgICByZWZEZXRhaWxzLmFuY2VzdG9yUHRycy5mb3JFYWNoKGZ1bmN0aW9uIChhbmNlc3RvclB0ciwgaW5kZXgpIHtcbiAgICAgICAgICBpZiAoaXNUeXBlKHJlZkRldGFpbHMudmFsdWUsICdVbmRlZmluZWQnKSkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgcmVmRGV0YWlscy52YWx1ZSA9IGZpbmRWYWx1ZShhbGxSZWZzLmRvY3VtZW50c1thbmNlc3RvclB0cl0sIHBhdGhGcm9tUHRyKHJlZkRldGFpbHMudXJpKSk7XG5cbiAgICAgICAgICAgICAgLy8gRGVsZXRlIGhlbHBlciBwcm9wZXJ0eVxuICAgICAgICAgICAgICBkZWxldGUgcmVmRGV0YWlscy5hbmNlc3RvclB0cnM7XG5cbiAgICAgICAgICAgICAgc2V0VmFsdWUob2JqLCBwYXRoRnJvbVB0cihyZWZQdHIpLCByZWZEZXRhaWxzLnZhbHVlKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICBpZiAoaW5kZXggPT09IHJlZkRldGFpbHMuYW5jZXN0b3JQdHJzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgICAgICByZWZEZXRhaWxzLmVycm9yID0gZXJyLm1lc3NhZ2U7XG4gICAgICAgICAgICAgICAgcmVmRGV0YWlscy5taXNzaW5nID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgIC8vIERlbGV0ZSBoZWxwZXIgcHJvcGVydHlcbiAgICAgICAgICAgICAgICBkZWxldGUgcmVmRGV0YWlscy5hbmNlc3RvclB0cnM7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHJlZnM6IHJlZnMsXG4gICAgICAgIHJlc29sdmVkOiBvYmpcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgcmV0dXJuIGFsbFRhc2tzO1xufVxuXG4vKipcbiAqIFJlc29sdmVzIEpTT04gUmVmZXJlbmNlcyBkZWZpbmVkIHdpdGhpbiB0aGUgZG9jdW1lbnQgYXQgdGhlIHByb3ZpZGVkIGxvY2F0aW9uLlxuICpcbiAqIFRoaXMgQVBJIGlzIGlkZW50aWNhbCB0byB7QGxpbmsgbW9kdWxlOkpzb25SZWZzLnJlc29sdmVSZWZzfSBleGNlcHQgdGhpcyBBUEkgd2lsbCByZXRyaWV2ZSBhIHJlbW90ZSBkb2N1bWVudCBhbmQgdGhlblxuICogcmV0dXJuIHRoZSByZXN1bHQgb2Yge0BsaW5rIG1vZHVsZTpKc29uUmVmcy5yZXNvbHZlUmVmc30gb24gdGhlIHJldHJpZXZlZCBkb2N1bWVudC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbG9jYXRpb24gLSBUaGUgbG9jYXRpb24gdG8gcmV0cmlldmUgKihDYW4gYmUgcmVsYXRpdmUgb3IgYWJzb2x1dGUsIGp1c3QgbWFrZSBzdXJlIHlvdSBsb29rIGF0IHRoZVxuICoge0BsaW5rIG1vZHVsZTpKc29uUmVmc35Kc29uUmVmc09wdGlvbnN8b3B0aW9ucyBkb2N1bWVudGF0aW9ufSB0byBzZWUgaG93IHJlbGF0aXZlIHJlZmVyZW5jZXMgYXJlIGhhbmRsZWQuKSpcbiAqIEBwYXJhbSB7bW9kdWxlOkpzb25SZWZzfkpzb25SZWZzT3B0aW9uc30gW29wdGlvbnNdIC0gVGhlIEpzb25SZWZzIG9wdGlvbnNcbiAqXG4gKiBAcmV0dXJucyB7UHJvbWlzZX0gYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgYSB7QGxpbmsgbW9kdWxlOkpzb25SZWZzflJldHJpZXZlZFJlc29sdmVkUmVmc1Jlc3VsdHN9IGFuZCByZWplY3RzIHdpdGggYW5cbiAqIGBFcnJvcmAgd2hlbiB0aGUgaW5wdXQgYXJndW1lbnRzIGZhaWwgdmFsaWRhdGlvbiwgd2hlbiBgb3B0aW9ucy5zdWJEb2NQYXRoYCBwb2ludHMgdG8gYW4gaW52YWxpZCBsb2NhdGlvbiBvciB3aGVuXG4gKiAgdGhlIGxvY2F0aW9uIGFyZ3VtZW50IHBvaW50cyB0byBhbiB1bmxvYWRhYmxlIHJlc291cmNlXG4gKlxuICogQGFsaWFzIG1vZHVsZTpKc29uUmVmcy5yZXNvbHZlUmVmc0F0XG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIEV4YW1wbGUgdGhhdCBsb2FkcyBhIEpTT04gZG9jdW1lbnQgKE5vIG9wdGlvbnMubG9hZGVyT3B0aW9ucy5wcm9jZXNzQ29udGVudCByZXF1aXJlZCkgYW5kIHJlc29sdmVzIGFsbCByZWZlcmVuY2VzXG4gKiBKc29uUmVmcy5yZXNvbHZlUmVmc0F0KCcuL3N3YWdnZXIuanNvbicpXG4gKiAgIC50aGVuKGZ1bmN0aW9uIChyZXMpIHtcbiAqICAgICAgLy8gRG8gc29tZXRoaW5nIHdpdGggdGhlIHJlc3BvbnNlXG4gKiAgICAgIC8vXG4gKiAgICAgIC8vIHJlcy5yZWZzOiBKU09OIFJlZmVyZW5jZSBsb2NhdGlvbnMgYW5kIGRldGFpbHNcbiAqICAgICAgLy8gcmVzLnJlc29sdmVkOiBUaGUgZG9jdW1lbnQgd2l0aCB0aGUgYXBwcm9wcmlhdGUgSlNPTiBSZWZlcmVuY2VzIHJlc29sdmVkXG4gKiAgICAgIC8vIHJlcy52YWx1ZTogVGhlIHJldHJpZXZlZCBkb2N1bWVudFxuICogICB9LCBmdW5jdGlvbiAoZXJyKSB7XG4gKiAgICAgY29uc29sZS5sb2coZXJyLnN0YWNrKTtcbiAqICAgfSk7XG4gKi9cbmZ1bmN0aW9uIHJlc29sdmVSZWZzQXQgKGxvY2F0aW9uLCBvcHRpb25zKSB7XG4gIHZhciBhbGxUYXNrcyA9IFByb21pc2UucmVzb2x2ZSgpO1xuXG4gIGFsbFRhc2tzID0gYWxsVGFza3NcbiAgICAudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBWYWxpZGF0ZSB0aGUgcHJvdmlkZWQgbG9jYXRpb25cbiAgICAgIGlmICghaXNUeXBlKGxvY2F0aW9uLCAnU3RyaW5nJykpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbG9jYXRpb24gbXVzdCBiZSBhIHN0cmluZycpO1xuICAgICAgfVxuXG4gICAgICAvLyBWYWxpZGF0ZSBvcHRpb25zXG4gICAgICBvcHRpb25zID0gdmFsaWRhdGVPcHRpb25zKG9wdGlvbnMpO1xuXG4gICAgICAvLyBDb21iaW5lIHRoZSBsb2NhdGlvbiBhbmQgdGhlIG9wdGlvbmFsIHJlbGF0aXZlIGJhc2VcbiAgICAgIGxvY2F0aW9uID0gY29tYmluZVVSSXMob3B0aW9ucy5yZWxhdGl2ZUJhc2UsIGxvY2F0aW9uKTtcblxuICAgICAgcmV0dXJuIGdldFJlbW90ZURvY3VtZW50KGxvY2F0aW9uLCBvcHRpb25zKTtcbiAgICB9KVxuICAgIC50aGVuKGZ1bmN0aW9uIChyZXMpIHtcbiAgICAgIHZhciBjT3B0aW9ucyA9IGNsb25lKG9wdGlvbnMpO1xuICAgICAgdmFyIHVyaURldGFpbHMgPSBwYXJzZVVSSShsb2NhdGlvbik7XG5cbiAgICAgIC8vIFNldCB0aGUgc3ViIGRvY3VtZW50IHBhdGggaWYgbmVjZXNzYXJ5XG4gICAgICBpZiAoIWlzVHlwZSh1cmlEZXRhaWxzLmZyYWdtZW50LCAnVW5kZWZpbmVkJykpIHtcbiAgICAgICAgY09wdGlvbnMuc3ViRG9jUGF0aCA9IHBhdGhGcm9tUHRyKGRlY29kZVVSSSh1cmlEZXRhaWxzLmZyYWdtZW50KSk7XG4gICAgICB9XG5cbiAgICAgIC8vIFVwZGF0ZSB0aGUgcmVsYXRpdmUgYmFzZSBiYXNlZCBvbiB0aGUgcmV0cmlldmVkIGxvY2F0aW9uXG4gICAgICBjT3B0aW9ucy5yZWxhdGl2ZUJhc2UgPSBwYXRoLmRpcm5hbWUobG9jYXRpb24pO1xuXG4gICAgICByZXR1cm4gcmVzb2x2ZVJlZnMocmVzLCBjT3B0aW9ucylcbiAgICAgICAgLnRoZW4oZnVuY3Rpb24gKHJlczIpIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcmVmczogcmVzMi5yZWZzLFxuICAgICAgICAgICAgcmVzb2x2ZWQ6IHJlczIucmVzb2x2ZWQsXG4gICAgICAgICAgICB2YWx1ZTogcmVzXG4gICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgcmV0dXJuIGFsbFRhc2tzO1xufVxuXG4vKiBFeHBvcnQgdGhlIG1vZHVsZSBtZW1iZXJzICovXG5tb2R1bGUuZXhwb3J0cy5jbGVhckNhY2hlID0gY2xlYXJDYWNoZTtcbm1vZHVsZS5leHBvcnRzLmRlY29kZVBhdGggPSBkZWNvZGVQYXRoO1xubW9kdWxlLmV4cG9ydHMuZW5jb2RlUGF0aCA9IGVuY29kZVBhdGg7XG5tb2R1bGUuZXhwb3J0cy5maW5kUmVmcyA9IGZpbmRSZWZzO1xubW9kdWxlLmV4cG9ydHMuZmluZFJlZnNBdCA9IGZpbmRSZWZzQXQ7XG5tb2R1bGUuZXhwb3J0cy5nZXRSZWZEZXRhaWxzID0gZ2V0UmVmRGV0YWlscztcbm1vZHVsZS5leHBvcnRzLmlzUHRyID0gaXNQdHI7XG5tb2R1bGUuZXhwb3J0cy5pc1JlZiA9IGlzUmVmO1xubW9kdWxlLmV4cG9ydHMucGF0aEZyb21QdHIgPSBwYXRoRnJvbVB0cjtcbm1vZHVsZS5leHBvcnRzLnBhdGhUb1B0ciA9IHBhdGhUb1B0cjtcbm1vZHVsZS5leHBvcnRzLnJlc29sdmVSZWZzID0gcmVzb2x2ZVJlZnM7XG5tb2R1bGUuZXhwb3J0cy5yZXNvbHZlUmVmc0F0ID0gcmVzb2x2ZVJlZnNBdDtcbiIsIlxuLyoqXG4gKiBFeHBvc2UgYEVtaXR0ZXJgLlxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gRW1pdHRlcjtcblxuLyoqXG4gKiBJbml0aWFsaXplIGEgbmV3IGBFbWl0dGVyYC5cbiAqXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmZ1bmN0aW9uIEVtaXR0ZXIob2JqKSB7XG4gIGlmIChvYmopIHJldHVybiBtaXhpbihvYmopO1xufTtcblxuLyoqXG4gKiBNaXhpbiB0aGUgZW1pdHRlciBwcm9wZXJ0aWVzLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmpcbiAqIEByZXR1cm4ge09iamVjdH1cbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbmZ1bmN0aW9uIG1peGluKG9iaikge1xuICBmb3IgKHZhciBrZXkgaW4gRW1pdHRlci5wcm90b3R5cGUpIHtcbiAgICBvYmpba2V5XSA9IEVtaXR0ZXIucHJvdG90eXBlW2tleV07XG4gIH1cbiAgcmV0dXJuIG9iajtcbn1cblxuLyoqXG4gKiBMaXN0ZW4gb24gdGhlIGdpdmVuIGBldmVudGAgd2l0aCBgZm5gLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBldmVudFxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm5cbiAqIEByZXR1cm4ge0VtaXR0ZXJ9XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbkVtaXR0ZXIucHJvdG90eXBlLm9uID1cbkVtaXR0ZXIucHJvdG90eXBlLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbihldmVudCwgZm4pe1xuICB0aGlzLl9jYWxsYmFja3MgPSB0aGlzLl9jYWxsYmFja3MgfHwge307XG4gICh0aGlzLl9jYWxsYmFja3NbJyQnICsgZXZlbnRdID0gdGhpcy5fY2FsbGJhY2tzWyckJyArIGV2ZW50XSB8fCBbXSlcbiAgICAucHVzaChmbik7XG4gIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4gKiBBZGRzIGFuIGBldmVudGAgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgYSBzaW5nbGVcbiAqIHRpbWUgdGhlbiBhdXRvbWF0aWNhbGx5IHJlbW92ZWQuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGV2ZW50XG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmblxuICogQHJldHVybiB7RW1pdHRlcn1cbiAqIEBhcGkgcHVibGljXG4gKi9cblxuRW1pdHRlci5wcm90b3R5cGUub25jZSA9IGZ1bmN0aW9uKGV2ZW50LCBmbil7XG4gIGZ1bmN0aW9uIG9uKCkge1xuICAgIHRoaXMub2ZmKGV2ZW50LCBvbik7XG4gICAgZm4uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgfVxuXG4gIG9uLmZuID0gZm47XG4gIHRoaXMub24oZXZlbnQsIG9uKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFJlbW92ZSB0aGUgZ2l2ZW4gY2FsbGJhY2sgZm9yIGBldmVudGAgb3IgYWxsXG4gKiByZWdpc3RlcmVkIGNhbGxiYWNrcy5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gZXZlbnRcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuXG4gKiBAcmV0dXJuIHtFbWl0dGVyfVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5FbWl0dGVyLnByb3RvdHlwZS5vZmYgPVxuRW1pdHRlci5wcm90b3R5cGUucmVtb3ZlTGlzdGVuZXIgPVxuRW1pdHRlci5wcm90b3R5cGUucmVtb3ZlQWxsTGlzdGVuZXJzID1cbkVtaXR0ZXIucHJvdG90eXBlLnJlbW92ZUV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbihldmVudCwgZm4pe1xuICB0aGlzLl9jYWxsYmFja3MgPSB0aGlzLl9jYWxsYmFja3MgfHwge307XG5cbiAgLy8gYWxsXG4gIGlmICgwID09IGFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICB0aGlzLl9jYWxsYmFja3MgPSB7fTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8vIHNwZWNpZmljIGV2ZW50XG4gIHZhciBjYWxsYmFja3MgPSB0aGlzLl9jYWxsYmFja3NbJyQnICsgZXZlbnRdO1xuICBpZiAoIWNhbGxiYWNrcykgcmV0dXJuIHRoaXM7XG5cbiAgLy8gcmVtb3ZlIGFsbCBoYW5kbGVyc1xuICBpZiAoMSA9PSBhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgZGVsZXRlIHRoaXMuX2NhbGxiYWNrc1snJCcgKyBldmVudF07XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvLyByZW1vdmUgc3BlY2lmaWMgaGFuZGxlclxuICB2YXIgY2I7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgY2FsbGJhY2tzLmxlbmd0aDsgaSsrKSB7XG4gICAgY2IgPSBjYWxsYmFja3NbaV07XG4gICAgaWYgKGNiID09PSBmbiB8fCBjYi5mbiA9PT0gZm4pIHtcbiAgICAgIGNhbGxiYWNrcy5zcGxpY2UoaSwgMSk7XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIEVtaXQgYGV2ZW50YCB3aXRoIHRoZSBnaXZlbiBhcmdzLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBldmVudFxuICogQHBhcmFtIHtNaXhlZH0gLi4uXG4gKiBAcmV0dXJuIHtFbWl0dGVyfVxuICovXG5cbkVtaXR0ZXIucHJvdG90eXBlLmVtaXQgPSBmdW5jdGlvbihldmVudCl7XG4gIHRoaXMuX2NhbGxiYWNrcyA9IHRoaXMuX2NhbGxiYWNrcyB8fCB7fTtcbiAgdmFyIGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSlcbiAgICAsIGNhbGxiYWNrcyA9IHRoaXMuX2NhbGxiYWNrc1snJCcgKyBldmVudF07XG5cbiAgaWYgKGNhbGxiYWNrcykge1xuICAgIGNhbGxiYWNrcyA9IGNhbGxiYWNrcy5zbGljZSgwKTtcbiAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gY2FsbGJhY2tzLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7XG4gICAgICBjYWxsYmFja3NbaV0uYXBwbHkodGhpcywgYXJncyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFJldHVybiBhcnJheSBvZiBjYWxsYmFja3MgZm9yIGBldmVudGAuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGV2ZW50XG4gKiBAcmV0dXJuIHtBcnJheX1cbiAqIEBhcGkgcHVibGljXG4gKi9cblxuRW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJzID0gZnVuY3Rpb24oZXZlbnQpe1xuICB0aGlzLl9jYWxsYmFja3MgPSB0aGlzLl9jYWxsYmFja3MgfHwge307XG4gIHJldHVybiB0aGlzLl9jYWxsYmFja3NbJyQnICsgZXZlbnRdIHx8IFtdO1xufTtcblxuLyoqXG4gKiBDaGVjayBpZiB0aGlzIGVtaXR0ZXIgaGFzIGBldmVudGAgaGFuZGxlcnMuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGV2ZW50XG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5FbWl0dGVyLnByb3RvdHlwZS5oYXNMaXN0ZW5lcnMgPSBmdW5jdGlvbihldmVudCl7XG4gIHJldHVybiAhISB0aGlzLmxpc3RlbmVycyhldmVudCkubGVuZ3RoO1xufTtcbiIsIi8qISBOYXRpdmUgUHJvbWlzZSBPbmx5XG4gICAgdjAuOC4xIChjKSBLeWxlIFNpbXBzb25cbiAgICBNSVQgTGljZW5zZTogaHR0cDovL2dldGlmeS5taXQtbGljZW5zZS5vcmdcbiovXG5cbihmdW5jdGlvbiBVTUQobmFtZSxjb250ZXh0LGRlZmluaXRpb24pe1xuXHQvLyBzcGVjaWFsIGZvcm0gb2YgVU1EIGZvciBwb2x5ZmlsbGluZyBhY3Jvc3MgZXZpcm9ubWVudHNcblx0Y29udGV4dFtuYW1lXSA9IGNvbnRleHRbbmFtZV0gfHwgZGVmaW5pdGlvbigpO1xuXHRpZiAodHlwZW9mIG1vZHVsZSAhPSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzKSB7IG1vZHVsZS5leHBvcnRzID0gY29udGV4dFtuYW1lXTsgfVxuXHRlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7IGRlZmluZShmdW5jdGlvbiAkQU1EJCgpeyByZXR1cm4gY29udGV4dFtuYW1lXTsgfSk7IH1cbn0pKFwiUHJvbWlzZVwiLHR5cGVvZiBnbG9iYWwgIT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHRoaXMsZnVuY3Rpb24gREVGKCl7XG5cdC8qanNoaW50IHZhbGlkdGhpczp0cnVlICovXG5cdFwidXNlIHN0cmljdFwiO1xuXG5cdHZhciBidWlsdEluUHJvcCwgY3ljbGUsIHNjaGVkdWxpbmdfcXVldWUsXG5cdFx0VG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLFxuXHRcdHRpbWVyID0gKHR5cGVvZiBzZXRJbW1lZGlhdGUgIT0gXCJ1bmRlZmluZWRcIikgP1xuXHRcdFx0ZnVuY3Rpb24gdGltZXIoZm4pIHsgcmV0dXJuIHNldEltbWVkaWF0ZShmbik7IH0gOlxuXHRcdFx0c2V0VGltZW91dFxuXHQ7XG5cblx0Ly8gZGFtbWl0LCBJRTguXG5cdHRyeSB7XG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LFwieFwiLHt9KTtcblx0XHRidWlsdEluUHJvcCA9IGZ1bmN0aW9uIGJ1aWx0SW5Qcm9wKG9iaixuYW1lLHZhbCxjb25maWcpIHtcblx0XHRcdHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLG5hbWUse1xuXHRcdFx0XHR2YWx1ZTogdmFsLFxuXHRcdFx0XHR3cml0YWJsZTogdHJ1ZSxcblx0XHRcdFx0Y29uZmlndXJhYmxlOiBjb25maWcgIT09IGZhbHNlXG5cdFx0XHR9KTtcblx0XHR9O1xuXHR9XG5cdGNhdGNoIChlcnIpIHtcblx0XHRidWlsdEluUHJvcCA9IGZ1bmN0aW9uIGJ1aWx0SW5Qcm9wKG9iaixuYW1lLHZhbCkge1xuXHRcdFx0b2JqW25hbWVdID0gdmFsO1xuXHRcdFx0cmV0dXJuIG9iajtcblx0XHR9O1xuXHR9XG5cblx0Ly8gTm90ZTogdXNpbmcgYSBxdWV1ZSBpbnN0ZWFkIG9mIGFycmF5IGZvciBlZmZpY2llbmN5XG5cdHNjaGVkdWxpbmdfcXVldWUgPSAoZnVuY3Rpb24gUXVldWUoKSB7XG5cdFx0dmFyIGZpcnN0LCBsYXN0LCBpdGVtO1xuXG5cdFx0ZnVuY3Rpb24gSXRlbShmbixzZWxmKSB7XG5cdFx0XHR0aGlzLmZuID0gZm47XG5cdFx0XHR0aGlzLnNlbGYgPSBzZWxmO1xuXHRcdFx0dGhpcy5uZXh0ID0gdm9pZCAwO1xuXHRcdH1cblxuXHRcdHJldHVybiB7XG5cdFx0XHRhZGQ6IGZ1bmN0aW9uIGFkZChmbixzZWxmKSB7XG5cdFx0XHRcdGl0ZW0gPSBuZXcgSXRlbShmbixzZWxmKTtcblx0XHRcdFx0aWYgKGxhc3QpIHtcblx0XHRcdFx0XHRsYXN0Lm5leHQgPSBpdGVtO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdGZpcnN0ID0gaXRlbTtcblx0XHRcdFx0fVxuXHRcdFx0XHRsYXN0ID0gaXRlbTtcblx0XHRcdFx0aXRlbSA9IHZvaWQgMDtcblx0XHRcdH0sXG5cdFx0XHRkcmFpbjogZnVuY3Rpb24gZHJhaW4oKSB7XG5cdFx0XHRcdHZhciBmID0gZmlyc3Q7XG5cdFx0XHRcdGZpcnN0ID0gbGFzdCA9IGN5Y2xlID0gdm9pZCAwO1xuXG5cdFx0XHRcdHdoaWxlIChmKSB7XG5cdFx0XHRcdFx0Zi5mbi5jYWxsKGYuc2VsZik7XG5cdFx0XHRcdFx0ZiA9IGYubmV4dDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH07XG5cdH0pKCk7XG5cblx0ZnVuY3Rpb24gc2NoZWR1bGUoZm4sc2VsZikge1xuXHRcdHNjaGVkdWxpbmdfcXVldWUuYWRkKGZuLHNlbGYpO1xuXHRcdGlmICghY3ljbGUpIHtcblx0XHRcdGN5Y2xlID0gdGltZXIoc2NoZWR1bGluZ19xdWV1ZS5kcmFpbik7XG5cdFx0fVxuXHR9XG5cblx0Ly8gcHJvbWlzZSBkdWNrIHR5cGluZ1xuXHRmdW5jdGlvbiBpc1RoZW5hYmxlKG8pIHtcblx0XHR2YXIgX3RoZW4sIG9fdHlwZSA9IHR5cGVvZiBvO1xuXG5cdFx0aWYgKG8gIT0gbnVsbCAmJlxuXHRcdFx0KFxuXHRcdFx0XHRvX3R5cGUgPT0gXCJvYmplY3RcIiB8fCBvX3R5cGUgPT0gXCJmdW5jdGlvblwiXG5cdFx0XHQpXG5cdFx0KSB7XG5cdFx0XHRfdGhlbiA9IG8udGhlbjtcblx0XHR9XG5cdFx0cmV0dXJuIHR5cGVvZiBfdGhlbiA9PSBcImZ1bmN0aW9uXCIgPyBfdGhlbiA6IGZhbHNlO1xuXHR9XG5cblx0ZnVuY3Rpb24gbm90aWZ5KCkge1xuXHRcdGZvciAodmFyIGk9MDsgaTx0aGlzLmNoYWluLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRub3RpZnlJc29sYXRlZChcblx0XHRcdFx0dGhpcyxcblx0XHRcdFx0KHRoaXMuc3RhdGUgPT09IDEpID8gdGhpcy5jaGFpbltpXS5zdWNjZXNzIDogdGhpcy5jaGFpbltpXS5mYWlsdXJlLFxuXHRcdFx0XHR0aGlzLmNoYWluW2ldXG5cdFx0XHQpO1xuXHRcdH1cblx0XHR0aGlzLmNoYWluLmxlbmd0aCA9IDA7XG5cdH1cblxuXHQvLyBOT1RFOiBUaGlzIGlzIGEgc2VwYXJhdGUgZnVuY3Rpb24gdG8gaXNvbGF0ZVxuXHQvLyB0aGUgYHRyeS4uY2F0Y2hgIHNvIHRoYXQgb3RoZXIgY29kZSBjYW4gYmVcblx0Ly8gb3B0aW1pemVkIGJldHRlclxuXHRmdW5jdGlvbiBub3RpZnlJc29sYXRlZChzZWxmLGNiLGNoYWluKSB7XG5cdFx0dmFyIHJldCwgX3RoZW47XG5cdFx0dHJ5IHtcblx0XHRcdGlmIChjYiA9PT0gZmFsc2UpIHtcblx0XHRcdFx0Y2hhaW4ucmVqZWN0KHNlbGYubXNnKTtcblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHRpZiAoY2IgPT09IHRydWUpIHtcblx0XHRcdFx0XHRyZXQgPSBzZWxmLm1zZztcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHRyZXQgPSBjYi5jYWxsKHZvaWQgMCxzZWxmLm1zZyk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAocmV0ID09PSBjaGFpbi5wcm9taXNlKSB7XG5cdFx0XHRcdFx0Y2hhaW4ucmVqZWN0KFR5cGVFcnJvcihcIlByb21pc2UtY2hhaW4gY3ljbGVcIikpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2UgaWYgKF90aGVuID0gaXNUaGVuYWJsZShyZXQpKSB7XG5cdFx0XHRcdFx0X3RoZW4uY2FsbChyZXQsY2hhaW4ucmVzb2x2ZSxjaGFpbi5yZWplY3QpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdGNoYWluLnJlc29sdmUocmV0KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRjYXRjaCAoZXJyKSB7XG5cdFx0XHRjaGFpbi5yZWplY3QoZXJyKTtcblx0XHR9XG5cdH1cblxuXHRmdW5jdGlvbiByZXNvbHZlKG1zZykge1xuXHRcdHZhciBfdGhlbiwgc2VsZiA9IHRoaXM7XG5cblx0XHQvLyBhbHJlYWR5IHRyaWdnZXJlZD9cblx0XHRpZiAoc2VsZi50cmlnZ2VyZWQpIHsgcmV0dXJuOyB9XG5cblx0XHRzZWxmLnRyaWdnZXJlZCA9IHRydWU7XG5cblx0XHQvLyB1bndyYXBcblx0XHRpZiAoc2VsZi5kZWYpIHtcblx0XHRcdHNlbGYgPSBzZWxmLmRlZjtcblx0XHR9XG5cblx0XHR0cnkge1xuXHRcdFx0aWYgKF90aGVuID0gaXNUaGVuYWJsZShtc2cpKSB7XG5cdFx0XHRcdHNjaGVkdWxlKGZ1bmN0aW9uKCl7XG5cdFx0XHRcdFx0dmFyIGRlZl93cmFwcGVyID0gbmV3IE1ha2VEZWZXcmFwcGVyKHNlbGYpO1xuXHRcdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0XHRfdGhlbi5jYWxsKG1zZyxcblx0XHRcdFx0XHRcdFx0ZnVuY3Rpb24gJHJlc29sdmUkKCl7IHJlc29sdmUuYXBwbHkoZGVmX3dyYXBwZXIsYXJndW1lbnRzKTsgfSxcblx0XHRcdFx0XHRcdFx0ZnVuY3Rpb24gJHJlamVjdCQoKXsgcmVqZWN0LmFwcGx5KGRlZl93cmFwcGVyLGFyZ3VtZW50cyk7IH1cblx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGNhdGNoIChlcnIpIHtcblx0XHRcdFx0XHRcdHJlamVjdC5jYWxsKGRlZl93cmFwcGVyLGVycik7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KVxuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdHNlbGYubXNnID0gbXNnO1xuXHRcdFx0XHRzZWxmLnN0YXRlID0gMTtcblx0XHRcdFx0aWYgKHNlbGYuY2hhaW4ubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdHNjaGVkdWxlKG5vdGlmeSxzZWxmKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRjYXRjaCAoZXJyKSB7XG5cdFx0XHRyZWplY3QuY2FsbChuZXcgTWFrZURlZldyYXBwZXIoc2VsZiksZXJyKTtcblx0XHR9XG5cdH1cblxuXHRmdW5jdGlvbiByZWplY3QobXNnKSB7XG5cdFx0dmFyIHNlbGYgPSB0aGlzO1xuXG5cdFx0Ly8gYWxyZWFkeSB0cmlnZ2VyZWQ/XG5cdFx0aWYgKHNlbGYudHJpZ2dlcmVkKSB7IHJldHVybjsgfVxuXG5cdFx0c2VsZi50cmlnZ2VyZWQgPSB0cnVlO1xuXG5cdFx0Ly8gdW53cmFwXG5cdFx0aWYgKHNlbGYuZGVmKSB7XG5cdFx0XHRzZWxmID0gc2VsZi5kZWY7XG5cdFx0fVxuXG5cdFx0c2VsZi5tc2cgPSBtc2c7XG5cdFx0c2VsZi5zdGF0ZSA9IDI7XG5cdFx0aWYgKHNlbGYuY2hhaW4ubGVuZ3RoID4gMCkge1xuXHRcdFx0c2NoZWR1bGUobm90aWZ5LHNlbGYpO1xuXHRcdH1cblx0fVxuXG5cdGZ1bmN0aW9uIGl0ZXJhdGVQcm9taXNlcyhDb25zdHJ1Y3RvcixhcnIscmVzb2x2ZXIscmVqZWN0ZXIpIHtcblx0XHRmb3IgKHZhciBpZHg9MDsgaWR4PGFyci5sZW5ndGg7IGlkeCsrKSB7XG5cdFx0XHQoZnVuY3Rpb24gSUlGRShpZHgpe1xuXHRcdFx0XHRDb25zdHJ1Y3Rvci5yZXNvbHZlKGFycltpZHhdKVxuXHRcdFx0XHQudGhlbihcblx0XHRcdFx0XHRmdW5jdGlvbiAkcmVzb2x2ZXIkKG1zZyl7XG5cdFx0XHRcdFx0XHRyZXNvbHZlcihpZHgsbXNnKTtcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdHJlamVjdGVyXG5cdFx0XHRcdCk7XG5cdFx0XHR9KShpZHgpO1xuXHRcdH1cblx0fVxuXG5cdGZ1bmN0aW9uIE1ha2VEZWZXcmFwcGVyKHNlbGYpIHtcblx0XHR0aGlzLmRlZiA9IHNlbGY7XG5cdFx0dGhpcy50cmlnZ2VyZWQgPSBmYWxzZTtcblx0fVxuXG5cdGZ1bmN0aW9uIE1ha2VEZWYoc2VsZikge1xuXHRcdHRoaXMucHJvbWlzZSA9IHNlbGY7XG5cdFx0dGhpcy5zdGF0ZSA9IDA7XG5cdFx0dGhpcy50cmlnZ2VyZWQgPSBmYWxzZTtcblx0XHR0aGlzLmNoYWluID0gW107XG5cdFx0dGhpcy5tc2cgPSB2b2lkIDA7XG5cdH1cblxuXHRmdW5jdGlvbiBQcm9taXNlKGV4ZWN1dG9yKSB7XG5cdFx0aWYgKHR5cGVvZiBleGVjdXRvciAhPSBcImZ1bmN0aW9uXCIpIHtcblx0XHRcdHRocm93IFR5cGVFcnJvcihcIk5vdCBhIGZ1bmN0aW9uXCIpO1xuXHRcdH1cblxuXHRcdGlmICh0aGlzLl9fTlBPX18gIT09IDApIHtcblx0XHRcdHRocm93IFR5cGVFcnJvcihcIk5vdCBhIHByb21pc2VcIik7XG5cdFx0fVxuXG5cdFx0Ly8gaW5zdGFuY2Ugc2hhZG93aW5nIHRoZSBpbmhlcml0ZWQgXCJicmFuZFwiXG5cdFx0Ly8gdG8gc2lnbmFsIGFuIGFscmVhZHkgXCJpbml0aWFsaXplZFwiIHByb21pc2Vcblx0XHR0aGlzLl9fTlBPX18gPSAxO1xuXG5cdFx0dmFyIGRlZiA9IG5ldyBNYWtlRGVmKHRoaXMpO1xuXG5cdFx0dGhpc1tcInRoZW5cIl0gPSBmdW5jdGlvbiB0aGVuKHN1Y2Nlc3MsZmFpbHVyZSkge1xuXHRcdFx0dmFyIG8gPSB7XG5cdFx0XHRcdHN1Y2Nlc3M6IHR5cGVvZiBzdWNjZXNzID09IFwiZnVuY3Rpb25cIiA/IHN1Y2Nlc3MgOiB0cnVlLFxuXHRcdFx0XHRmYWlsdXJlOiB0eXBlb2YgZmFpbHVyZSA9PSBcImZ1bmN0aW9uXCIgPyBmYWlsdXJlIDogZmFsc2Vcblx0XHRcdH07XG5cdFx0XHQvLyBOb3RlOiBgdGhlbiguLilgIGl0c2VsZiBjYW4gYmUgYm9ycm93ZWQgdG8gYmUgdXNlZCBhZ2FpbnN0XG5cdFx0XHQvLyBhIGRpZmZlcmVudCBwcm9taXNlIGNvbnN0cnVjdG9yIGZvciBtYWtpbmcgdGhlIGNoYWluZWQgcHJvbWlzZSxcblx0XHRcdC8vIGJ5IHN1YnN0aXR1dGluZyBhIGRpZmZlcmVudCBgdGhpc2AgYmluZGluZy5cblx0XHRcdG8ucHJvbWlzZSA9IG5ldyB0aGlzLmNvbnN0cnVjdG9yKGZ1bmN0aW9uIGV4dHJhY3RDaGFpbihyZXNvbHZlLHJlamVjdCkge1xuXHRcdFx0XHRpZiAodHlwZW9mIHJlc29sdmUgIT0gXCJmdW5jdGlvblwiIHx8IHR5cGVvZiByZWplY3QgIT0gXCJmdW5jdGlvblwiKSB7XG5cdFx0XHRcdFx0dGhyb3cgVHlwZUVycm9yKFwiTm90IGEgZnVuY3Rpb25cIik7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRvLnJlc29sdmUgPSByZXNvbHZlO1xuXHRcdFx0XHRvLnJlamVjdCA9IHJlamVjdDtcblx0XHRcdH0pO1xuXHRcdFx0ZGVmLmNoYWluLnB1c2gobyk7XG5cblx0XHRcdGlmIChkZWYuc3RhdGUgIT09IDApIHtcblx0XHRcdFx0c2NoZWR1bGUobm90aWZ5LGRlZik7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBvLnByb21pc2U7XG5cdFx0fTtcblx0XHR0aGlzW1wiY2F0Y2hcIl0gPSBmdW5jdGlvbiAkY2F0Y2gkKGZhaWx1cmUpIHtcblx0XHRcdHJldHVybiB0aGlzLnRoZW4odm9pZCAwLGZhaWx1cmUpO1xuXHRcdH07XG5cblx0XHR0cnkge1xuXHRcdFx0ZXhlY3V0b3IuY2FsbChcblx0XHRcdFx0dm9pZCAwLFxuXHRcdFx0XHRmdW5jdGlvbiBwdWJsaWNSZXNvbHZlKG1zZyl7XG5cdFx0XHRcdFx0cmVzb2x2ZS5jYWxsKGRlZixtc2cpO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRmdW5jdGlvbiBwdWJsaWNSZWplY3QobXNnKSB7XG5cdFx0XHRcdFx0cmVqZWN0LmNhbGwoZGVmLG1zZyk7XG5cdFx0XHRcdH1cblx0XHRcdCk7XG5cdFx0fVxuXHRcdGNhdGNoIChlcnIpIHtcblx0XHRcdHJlamVjdC5jYWxsKGRlZixlcnIpO1xuXHRcdH1cblx0fVxuXG5cdHZhciBQcm9taXNlUHJvdG90eXBlID0gYnVpbHRJblByb3Aoe30sXCJjb25zdHJ1Y3RvclwiLFByb21pc2UsXG5cdFx0Lypjb25maWd1cmFibGU9Ki9mYWxzZVxuXHQpO1xuXG5cdC8vIE5vdGU6IEFuZHJvaWQgNCBjYW5ub3QgdXNlIGBPYmplY3QuZGVmaW5lUHJvcGVydHkoLi4pYCBoZXJlXG5cdFByb21pc2UucHJvdG90eXBlID0gUHJvbWlzZVByb3RvdHlwZTtcblxuXHQvLyBidWlsdC1pbiBcImJyYW5kXCIgdG8gc2lnbmFsIGFuIFwidW5pbml0aWFsaXplZFwiIHByb21pc2Vcblx0YnVpbHRJblByb3AoUHJvbWlzZVByb3RvdHlwZSxcIl9fTlBPX19cIiwwLFxuXHRcdC8qY29uZmlndXJhYmxlPSovZmFsc2Vcblx0KTtcblxuXHRidWlsdEluUHJvcChQcm9taXNlLFwicmVzb2x2ZVwiLGZ1bmN0aW9uIFByb21pc2UkcmVzb2x2ZShtc2cpIHtcblx0XHR2YXIgQ29uc3RydWN0b3IgPSB0aGlzO1xuXG5cdFx0Ly8gc3BlYyBtYW5kYXRlZCBjaGVja3Ncblx0XHQvLyBub3RlOiBiZXN0IFwiaXNQcm9taXNlXCIgY2hlY2sgdGhhdCdzIHByYWN0aWNhbCBmb3Igbm93XG5cdFx0aWYgKG1zZyAmJiB0eXBlb2YgbXNnID09IFwib2JqZWN0XCIgJiYgbXNnLl9fTlBPX18gPT09IDEpIHtcblx0XHRcdHJldHVybiBtc2c7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIG5ldyBDb25zdHJ1Y3RvcihmdW5jdGlvbiBleGVjdXRvcihyZXNvbHZlLHJlamVjdCl7XG5cdFx0XHRpZiAodHlwZW9mIHJlc29sdmUgIT0gXCJmdW5jdGlvblwiIHx8IHR5cGVvZiByZWplY3QgIT0gXCJmdW5jdGlvblwiKSB7XG5cdFx0XHRcdHRocm93IFR5cGVFcnJvcihcIk5vdCBhIGZ1bmN0aW9uXCIpO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXNvbHZlKG1zZyk7XG5cdFx0fSk7XG5cdH0pO1xuXG5cdGJ1aWx0SW5Qcm9wKFByb21pc2UsXCJyZWplY3RcIixmdW5jdGlvbiBQcm9taXNlJHJlamVjdChtc2cpIHtcblx0XHRyZXR1cm4gbmV3IHRoaXMoZnVuY3Rpb24gZXhlY3V0b3IocmVzb2x2ZSxyZWplY3Qpe1xuXHRcdFx0aWYgKHR5cGVvZiByZXNvbHZlICE9IFwiZnVuY3Rpb25cIiB8fCB0eXBlb2YgcmVqZWN0ICE9IFwiZnVuY3Rpb25cIikge1xuXHRcdFx0XHR0aHJvdyBUeXBlRXJyb3IoXCJOb3QgYSBmdW5jdGlvblwiKTtcblx0XHRcdH1cblxuXHRcdFx0cmVqZWN0KG1zZyk7XG5cdFx0fSk7XG5cdH0pO1xuXG5cdGJ1aWx0SW5Qcm9wKFByb21pc2UsXCJhbGxcIixmdW5jdGlvbiBQcm9taXNlJGFsbChhcnIpIHtcblx0XHR2YXIgQ29uc3RydWN0b3IgPSB0aGlzO1xuXG5cdFx0Ly8gc3BlYyBtYW5kYXRlZCBjaGVja3Ncblx0XHRpZiAoVG9TdHJpbmcuY2FsbChhcnIpICE9IFwiW29iamVjdCBBcnJheV1cIikge1xuXHRcdFx0cmV0dXJuIENvbnN0cnVjdG9yLnJlamVjdChUeXBlRXJyb3IoXCJOb3QgYW4gYXJyYXlcIikpO1xuXHRcdH1cblx0XHRpZiAoYXJyLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0cmV0dXJuIENvbnN0cnVjdG9yLnJlc29sdmUoW10pO1xuXHRcdH1cblxuXHRcdHJldHVybiBuZXcgQ29uc3RydWN0b3IoZnVuY3Rpb24gZXhlY3V0b3IocmVzb2x2ZSxyZWplY3Qpe1xuXHRcdFx0aWYgKHR5cGVvZiByZXNvbHZlICE9IFwiZnVuY3Rpb25cIiB8fCB0eXBlb2YgcmVqZWN0ICE9IFwiZnVuY3Rpb25cIikge1xuXHRcdFx0XHR0aHJvdyBUeXBlRXJyb3IoXCJOb3QgYSBmdW5jdGlvblwiKTtcblx0XHRcdH1cblxuXHRcdFx0dmFyIGxlbiA9IGFyci5sZW5ndGgsIG1zZ3MgPSBBcnJheShsZW4pLCBjb3VudCA9IDA7XG5cblx0XHRcdGl0ZXJhdGVQcm9taXNlcyhDb25zdHJ1Y3RvcixhcnIsZnVuY3Rpb24gcmVzb2x2ZXIoaWR4LG1zZykge1xuXHRcdFx0XHRtc2dzW2lkeF0gPSBtc2c7XG5cdFx0XHRcdGlmICgrK2NvdW50ID09PSBsZW4pIHtcblx0XHRcdFx0XHRyZXNvbHZlKG1zZ3MpO1xuXHRcdFx0XHR9XG5cdFx0XHR9LHJlamVjdCk7XG5cdFx0fSk7XG5cdH0pO1xuXG5cdGJ1aWx0SW5Qcm9wKFByb21pc2UsXCJyYWNlXCIsZnVuY3Rpb24gUHJvbWlzZSRyYWNlKGFycikge1xuXHRcdHZhciBDb25zdHJ1Y3RvciA9IHRoaXM7XG5cblx0XHQvLyBzcGVjIG1hbmRhdGVkIGNoZWNrc1xuXHRcdGlmIChUb1N0cmluZy5jYWxsKGFycikgIT0gXCJbb2JqZWN0IEFycmF5XVwiKSB7XG5cdFx0XHRyZXR1cm4gQ29uc3RydWN0b3IucmVqZWN0KFR5cGVFcnJvcihcIk5vdCBhbiBhcnJheVwiKSk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIG5ldyBDb25zdHJ1Y3RvcihmdW5jdGlvbiBleGVjdXRvcihyZXNvbHZlLHJlamVjdCl7XG5cdFx0XHRpZiAodHlwZW9mIHJlc29sdmUgIT0gXCJmdW5jdGlvblwiIHx8IHR5cGVvZiByZWplY3QgIT0gXCJmdW5jdGlvblwiKSB7XG5cdFx0XHRcdHRocm93IFR5cGVFcnJvcihcIk5vdCBhIGZ1bmN0aW9uXCIpO1xuXHRcdFx0fVxuXG5cdFx0XHRpdGVyYXRlUHJvbWlzZXMoQ29uc3RydWN0b3IsYXJyLGZ1bmN0aW9uIHJlc29sdmVyKGlkeCxtc2cpe1xuXHRcdFx0XHRyZXNvbHZlKG1zZyk7XG5cdFx0XHR9LHJlamVjdCk7XG5cdFx0fSk7XG5cdH0pO1xuXG5cdHJldHVybiBQcm9taXNlO1xufSk7XG4iLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxuLy8gcmVzb2x2ZXMgLiBhbmQgLi4gZWxlbWVudHMgaW4gYSBwYXRoIGFycmF5IHdpdGggZGlyZWN0b3J5IG5hbWVzIHRoZXJlXG4vLyBtdXN0IGJlIG5vIHNsYXNoZXMsIGVtcHR5IGVsZW1lbnRzLCBvciBkZXZpY2UgbmFtZXMgKGM6XFwpIGluIHRoZSBhcnJheVxuLy8gKHNvIGFsc28gbm8gbGVhZGluZyBhbmQgdHJhaWxpbmcgc2xhc2hlcyAtIGl0IGRvZXMgbm90IGRpc3Rpbmd1aXNoXG4vLyByZWxhdGl2ZSBhbmQgYWJzb2x1dGUgcGF0aHMpXG5mdW5jdGlvbiBub3JtYWxpemVBcnJheShwYXJ0cywgYWxsb3dBYm92ZVJvb3QpIHtcbiAgLy8gaWYgdGhlIHBhdGggdHJpZXMgdG8gZ28gYWJvdmUgdGhlIHJvb3QsIGB1cGAgZW5kcyB1cCA+IDBcbiAgdmFyIHVwID0gMDtcbiAgZm9yICh2YXIgaSA9IHBhcnRzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgdmFyIGxhc3QgPSBwYXJ0c1tpXTtcbiAgICBpZiAobGFzdCA9PT0gJy4nKSB7XG4gICAgICBwYXJ0cy5zcGxpY2UoaSwgMSk7XG4gICAgfSBlbHNlIGlmIChsYXN0ID09PSAnLi4nKSB7XG4gICAgICBwYXJ0cy5zcGxpY2UoaSwgMSk7XG4gICAgICB1cCsrO1xuICAgIH0gZWxzZSBpZiAodXApIHtcbiAgICAgIHBhcnRzLnNwbGljZShpLCAxKTtcbiAgICAgIHVwLS07XG4gICAgfVxuICB9XG5cbiAgLy8gaWYgdGhlIHBhdGggaXMgYWxsb3dlZCB0byBnbyBhYm92ZSB0aGUgcm9vdCwgcmVzdG9yZSBsZWFkaW5nIC4uc1xuICBpZiAoYWxsb3dBYm92ZVJvb3QpIHtcbiAgICBmb3IgKDsgdXAtLTsgdXApIHtcbiAgICAgIHBhcnRzLnVuc2hpZnQoJy4uJyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHBhcnRzO1xufVxuXG4vLyBTcGxpdCBhIGZpbGVuYW1lIGludG8gW3Jvb3QsIGRpciwgYmFzZW5hbWUsIGV4dF0sIHVuaXggdmVyc2lvblxuLy8gJ3Jvb3QnIGlzIGp1c3QgYSBzbGFzaCwgb3Igbm90aGluZy5cbnZhciBzcGxpdFBhdGhSZSA9XG4gICAgL14oXFwvP3wpKFtcXHNcXFNdKj8pKCg/OlxcLnsxLDJ9fFteXFwvXSs/fCkoXFwuW14uXFwvXSp8KSkoPzpbXFwvXSopJC87XG52YXIgc3BsaXRQYXRoID0gZnVuY3Rpb24oZmlsZW5hbWUpIHtcbiAgcmV0dXJuIHNwbGl0UGF0aFJlLmV4ZWMoZmlsZW5hbWUpLnNsaWNlKDEpO1xufTtcblxuLy8gcGF0aC5yZXNvbHZlKFtmcm9tIC4uLl0sIHRvKVxuLy8gcG9zaXggdmVyc2lvblxuZXhwb3J0cy5yZXNvbHZlID0gZnVuY3Rpb24oKSB7XG4gIHZhciByZXNvbHZlZFBhdGggPSAnJyxcbiAgICAgIHJlc29sdmVkQWJzb2x1dGUgPSBmYWxzZTtcblxuICBmb3IgKHZhciBpID0gYXJndW1lbnRzLmxlbmd0aCAtIDE7IGkgPj0gLTEgJiYgIXJlc29sdmVkQWJzb2x1dGU7IGktLSkge1xuICAgIHZhciBwYXRoID0gKGkgPj0gMCkgPyBhcmd1bWVudHNbaV0gOiBwcm9jZXNzLmN3ZCgpO1xuXG4gICAgLy8gU2tpcCBlbXB0eSBhbmQgaW52YWxpZCBlbnRyaWVzXG4gICAgaWYgKHR5cGVvZiBwYXRoICE9PSAnc3RyaW5nJykge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQXJndW1lbnRzIHRvIHBhdGgucmVzb2x2ZSBtdXN0IGJlIHN0cmluZ3MnKTtcbiAgICB9IGVsc2UgaWYgKCFwYXRoKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICByZXNvbHZlZFBhdGggPSBwYXRoICsgJy8nICsgcmVzb2x2ZWRQYXRoO1xuICAgIHJlc29sdmVkQWJzb2x1dGUgPSBwYXRoLmNoYXJBdCgwKSA9PT0gJy8nO1xuICB9XG5cbiAgLy8gQXQgdGhpcyBwb2ludCB0aGUgcGF0aCBzaG91bGQgYmUgcmVzb2x2ZWQgdG8gYSBmdWxsIGFic29sdXRlIHBhdGgsIGJ1dFxuICAvLyBoYW5kbGUgcmVsYXRpdmUgcGF0aHMgdG8gYmUgc2FmZSAobWlnaHQgaGFwcGVuIHdoZW4gcHJvY2Vzcy5jd2QoKSBmYWlscylcblxuICAvLyBOb3JtYWxpemUgdGhlIHBhdGhcbiAgcmVzb2x2ZWRQYXRoID0gbm9ybWFsaXplQXJyYXkoZmlsdGVyKHJlc29sdmVkUGF0aC5zcGxpdCgnLycpLCBmdW5jdGlvbihwKSB7XG4gICAgcmV0dXJuICEhcDtcbiAgfSksICFyZXNvbHZlZEFic29sdXRlKS5qb2luKCcvJyk7XG5cbiAgcmV0dXJuICgocmVzb2x2ZWRBYnNvbHV0ZSA/ICcvJyA6ICcnKSArIHJlc29sdmVkUGF0aCkgfHwgJy4nO1xufTtcblxuLy8gcGF0aC5ub3JtYWxpemUocGF0aClcbi8vIHBvc2l4IHZlcnNpb25cbmV4cG9ydHMubm9ybWFsaXplID0gZnVuY3Rpb24ocGF0aCkge1xuICB2YXIgaXNBYnNvbHV0ZSA9IGV4cG9ydHMuaXNBYnNvbHV0ZShwYXRoKSxcbiAgICAgIHRyYWlsaW5nU2xhc2ggPSBzdWJzdHIocGF0aCwgLTEpID09PSAnLyc7XG5cbiAgLy8gTm9ybWFsaXplIHRoZSBwYXRoXG4gIHBhdGggPSBub3JtYWxpemVBcnJheShmaWx0ZXIocGF0aC5zcGxpdCgnLycpLCBmdW5jdGlvbihwKSB7XG4gICAgcmV0dXJuICEhcDtcbiAgfSksICFpc0Fic29sdXRlKS5qb2luKCcvJyk7XG5cbiAgaWYgKCFwYXRoICYmICFpc0Fic29sdXRlKSB7XG4gICAgcGF0aCA9ICcuJztcbiAgfVxuICBpZiAocGF0aCAmJiB0cmFpbGluZ1NsYXNoKSB7XG4gICAgcGF0aCArPSAnLyc7XG4gIH1cblxuICByZXR1cm4gKGlzQWJzb2x1dGUgPyAnLycgOiAnJykgKyBwYXRoO1xufTtcblxuLy8gcG9zaXggdmVyc2lvblxuZXhwb3J0cy5pc0Fic29sdXRlID0gZnVuY3Rpb24ocGF0aCkge1xuICByZXR1cm4gcGF0aC5jaGFyQXQoMCkgPT09ICcvJztcbn07XG5cbi8vIHBvc2l4IHZlcnNpb25cbmV4cG9ydHMuam9pbiA9IGZ1bmN0aW9uKCkge1xuICB2YXIgcGF0aHMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDApO1xuICByZXR1cm4gZXhwb3J0cy5ub3JtYWxpemUoZmlsdGVyKHBhdGhzLCBmdW5jdGlvbihwLCBpbmRleCkge1xuICAgIGlmICh0eXBlb2YgcCAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50cyB0byBwYXRoLmpvaW4gbXVzdCBiZSBzdHJpbmdzJyk7XG4gICAgfVxuICAgIHJldHVybiBwO1xuICB9KS5qb2luKCcvJykpO1xufTtcblxuXG4vLyBwYXRoLnJlbGF0aXZlKGZyb20sIHRvKVxuLy8gcG9zaXggdmVyc2lvblxuZXhwb3J0cy5yZWxhdGl2ZSA9IGZ1bmN0aW9uKGZyb20sIHRvKSB7XG4gIGZyb20gPSBleHBvcnRzLnJlc29sdmUoZnJvbSkuc3Vic3RyKDEpO1xuICB0byA9IGV4cG9ydHMucmVzb2x2ZSh0bykuc3Vic3RyKDEpO1xuXG4gIGZ1bmN0aW9uIHRyaW0oYXJyKSB7XG4gICAgdmFyIHN0YXJ0ID0gMDtcbiAgICBmb3IgKDsgc3RhcnQgPCBhcnIubGVuZ3RoOyBzdGFydCsrKSB7XG4gICAgICBpZiAoYXJyW3N0YXJ0XSAhPT0gJycpIGJyZWFrO1xuICAgIH1cblxuICAgIHZhciBlbmQgPSBhcnIubGVuZ3RoIC0gMTtcbiAgICBmb3IgKDsgZW5kID49IDA7IGVuZC0tKSB7XG4gICAgICBpZiAoYXJyW2VuZF0gIT09ICcnKSBicmVhaztcbiAgICB9XG5cbiAgICBpZiAoc3RhcnQgPiBlbmQpIHJldHVybiBbXTtcbiAgICByZXR1cm4gYXJyLnNsaWNlKHN0YXJ0LCBlbmQgLSBzdGFydCArIDEpO1xuICB9XG5cbiAgdmFyIGZyb21QYXJ0cyA9IHRyaW0oZnJvbS5zcGxpdCgnLycpKTtcbiAgdmFyIHRvUGFydHMgPSB0cmltKHRvLnNwbGl0KCcvJykpO1xuXG4gIHZhciBsZW5ndGggPSBNYXRoLm1pbihmcm9tUGFydHMubGVuZ3RoLCB0b1BhcnRzLmxlbmd0aCk7XG4gIHZhciBzYW1lUGFydHNMZW5ndGggPSBsZW5ndGg7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoZnJvbVBhcnRzW2ldICE9PSB0b1BhcnRzW2ldKSB7XG4gICAgICBzYW1lUGFydHNMZW5ndGggPSBpO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgdmFyIG91dHB1dFBhcnRzID0gW107XG4gIGZvciAodmFyIGkgPSBzYW1lUGFydHNMZW5ndGg7IGkgPCBmcm9tUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICBvdXRwdXRQYXJ0cy5wdXNoKCcuLicpO1xuICB9XG5cbiAgb3V0cHV0UGFydHMgPSBvdXRwdXRQYXJ0cy5jb25jYXQodG9QYXJ0cy5zbGljZShzYW1lUGFydHNMZW5ndGgpKTtcblxuICByZXR1cm4gb3V0cHV0UGFydHMuam9pbignLycpO1xufTtcblxuZXhwb3J0cy5zZXAgPSAnLyc7XG5leHBvcnRzLmRlbGltaXRlciA9ICc6JztcblxuZXhwb3J0cy5kaXJuYW1lID0gZnVuY3Rpb24ocGF0aCkge1xuICB2YXIgcmVzdWx0ID0gc3BsaXRQYXRoKHBhdGgpLFxuICAgICAgcm9vdCA9IHJlc3VsdFswXSxcbiAgICAgIGRpciA9IHJlc3VsdFsxXTtcblxuICBpZiAoIXJvb3QgJiYgIWRpcikge1xuICAgIC8vIE5vIGRpcm5hbWUgd2hhdHNvZXZlclxuICAgIHJldHVybiAnLic7XG4gIH1cblxuICBpZiAoZGlyKSB7XG4gICAgLy8gSXQgaGFzIGEgZGlybmFtZSwgc3RyaXAgdHJhaWxpbmcgc2xhc2hcbiAgICBkaXIgPSBkaXIuc3Vic3RyKDAsIGRpci5sZW5ndGggLSAxKTtcbiAgfVxuXG4gIHJldHVybiByb290ICsgZGlyO1xufTtcblxuXG5leHBvcnRzLmJhc2VuYW1lID0gZnVuY3Rpb24ocGF0aCwgZXh0KSB7XG4gIHZhciBmID0gc3BsaXRQYXRoKHBhdGgpWzJdO1xuICAvLyBUT0RPOiBtYWtlIHRoaXMgY29tcGFyaXNvbiBjYXNlLWluc2Vuc2l0aXZlIG9uIHdpbmRvd3M/XG4gIGlmIChleHQgJiYgZi5zdWJzdHIoLTEgKiBleHQubGVuZ3RoKSA9PT0gZXh0KSB7XG4gICAgZiA9IGYuc3Vic3RyKDAsIGYubGVuZ3RoIC0gZXh0Lmxlbmd0aCk7XG4gIH1cbiAgcmV0dXJuIGY7XG59O1xuXG5cbmV4cG9ydHMuZXh0bmFtZSA9IGZ1bmN0aW9uKHBhdGgpIHtcbiAgcmV0dXJuIHNwbGl0UGF0aChwYXRoKVszXTtcbn07XG5cbmZ1bmN0aW9uIGZpbHRlciAoeHMsIGYpIHtcbiAgICBpZiAoeHMuZmlsdGVyKSByZXR1cm4geHMuZmlsdGVyKGYpO1xuICAgIHZhciByZXMgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmIChmKHhzW2ldLCBpLCB4cykpIHJlcy5wdXNoKHhzW2ldKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbn1cblxuLy8gU3RyaW5nLnByb3RvdHlwZS5zdWJzdHIgLSBuZWdhdGl2ZSBpbmRleCBkb24ndCB3b3JrIGluIElFOFxudmFyIHN1YnN0ciA9ICdhYicuc3Vic3RyKC0xKSA9PT0gJ2InXG4gICAgPyBmdW5jdGlvbiAoc3RyLCBzdGFydCwgbGVuKSB7IHJldHVybiBzdHIuc3Vic3RyKHN0YXJ0LCBsZW4pIH1cbiAgICA6IGZ1bmN0aW9uIChzdHIsIHN0YXJ0LCBsZW4pIHtcbiAgICAgICAgaWYgKHN0YXJ0IDwgMCkgc3RhcnQgPSBzdHIubGVuZ3RoICsgc3RhcnQ7XG4gICAgICAgIHJldHVybiBzdHIuc3Vic3RyKHN0YXJ0LCBsZW4pO1xuICAgIH1cbjtcbiIsIi8qXG4gKiBUaGUgTUlUIExpY2Vuc2UgKE1JVClcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTUgSmVyZW15IFdoaXRsb2NrXG4gKlxuICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuICogb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuICogaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuICogdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuICogY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4gKiBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuICpcbiAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4gKiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbiAqXG4gKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4gKiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbiAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuICogQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuICogTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbiAqIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbiAqIFRIRSBTT0ZUV0FSRS5cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbi8qKlxuICogVXRpbGl0eSB0aGF0IHByb3ZpZGVzIGEgc2luZ2xlIEFQSSBmb3IgbG9hZGluZyB0aGUgY29udGVudCBvZiBhIHBhdGgvVVJMLlxuICpcbiAqIEBtb2R1bGUgUGF0aExvYWRlclxuICovXG5cbnZhciBzdXBwb3J0ZWRMb2FkZXJzID0ge1xuICBmaWxlOiByZXF1aXJlKCcuL2xpYi9sb2FkZXJzL2ZpbGUnKSxcbiAgaHR0cDogcmVxdWlyZSgnLi9saWIvbG9hZGVycy9odHRwJyksXG4gIGh0dHBzOiByZXF1aXJlKCcuL2xpYi9sb2FkZXJzL2h0dHAnKVxufTtcbnZhciBkZWZhdWx0TG9hZGVyID0gdHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIGltcG9ydFNjcmlwdHMgPT09ICdmdW5jdGlvbicgP1xuICAgICAgc3VwcG9ydGVkTG9hZGVycy5odHRwIDpcbiAgICAgIHN1cHBvcnRlZExvYWRlcnMuZmlsZTtcblxuLy8gTG9hZCBwcm9taXNlcyBwb2x5ZmlsbCBpZiBuZWNlc3Nhcnlcbi8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuaWYgKHR5cGVvZiBQcm9taXNlID09PSAndW5kZWZpbmVkJykge1xuICByZXF1aXJlKCduYXRpdmUtcHJvbWlzZS1vbmx5Jyk7XG59XG5cbmZ1bmN0aW9uIGdldFNjaGVtZSAobG9jYXRpb24pIHtcbiAgaWYgKHR5cGVvZiBsb2NhdGlvbiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBsb2NhdGlvbiA9IGxvY2F0aW9uLmluZGV4T2YoJzovLycpID09PSAtMSA/ICcnIDogbG9jYXRpb24uc3BsaXQoJzovLycpWzBdO1xuICB9XG5cbiAgcmV0dXJuIGxvY2F0aW9uO1xufVxuXG4vKipcbiAqIENhbGxiYWNrIHVzZWQgdG8gcHJvdmlkZSBhY2Nlc3MgdG8gYWx0ZXJpbmcgYSByZW1vdGUgcmVxdWVzdCBwcmlvciB0byB0aGUgcmVxdWVzdCBiZWluZyBtYWRlLlxuICpcbiAqIEB0eXBlZGVmIHtmdW5jdGlvbn0gUHJlcGFyZVJlcXVlc3RDYWxsYmFja1xuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSByZXEgLSBUaGUgU3VwZXJhZ2VudCByZXF1ZXN0IG9iamVjdFxuICogQHBhcmFtIHtzdHJpbmd9IGxvY2F0aW9uIC0gVGhlIGxvY2F0aW9uIGJlaW5nIHJldHJpZXZlZFxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2sgLSBGaXJzdCBjYWxsYmFja1xuICpcbiAqIEBhbGlhcyBtb2R1bGU6UGF0aExvYWRlcn5QcmVwYXJlUmVxdWVzdENhbGxiYWNrXG4gKi9cblxuIC8qKlxuICAqIENhbGxiYWNrIHVzZWQgdG8gcHJvdmlkZSBhY2Nlc3MgdG8gcHJvY2Vzc2luZyB0aGUgcmF3IHJlc3BvbnNlIG9mIHRoZSByZXF1ZXN0IGJlaW5nIG1hZGUuICooSFRUUCBsb2FkZXIgb25seSkqXG4gICpcbiAgKiBAdHlwZWRlZiB7ZnVuY3Rpb259IFByb2Nlc3NSZXNwb25zZUNhbGxiYWNrXG4gICpcbiAgKiBAcGFyYW0ge29iamVjdH0gcmVzIC0gVGhlIFN1cGVyYWdlbnQgcmVzcG9uc2Ugb2JqZWN0ICooRm9yIG5vbi1IVFRQIGxvYWRlcnMsIHRoaXMgb2JqZWN0IHdpbGwgYmUgbGlrZSB0aGUgU3VwZXJhZ2VudFxuICAqIG9iamVjdCBpbiB0aGF0IGl0IHdpbGwgaGF2ZSBhIGB0ZXh0YCBwcm9wZXJ0eSB3aG9zZSB2YWx1ZSBpcyB0aGUgcmF3IHN0cmluZyB2YWx1ZSBiZWluZyBwcm9jZXNzZWQuICBUaGlzIHdhcyBkb25lXG4gICogZm9yIGNvbnNpc3RlbmN5LikqXG4gICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2sgLSBFcnJvci1maXJzdCBjYWxsYmFja1xuICAqXG4gICogQHJldHVybnMgeyp9IHRoZSByZXN1bHQgb2YgcHJvY2Vzc2luZyB0aGUgcmVzcG9uc2V4c1xuICAqXG4gICogQGFsaWFzIG1vZHVsZTpQYXRoTG9hZGVyflByb2Nlc3NSZXNwb25zZUNhbGxiYWNrXG4gICovXG5cbmZ1bmN0aW9uIGdldExvYWRlciAobG9jYXRpb24pIHtcbiAgdmFyIHNjaGVtZSA9IGdldFNjaGVtZShsb2NhdGlvbik7XG4gIHZhciBsb2FkZXIgPSBzdXBwb3J0ZWRMb2FkZXJzW3NjaGVtZV07XG5cbiAgaWYgKHR5cGVvZiBsb2FkZXIgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgaWYgKHNjaGVtZSA9PT0gJycpIHtcbiAgICAgIGxvYWRlciA9IGRlZmF1bHRMb2FkZXI7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVW5zdXBwb3J0ZWQgc2NoZW1lOiAnICsgc2NoZW1lKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gbG9hZGVyO1xufVxuXG4vKipcbiAqIExvYWRzIGEgZG9jdW1lbnQgYXQgdGhlIHByb3ZpZGVkIGxvY2F0aW9uIGFuZCByZXR1cm5zIGEgSmF2YVNjcmlwdCBvYmplY3QgcmVwcmVzZW50YXRpb24uXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IGxvY2F0aW9uIC0gVGhlIGxvY2F0aW9uIHRvIHRoZSBkb2N1bWVudFxuICogQHBhcmFtIHtvYmplY3R9IFtvcHRpb25zXSAtIFRoZSBvcHRpb25zXG4gKiBAcGFyYW0ge3N0cmluZ30gW29wdGlvbnMuZW5jb2Rpbmc9J3V0Zi04J10gLSBUaGUgZW5jb2RpbmcgdG8gdXNlIHdoZW4gbG9hZGluZyB0aGUgZmlsZSAqKEZpbGUgbG9hZGVyIG9ubHkpKlxuICogQHBhcmFtIHtzdHJpbmd9IFtvcHRpb25zLm1ldGhvZD1nZXRdIC0gVGhlIEhUVFAgbWV0aG9kIHRvIHVzZSBmb3IgdGhlIHJlcXVlc3QgKihIVFRQIGxvYWRlciBvbmx5KSpcbiAqIEBwYXJhbSB7bW9kdWxlOlBhdGhMb2FkZXJ+UHJlcGFyZVJlcXVlc3RDYWxsYmFja30gW29wdGlvbnMucHJlcGFyZVJlcXVlc3RdIC0gVGhlIGNhbGxiYWNrIHVzZWQgdG8gcHJlcGFyZSB0aGUgcmVxdWVzdFxuICogKihIVFRQIGxvYWRlciBvbmx5KSpcbiAqIEBwYXJhbSB7bW9kdWxlOlBhdGhMb2FkZXJ+UHJvY2Vzc1Jlc3BvbnNlQ2FsbGJhY2t9IFtvcHRpb25zLnByb2Nlc3NDb250ZW50XSAtIFRoZSBjYWxsYmFjayB1c2VkIHRvIHByb2Nlc3MgdGhlXG4gKiByZXNwb25zZVxuICpcbiAqIEByZXR1cm5zIHtQcm9taXNlfSBBbHdheXMgcmV0dXJucyBhIHByb21pc2UgZXZlbiBpZiB0aGVyZSBpcyBhIGNhbGxiYWNrIHByb3ZpZGVkXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIEV4YW1wbGUgdXNpbmcgUHJvbWlzZXNcbiAqXG4gKiBQYXRoTG9hZGVyXG4gKiAgIC5sb2FkKCcuL3BhY2thZ2UuanNvbicpXG4gKiAgIC50aGVuKEpTT04ucGFyc2UpXG4gKiAgIC50aGVuKGZ1bmN0aW9uIChkb2N1bWVudCkge1xuICogICAgIGNvbnNvbGUubG9nKGRvY3VtZW50Lm5hbWUgKyAnICgnICsgZG9jdW1lbnQudmVyc2lvbiArICcpOiAnICsgZG9jdW1lbnQuZGVzY3JpcHRpb24pO1xuICogICB9LCBmdW5jdGlvbiAoZXJyKSB7XG4gKiAgICAgY29uc29sZS5lcnJvcihlcnIuc3RhY2spO1xuICogICB9KTtcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gRXhhbXBsZSB1c2luZyBvcHRpb25zLnByZXBhcmVSZXF1ZXN0IHRvIHByb3ZpZGUgYXV0aGVudGljYXRpb24gZGV0YWlscyBmb3IgYSByZW1vdGVseSBzZWN1cmUgVVJMXG4gKlxuICogUGF0aExvYWRlclxuICogICAubG9hZCgnaHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS9yZXBvcy93aGl0bG9ja2pjL3BhdGgtbG9hZGVyJywge1xuICogICAgIHByZXBhcmVSZXF1ZXN0OiBmdW5jdGlvbiAocmVxLCBjYWxsYmFjaykge1xuICogICAgICAgcmVxLmF1dGgoJ215LXVzZXJuYW1lJywgJ215LXBhc3N3b3JkJyk7XG4gKiAgICAgICBjYWxsYmFjayh1bmRlZmluZWQsIHJlcSk7XG4gKiAgICAgfVxuICogICB9KVxuICogICAudGhlbihKU09OLnBhcnNlKVxuICogICAudGhlbihmdW5jdGlvbiAoZG9jdW1lbnQpIHtcbiAqICAgICBjb25zb2xlLmxvZyhkb2N1bWVudC5mdWxsX25hbWUgKyAnOiAnICsgZG9jdW1lbnQuZGVzY3JpcHRpb24pO1xuICogICB9LCBmdW5jdGlvbiAoZXJyKSB7XG4gKiAgICAgY29uc29sZS5lcnJvcihlcnIuc3RhY2spO1xuICogICB9KTtcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gRXhhbXBsZSBsb2FkaW5nIGEgWUFNTCBmaWxlXG4gKlxuICogUGF0aExvYWRlclxuICogICAubG9hZCgnL1VzZXJzL25vdC15b3UvcHJvamVjdHMvcGF0aC1sb2FkZXIvLnRyYXZpcy55bWwnKVxuICogICAudGhlbihZQU1MLnNhZmVMb2FkKVxuICogICAudGhlbihmdW5jdGlvbiAoZG9jdW1lbnQpIHtcbiAqICAgICBjb25zb2xlLmxvZygncGF0aC1sb2FkZXIgdXNlcyB0aGUnLCBkb2N1bWVudC5sYW5ndWFnZSwgJ2xhbmd1YWdlLicpO1xuICogICB9LCBmdW5jdGlvbiAoZXJyKSB7XG4gKiAgICAgY29uc29sZS5lcnJvcihlcnIuc3RhY2spO1xuICogICB9KTtcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gRXhhbXBsZSBsb2FkaW5nIGEgWUFNTCBmaWxlIHdpdGggb3B0aW9ucy5wcm9jZXNzQ29udGVudCAoVXNlZnVsIGlmIHlvdSBuZWVkIGluZm9ybWF0aW9uIGluIHRoZSByYXcgcmVzcG9uc2UpXG4gKlxuICogUGF0aExvYWRlclxuICogICAubG9hZCgnL1VzZXJzL25vdC15b3UvcHJvamVjdHMvcGF0aC1sb2FkZXIvLnRyYXZpcy55bWwnLCB7XG4gKiAgICAgcHJvY2Vzc0NvbnRlbnQ6IGZ1bmN0aW9uIChyZXMsIGNhbGxiYWNrKSB7XG4gKiAgICAgICBjYWxsYmFjayhZQU1MLnNhZmVMb2FkKHJlcy50ZXh0KSk7XG4gKiAgICAgfVxuICogICB9KVxuICogICAudGhlbihmdW5jdGlvbiAoZG9jdW1lbnQpIHtcbiAqICAgICBjb25zb2xlLmxvZygncGF0aC1sb2FkZXIgdXNlcyB0aGUnLCBkb2N1bWVudC5sYW5ndWFnZSwgJ2xhbmd1YWdlLicpO1xuICogICB9LCBmdW5jdGlvbiAoZXJyKSB7XG4gKiAgICAgY29uc29sZS5lcnJvcihlcnIuc3RhY2spO1xuICogICB9KTtcbiAqL1xubW9kdWxlLmV4cG9ydHMubG9hZCA9IGZ1bmN0aW9uIChsb2NhdGlvbiwgb3B0aW9ucykge1xuICB2YXIgYWxsVGFza3MgPSBQcm9taXNlLnJlc29sdmUoKTtcblxuICAvLyBEZWZhdWx0IG9wdGlvbnMgdG8gZW1wdHkgb2JqZWN0XG4gIGlmICh0eXBlb2Ygb3B0aW9ucyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBvcHRpb25zID0ge307XG4gIH1cblxuICAvLyBWYWxpZGF0ZSBhcmd1bWVudHNcbiAgYWxsVGFza3MgPSBhbGxUYXNrcy50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodHlwZW9mIGxvY2F0aW9uID09PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbG9jYXRpb24gaXMgcmVxdWlyZWQnKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBsb2NhdGlvbiAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2xvY2F0aW9uIG11c3QgYmUgYSBzdHJpbmcnKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIG9wdGlvbnMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBpZiAodHlwZW9mIG9wdGlvbnMgIT09ICdvYmplY3QnKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ29wdGlvbnMgbXVzdCBiZSBhbiBvYmplY3QnKTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIG9wdGlvbnMucHJvY2Vzc0NvbnRlbnQgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBvcHRpb25zLnByb2Nlc3NDb250ZW50ICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ29wdGlvbnMucHJvY2Vzc0NvbnRlbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG4gICAgICB9XG4gICAgfVxuICB9KTtcblxuICAvLyBMb2FkIHRoZSBkb2N1bWVudCBmcm9tIHRoZSBwcm92aWRlZCBsb2NhdGlvbiBhbmQgcHJvY2VzcyBpdFxuICBhbGxUYXNrcyA9IGFsbFRhc2tzXG4gICAgLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgdmFyIGxvYWRlciA9IGdldExvYWRlcihsb2NhdGlvbik7XG5cbiAgICAgICAgbG9hZGVyLmxvYWQobG9jYXRpb24sIG9wdGlvbnMgfHwge30sIGZ1bmN0aW9uIChlcnIsIGRvY3VtZW50KSB7XG4gICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc29sdmUoZG9jdW1lbnQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KVxuICAgIC50aGVuKGZ1bmN0aW9uIChyZXMpIHtcbiAgICAgIGlmIChvcHRpb25zLnByb2Nlc3NDb250ZW50KSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgICAgLy8gRm9yIGNvbnNpc3RlbmN5IGJldHdlZW4gZmlsZSBhbmQgaHR0cCwgYWx3YXlzIHNlbmQgYW4gb2JqZWN0IHdpdGggYSAndGV4dCcgcHJvcGVydHkgY29udGFpbmluZyB0aGUgcmF3XG4gICAgICAgICAgLy8gc3RyaW5nIHZhbHVlIGJlaW5nIHByb2Nlc3NlZC5cbiAgICAgICAgICBvcHRpb25zLnByb2Nlc3NDb250ZW50KHR5cGVvZiByZXMgPT09ICdvYmplY3QnID8gcmVzIDoge3RleHQ6IHJlc30sIGZ1bmN0aW9uIChlcnIsIHByb2Nlc3NlZCkge1xuICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJlc29sdmUocHJvY2Vzc2VkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBJZiB0aGVyZSB3YXMgbm8gY29udGVudCBwcm9jZXNzb3IsIHdlIHdpbGwgYXNzdW1lIHRoYXQgZm9yIGFsbCBvYmplY3RzIHRoYXQgaXQgaXMgYSBTdXBlcmFnZW50IHJlc3BvbnNlXG4gICAgICAgIC8vIGFuZCB3aWxsIHJldHVybiBpdHMgYHRleHRgIHByb3BlcnR5IHZhbHVlLiAgT3RoZXJ3aXNlLCB3ZSB3aWxsIHJldHVybiB0aGUgcmF3IHJlc3BvbnNlLlxuICAgICAgICByZXR1cm4gdHlwZW9mIHJlcyA9PT0gJ29iamVjdCcgPyByZXMudGV4dCA6IHJlcztcbiAgICAgIH1cbiAgICB9KTtcblxuICByZXR1cm4gYWxsVGFza3M7XG59O1xuIiwiLypcbiAqIFRoZSBNSVQgTGljZW5zZSAoTUlUKVxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxNSBKZXJlbXkgV2hpdGxvY2tcbiAqXG4gKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4gKiBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4gKiBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG4gKiB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4gKiBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbiAqIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4gKlxuICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbiAqIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICpcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1JcbiAqIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuICogRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4gKiBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4gKiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuICogT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuICogVEhFIFNPRlRXQVJFLlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHVuc3VwcG9ydGVkRXJyb3IgPSBuZXcgVHlwZUVycm9yKCdUaGUgXFwnZmlsZVxcJyBzY2hlbWUgaXMgbm90IHN1cHBvcnRlZCBpbiB0aGUgYnJvd3NlcicpO1xuXG4vKipcbiAqIFRoZSBmaWxlIGxvYWRlciBpcyBub3Qgc3VwcG9ydGVkIGluIHRoZSBicm93c2VyLlxuICpcbiAqIEB0aHJvd3Mge2Vycm9yfSB0aGUgZmlsZSBsb2FkZXIgaXMgbm90IHN1cHBvcnRlZCBpbiB0aGUgYnJvd3NlclxuICovXG5tb2R1bGUuZXhwb3J0cy5nZXRCYXNlID0gZnVuY3Rpb24gKCkge1xuICB0aHJvdyB1bnN1cHBvcnRlZEVycm9yO1xufTtcblxuLyoqXG4gKiBUaGUgZmlsZSBsb2FkZXIgaXMgbm90IHN1cHBvcnRlZCBpbiB0aGUgYnJvd3Nlci5cbiAqL1xubW9kdWxlLmV4cG9ydHMubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIGZuID0gYXJndW1lbnRzW2FyZ3VtZW50cy5sZW5ndGggLSAxXTtcblxuICBpZiAodHlwZW9mIGZuID09PSAnZnVuY3Rpb24nKSB7XG4gICAgZm4odW5zdXBwb3J0ZWRFcnJvcik7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgdW5zdXBwb3J0ZWRFcnJvcjtcbiAgfVxufTtcbiIsIi8qIGVzbGludC1lbnYgbm9kZSwgYnJvd3NlciAqL1xuXG4vKlxuICogVGhlIE1JVCBMaWNlbnNlIChNSVQpXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDE1IEplcmVteSBXaGl0bG9ja1xuICpcbiAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbiAqIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbiAqIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbiAqIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbiAqIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuICogZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbiAqXG4gKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuICogYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4gKlxuICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuICogSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4gKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbiAqIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbiAqIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4gKiBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4gKiBUSEUgU09GVFdBUkUuXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgcmVxdWVzdCA9IHJlcXVpcmUoJ3N1cGVyYWdlbnQnKTtcblxudmFyIHN1cHBvcnRlZEh0dHBNZXRob2RzID0gWydkZWxldGUnLCAnZ2V0JywgJ2hlYWQnLCAncGF0Y2gnLCAncG9zdCcsICdwdXQnXTtcblxuLyoqXG4gKiBMb2FkcyBhIGZpbGUgZnJvbSBhbiBodHRwIG9yIGh0dHBzIFVSTC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbG9jYXRpb24gLSBUaGUgZG9jdW1lbnQgVVJMIChJZiByZWxhdGl2ZSwgbG9jYXRpb24gaXMgcmVsYXRpdmUgdG8gd2luZG93LmxvY2F0aW9uLm9yaWdpbikuXG4gKiBAcGFyYW0ge29iamVjdH0gb3B0aW9ucyAtIFRoZSBsb2FkZXIgb3B0aW9uc1xuICogQHBhcmFtIHtzdHJpbmd9IFtvcHRpb25zLm1ldGhvZD1nZXRdIC0gVGhlIEhUVFAgbWV0aG9kIHRvIHVzZSBmb3IgdGhlIHJlcXVlc3RcbiAqIEBwYXJhbSB7bW9kdWxlOlBhdGhMb2FkZXJ+UHJlcGFyZVJlcXVlc3RDYWxsYmFja30gW29wdGlvbnMucHJlcGFyZVJlcXVlc3RdIC0gVGhlIGNhbGxiYWNrIHVzZWQgdG8gcHJlcGFyZSBhIHJlcXVlc3RcbiAqIEBwYXJhbSB7bW9kdWxlOlBhdGhMb2FkZXJ+UHJvY2Vzc1Jlc3BvbnNlQ2FsbGJhY2t9IFtvcHRpb25zLnByb2Nlc3NDb250ZW50XSAtIFRoZSBjYWxsYmFjayB1c2VkIHRvIHByb2Nlc3MgdGhlXG4gKiByZXNwb25zZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2sgLSBUaGUgZXJyb3ItZmlyc3QgY2FsbGJhY2tcbiAqL1xubW9kdWxlLmV4cG9ydHMubG9hZCA9IGZ1bmN0aW9uIChsb2NhdGlvbiwgb3B0aW9ucywgY2FsbGJhY2spIHtcbiAgdmFyIHJlYWxNZXRob2QgPSBvcHRpb25zLm1ldGhvZCA/IG9wdGlvbnMubWV0aG9kLnRvTG93ZXJDYXNlKCkgOiAnZ2V0JztcbiAgdmFyIGVycjtcbiAgdmFyIHJlYWxSZXF1ZXN0O1xuXG4gIGZ1bmN0aW9uIG1ha2VSZXF1ZXN0IChlcnIsIHJlcSkge1xuICAgIGlmIChlcnIpIHtcbiAgICAgIGNhbGxiYWNrKGVycik7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGJ1ZmZlcigpIGlzIG9ubHkgYXZhaWxhYmxlIGluIE5vZGUuanNcbiAgICAgIGlmICh0eXBlb2YgcmVxLmJ1ZmZlciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXEuYnVmZmVyKHRydWUpO1xuICAgICAgfVxuXG4gICAgICByZXFcbiAgICAgICAgLmVuZChmdW5jdGlvbiAoZXJyMiwgcmVzKSB7XG4gICAgICAgICAgaWYgKGVycjIpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGVycjIpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWxsYmFjayh1bmRlZmluZWQsIHJlcyk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBpZiAodHlwZW9mIG9wdGlvbnMubWV0aG9kICE9PSAndW5kZWZpbmVkJykge1xuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5tZXRob2QgIT09ICdzdHJpbmcnKSB7XG4gICAgICBlcnIgPSBuZXcgVHlwZUVycm9yKCdvcHRpb25zLm1ldGhvZCBtdXN0IGJlIGEgc3RyaW5nJyk7XG4gICAgfSBlbHNlIGlmIChzdXBwb3J0ZWRIdHRwTWV0aG9kcy5pbmRleE9mKG9wdGlvbnMubWV0aG9kKSA9PT0gLTEpIHtcbiAgICAgIGVyciA9IG5ldyBUeXBlRXJyb3IoJ29wdGlvbnMubWV0aG9kIG11c3QgYmUgb25lIG9mIHRoZSBmb2xsb3dpbmc6ICcgK1xuICAgICAgICBzdXBwb3J0ZWRIdHRwTWV0aG9kcy5zbGljZSgwLCBzdXBwb3J0ZWRIdHRwTWV0aG9kcy5sZW5ndGggLSAxKS5qb2luKCcsICcpICsgJyBvciAnICtcbiAgICAgICAgc3VwcG9ydGVkSHR0cE1ldGhvZHNbc3VwcG9ydGVkSHR0cE1ldGhvZHMubGVuZ3RoIC0gMV0pO1xuICAgIH1cbiAgfSBlbHNlIGlmICh0eXBlb2Ygb3B0aW9ucy5wcmVwYXJlUmVxdWVzdCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIG9wdGlvbnMucHJlcGFyZVJlcXVlc3QgIT09ICdmdW5jdGlvbicpIHtcbiAgICBlcnIgPSBuZXcgVHlwZUVycm9yKCdvcHRpb25zLnByZXBhcmVSZXF1ZXN0IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICB9XG5cbiAgaWYgKCFlcnIpIHtcbiAgICByZWFsUmVxdWVzdCA9IHJlcXVlc3RbcmVhbE1ldGhvZCA9PT0gJ2RlbGV0ZScgPyAnZGVsJyA6IHJlYWxNZXRob2RdKGxvY2F0aW9uKTtcblxuICAgIGlmIChvcHRpb25zLnByZXBhcmVSZXF1ZXN0KSB7XG4gICAgICB0cnkge1xuICAgICAgICBvcHRpb25zLnByZXBhcmVSZXF1ZXN0KHJlYWxSZXF1ZXN0LCBtYWtlUmVxdWVzdCk7XG4gICAgICB9IGNhdGNoIChlcnIyKSB7XG4gICAgICAgIGNhbGxiYWNrKGVycjIpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBtYWtlUmVxdWVzdCh1bmRlZmluZWQsIHJlYWxSZXF1ZXN0KTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgY2FsbGJhY2soZXJyKTtcbiAgfVxufTtcbiIsIi8vIHNoaW0gZm9yIHVzaW5nIHByb2Nlc3MgaW4gYnJvd3NlclxuXG52YXIgcHJvY2VzcyA9IG1vZHVsZS5leHBvcnRzID0ge307XG52YXIgcXVldWUgPSBbXTtcbnZhciBkcmFpbmluZyA9IGZhbHNlO1xudmFyIGN1cnJlbnRRdWV1ZTtcbnZhciBxdWV1ZUluZGV4ID0gLTE7XG5cbmZ1bmN0aW9uIGNsZWFuVXBOZXh0VGljaygpIHtcbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIGlmIChjdXJyZW50UXVldWUubGVuZ3RoKSB7XG4gICAgICAgIHF1ZXVlID0gY3VycmVudFF1ZXVlLmNvbmNhdChxdWV1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgIH1cbiAgICBpZiAocXVldWUubGVuZ3RoKSB7XG4gICAgICAgIGRyYWluUXVldWUoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRyYWluUXVldWUoKSB7XG4gICAgaWYgKGRyYWluaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGNsZWFuVXBOZXh0VGljayk7XG4gICAgZHJhaW5pbmcgPSB0cnVlO1xuXG4gICAgdmFyIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB3aGlsZShsZW4pIHtcbiAgICAgICAgY3VycmVudFF1ZXVlID0gcXVldWU7XG4gICAgICAgIHF1ZXVlID0gW107XG4gICAgICAgIHdoaWxlICgrK3F1ZXVlSW5kZXggPCBsZW4pIHtcbiAgICAgICAgICAgIGlmIChjdXJyZW50UXVldWUpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50UXVldWVbcXVldWVJbmRleF0ucnVuKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgICAgICBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgfVxuICAgIGN1cnJlbnRRdWV1ZSA9IG51bGw7XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbiAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG59XG5cbnByb2Nlc3MubmV4dFRpY2sgPSBmdW5jdGlvbiAoZnVuKSB7XG4gICAgdmFyIGFyZ3MgPSBuZXcgQXJyYXkoYXJndW1lbnRzLmxlbmd0aCAtIDEpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgYXJnc1tpIC0gMV0gPSBhcmd1bWVudHNbaV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcXVldWUucHVzaChuZXcgSXRlbShmdW4sIGFyZ3MpKTtcbiAgICBpZiAocXVldWUubGVuZ3RoID09PSAxICYmICFkcmFpbmluZykge1xuICAgICAgICBzZXRUaW1lb3V0KGRyYWluUXVldWUsIDApO1xuICAgIH1cbn07XG5cbi8vIHY4IGxpa2VzIHByZWRpY3RpYmxlIG9iamVjdHNcbmZ1bmN0aW9uIEl0ZW0oZnVuLCBhcnJheSkge1xuICAgIHRoaXMuZnVuID0gZnVuO1xuICAgIHRoaXMuYXJyYXkgPSBhcnJheTtcbn1cbkl0ZW0ucHJvdG90eXBlLnJ1biA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmZ1bi5hcHBseShudWxsLCB0aGlzLmFycmF5KTtcbn07XG5wcm9jZXNzLnRpdGxlID0gJ2Jyb3dzZXInO1xucHJvY2Vzcy5icm93c2VyID0gdHJ1ZTtcbnByb2Nlc3MuZW52ID0ge307XG5wcm9jZXNzLmFyZ3YgPSBbXTtcbnByb2Nlc3MudmVyc2lvbiA9ICcnOyAvLyBlbXB0eSBzdHJpbmcgdG8gYXZvaWQgcmVnZXhwIGlzc3Vlc1xucHJvY2Vzcy52ZXJzaW9ucyA9IHt9O1xuXG5mdW5jdGlvbiBub29wKCkge31cblxucHJvY2Vzcy5vbiA9IG5vb3A7XG5wcm9jZXNzLmFkZExpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3Mub25jZSA9IG5vb3A7XG5wcm9jZXNzLm9mZiA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUxpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3MucmVtb3ZlQWxsTGlzdGVuZXJzID0gbm9vcDtcbnByb2Nlc3MuZW1pdCA9IG5vb3A7XG5cbnByb2Nlc3MuYmluZGluZyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmJpbmRpbmcgaXMgbm90IHN1cHBvcnRlZCcpO1xufTtcblxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5wcm9jZXNzLnVtYXNrID0gZnVuY3Rpb24oKSB7IHJldHVybiAwOyB9O1xuIiwiLy8gQ29weXJpZ2h0IEpveWVudCwgSW5jLiBhbmQgb3RoZXIgTm9kZSBjb250cmlidXRvcnMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGFcbi8vIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGVcbi8vIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZ1xuLy8gd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLFxuLy8gZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdFxuLy8gcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlXG4vLyBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZFxuLy8gaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTU1xuLy8gT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRlxuLy8gTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTlxuLy8gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sXG4vLyBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1Jcbi8vIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEVcbi8vIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbid1c2Ugc3RyaWN0JztcblxuLy8gSWYgb2JqLmhhc093blByb3BlcnR5IGhhcyBiZWVuIG92ZXJyaWRkZW4sIHRoZW4gY2FsbGluZ1xuLy8gb2JqLmhhc093blByb3BlcnR5KHByb3ApIHdpbGwgYnJlYWsuXG4vLyBTZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9qb3llbnQvbm9kZS9pc3N1ZXMvMTcwN1xuZnVuY3Rpb24gaGFzT3duUHJvcGVydHkob2JqLCBwcm9wKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihxcywgc2VwLCBlcSwgb3B0aW9ucykge1xuICBzZXAgPSBzZXAgfHwgJyYnO1xuICBlcSA9IGVxIHx8ICc9JztcbiAgdmFyIG9iaiA9IHt9O1xuXG4gIGlmICh0eXBlb2YgcXMgIT09ICdzdHJpbmcnIHx8IHFzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBvYmo7XG4gIH1cblxuICB2YXIgcmVnZXhwID0gL1xcKy9nO1xuICBxcyA9IHFzLnNwbGl0KHNlcCk7XG5cbiAgdmFyIG1heEtleXMgPSAxMDAwO1xuICBpZiAob3B0aW9ucyAmJiB0eXBlb2Ygb3B0aW9ucy5tYXhLZXlzID09PSAnbnVtYmVyJykge1xuICAgIG1heEtleXMgPSBvcHRpb25zLm1heEtleXM7XG4gIH1cblxuICB2YXIgbGVuID0gcXMubGVuZ3RoO1xuICAvLyBtYXhLZXlzIDw9IDAgbWVhbnMgdGhhdCB3ZSBzaG91bGQgbm90IGxpbWl0IGtleXMgY291bnRcbiAgaWYgKG1heEtleXMgPiAwICYmIGxlbiA+IG1heEtleXMpIHtcbiAgICBsZW4gPSBtYXhLZXlzO1xuICB9XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSkge1xuICAgIHZhciB4ID0gcXNbaV0ucmVwbGFjZShyZWdleHAsICclMjAnKSxcbiAgICAgICAgaWR4ID0geC5pbmRleE9mKGVxKSxcbiAgICAgICAga3N0ciwgdnN0ciwgaywgdjtcblxuICAgIGlmIChpZHggPj0gMCkge1xuICAgICAga3N0ciA9IHguc3Vic3RyKDAsIGlkeCk7XG4gICAgICB2c3RyID0geC5zdWJzdHIoaWR4ICsgMSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGtzdHIgPSB4O1xuICAgICAgdnN0ciA9ICcnO1xuICAgIH1cblxuICAgIGsgPSBkZWNvZGVVUklDb21wb25lbnQoa3N0cik7XG4gICAgdiA9IGRlY29kZVVSSUNvbXBvbmVudCh2c3RyKTtcblxuICAgIGlmICghaGFzT3duUHJvcGVydHkob2JqLCBrKSkge1xuICAgICAgb2JqW2tdID0gdjtcbiAgICB9IGVsc2UgaWYgKGlzQXJyYXkob2JqW2tdKSkge1xuICAgICAgb2JqW2tdLnB1c2godik7XG4gICAgfSBlbHNlIHtcbiAgICAgIG9ialtrXSA9IFtvYmpba10sIHZdO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBvYmo7XG59O1xuXG52YXIgaXNBcnJheSA9IEFycmF5LmlzQXJyYXkgfHwgZnVuY3Rpb24gKHhzKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoeHMpID09PSAnW29iamVjdCBBcnJheV0nO1xufTtcbiIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzdHJpbmdpZnlQcmltaXRpdmUgPSBmdW5jdGlvbih2KSB7XG4gIHN3aXRjaCAodHlwZW9mIHYpIHtcbiAgICBjYXNlICdzdHJpbmcnOlxuICAgICAgcmV0dXJuIHY7XG5cbiAgICBjYXNlICdib29sZWFuJzpcbiAgICAgIHJldHVybiB2ID8gJ3RydWUnIDogJ2ZhbHNlJztcblxuICAgIGNhc2UgJ251bWJlcic6XG4gICAgICByZXR1cm4gaXNGaW5pdGUodikgPyB2IDogJyc7XG5cbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuICcnO1xuICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKG9iaiwgc2VwLCBlcSwgbmFtZSkge1xuICBzZXAgPSBzZXAgfHwgJyYnO1xuICBlcSA9IGVxIHx8ICc9JztcbiAgaWYgKG9iaiA9PT0gbnVsbCkge1xuICAgIG9iaiA9IHVuZGVmaW5lZDtcbiAgfVxuXG4gIGlmICh0eXBlb2Ygb2JqID09PSAnb2JqZWN0Jykge1xuICAgIHJldHVybiBtYXAob2JqZWN0S2V5cyhvYmopLCBmdW5jdGlvbihrKSB7XG4gICAgICB2YXIga3MgPSBlbmNvZGVVUklDb21wb25lbnQoc3RyaW5naWZ5UHJpbWl0aXZlKGspKSArIGVxO1xuICAgICAgaWYgKGlzQXJyYXkob2JqW2tdKSkge1xuICAgICAgICByZXR1cm4gbWFwKG9ialtrXSwgZnVuY3Rpb24odikge1xuICAgICAgICAgIHJldHVybiBrcyArIGVuY29kZVVSSUNvbXBvbmVudChzdHJpbmdpZnlQcmltaXRpdmUodikpO1xuICAgICAgICB9KS5qb2luKHNlcCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4ga3MgKyBlbmNvZGVVUklDb21wb25lbnQoc3RyaW5naWZ5UHJpbWl0aXZlKG9ialtrXSkpO1xuICAgICAgfVxuICAgIH0pLmpvaW4oc2VwKTtcblxuICB9XG5cbiAgaWYgKCFuYW1lKSByZXR1cm4gJyc7XG4gIHJldHVybiBlbmNvZGVVUklDb21wb25lbnQoc3RyaW5naWZ5UHJpbWl0aXZlKG5hbWUpKSArIGVxICtcbiAgICAgICAgIGVuY29kZVVSSUNvbXBvbmVudChzdHJpbmdpZnlQcmltaXRpdmUob2JqKSk7XG59O1xuXG52YXIgaXNBcnJheSA9IEFycmF5LmlzQXJyYXkgfHwgZnVuY3Rpb24gKHhzKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoeHMpID09PSAnW29iamVjdCBBcnJheV0nO1xufTtcblxuZnVuY3Rpb24gbWFwICh4cywgZikge1xuICBpZiAoeHMubWFwKSByZXR1cm4geHMubWFwKGYpO1xuICB2YXIgcmVzID0gW107XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgeHMubGVuZ3RoOyBpKyspIHtcbiAgICByZXMucHVzaChmKHhzW2ldLCBpKSk7XG4gIH1cbiAgcmV0dXJuIHJlcztcbn1cblxudmFyIG9iamVjdEtleXMgPSBPYmplY3Qua2V5cyB8fCBmdW5jdGlvbiAob2JqKSB7XG4gIHZhciByZXMgPSBbXTtcbiAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBrZXkpKSByZXMucHVzaChrZXkpO1xuICB9XG4gIHJldHVybiByZXM7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLmRlY29kZSA9IGV4cG9ydHMucGFyc2UgPSByZXF1aXJlKCcuL2RlY29kZScpO1xuZXhwb3J0cy5lbmNvZGUgPSBleHBvcnRzLnN0cmluZ2lmeSA9IHJlcXVpcmUoJy4vZW5jb2RlJyk7XG4iLCJcbi8qKlxuICogUmVkdWNlIGBhcnJgIHdpdGggYGZuYC5cbiAqXG4gKiBAcGFyYW0ge0FycmF5fSBhcnJcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuXG4gKiBAcGFyYW0ge01peGVkfSBpbml0aWFsXG4gKlxuICogVE9ETzogY29tYmF0aWJsZSBlcnJvciBoYW5kbGluZz9cbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGFyciwgZm4sIGluaXRpYWwpeyAgXG4gIHZhciBpZHggPSAwO1xuICB2YXIgbGVuID0gYXJyLmxlbmd0aDtcbiAgdmFyIGN1cnIgPSBhcmd1bWVudHMubGVuZ3RoID09IDNcbiAgICA/IGluaXRpYWxcbiAgICA6IGFycltpZHgrK107XG5cbiAgd2hpbGUgKGlkeCA8IGxlbikge1xuICAgIGN1cnIgPSBmbi5jYWxsKG51bGwsIGN1cnIsIGFycltpZHhdLCArK2lkeCwgYXJyKTtcbiAgfVxuICBcbiAgcmV0dXJuIGN1cnI7XG59OyIsIid1c2Ugc3RyaWN0Jztcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHN0cikge1xuXHR2YXIgaXNFeHRlbmRlZExlbmd0aFBhdGggPSAvXlxcXFxcXFxcXFw/XFxcXC8udGVzdChzdHIpO1xuXHR2YXIgaGFzTm9uQXNjaWkgPSAvW15cXHgwMC1cXHg4MF0rLy50ZXN0KHN0cik7XG5cblx0aWYgKGlzRXh0ZW5kZWRMZW5ndGhQYXRoIHx8IGhhc05vbkFzY2lpKSB7XG5cdFx0cmV0dXJuIHN0cjtcblx0fVxuXG5cdHJldHVybiBzdHIucmVwbGFjZSgvXFxcXC9nLCAnLycpO1xufTtcbiIsIi8qKlxuICogTW9kdWxlIGRlcGVuZGVuY2llcy5cbiAqL1xuXG52YXIgRW1pdHRlciA9IHJlcXVpcmUoJ2VtaXR0ZXInKTtcbnZhciByZWR1Y2UgPSByZXF1aXJlKCdyZWR1Y2UnKTtcbnZhciByZXF1ZXN0QmFzZSA9IHJlcXVpcmUoJy4vcmVxdWVzdC1iYXNlJyk7XG52YXIgaXNPYmplY3QgPSByZXF1aXJlKCcuL2lzLW9iamVjdCcpO1xuXG4vKipcbiAqIFJvb3QgcmVmZXJlbmNlIGZvciBpZnJhbWVzLlxuICovXG5cbnZhciByb290O1xuaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7IC8vIEJyb3dzZXIgd2luZG93XG4gIHJvb3QgPSB3aW5kb3c7XG59IGVsc2UgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJykgeyAvLyBXZWIgV29ya2VyXG4gIHJvb3QgPSBzZWxmO1xufSBlbHNlIHsgLy8gT3RoZXIgZW52aXJvbm1lbnRzXG4gIHJvb3QgPSB0aGlzO1xufVxuXG4vKipcbiAqIE5vb3AuXG4gKi9cblxuZnVuY3Rpb24gbm9vcCgpe307XG5cbi8qKlxuICogQ2hlY2sgaWYgYG9iamAgaXMgYSBob3N0IG9iamVjdCxcbiAqIHdlIGRvbid0IHdhbnQgdG8gc2VyaWFsaXplIHRoZXNlIDopXG4gKlxuICogVE9ETzogZnV0dXJlIHByb29mLCBtb3ZlIHRvIGNvbXBvZW50IGxhbmRcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gaXNIb3N0KG9iaikge1xuICB2YXIgc3RyID0ge30udG9TdHJpbmcuY2FsbChvYmopO1xuXG4gIHN3aXRjaCAoc3RyKSB7XG4gICAgY2FzZSAnW29iamVjdCBGaWxlXSc6XG4gICAgY2FzZSAnW29iamVjdCBCbG9iXSc6XG4gICAgY2FzZSAnW29iamVjdCBGb3JtRGF0YV0nOlxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vKipcbiAqIEV4cG9zZSBgcmVxdWVzdGAuXG4gKi9cblxudmFyIHJlcXVlc3QgPSBtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vcmVxdWVzdCcpLmJpbmQobnVsbCwgUmVxdWVzdCk7XG5cbi8qKlxuICogRGV0ZXJtaW5lIFhIUi5cbiAqL1xuXG5yZXF1ZXN0LmdldFhIUiA9IGZ1bmN0aW9uICgpIHtcbiAgaWYgKHJvb3QuWE1MSHR0cFJlcXVlc3RcbiAgICAgICYmICghcm9vdC5sb2NhdGlvbiB8fCAnZmlsZTonICE9IHJvb3QubG9jYXRpb24ucHJvdG9jb2xcbiAgICAgICAgICB8fCAhcm9vdC5BY3RpdmVYT2JqZWN0KSkge1xuICAgIHJldHVybiBuZXcgWE1MSHR0cFJlcXVlc3Q7XG4gIH0gZWxzZSB7XG4gICAgdHJ5IHsgcmV0dXJuIG5ldyBBY3RpdmVYT2JqZWN0KCdNaWNyb3NvZnQuWE1MSFRUUCcpOyB9IGNhdGNoKGUpIHt9XG4gICAgdHJ5IHsgcmV0dXJuIG5ldyBBY3RpdmVYT2JqZWN0KCdNc3htbDIuWE1MSFRUUC42LjAnKTsgfSBjYXRjaChlKSB7fVxuICAgIHRyeSB7IHJldHVybiBuZXcgQWN0aXZlWE9iamVjdCgnTXN4bWwyLlhNTEhUVFAuMy4wJyk7IH0gY2F0Y2goZSkge31cbiAgICB0cnkgeyByZXR1cm4gbmV3IEFjdGl2ZVhPYmplY3QoJ01zeG1sMi5YTUxIVFRQJyk7IH0gY2F0Y2goZSkge31cbiAgfVxuICByZXR1cm4gZmFsc2U7XG59O1xuXG4vKipcbiAqIFJlbW92ZXMgbGVhZGluZyBhbmQgdHJhaWxpbmcgd2hpdGVzcGFjZSwgYWRkZWQgdG8gc3VwcG9ydCBJRS5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gc1xuICogQHJldHVybiB7U3RyaW5nfVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxudmFyIHRyaW0gPSAnJy50cmltXG4gID8gZnVuY3Rpb24ocykgeyByZXR1cm4gcy50cmltKCk7IH1cbiAgOiBmdW5jdGlvbihzKSB7IHJldHVybiBzLnJlcGxhY2UoLyheXFxzKnxcXHMqJCkvZywgJycpOyB9O1xuXG4vKipcbiAqIFNlcmlhbGl6ZSB0aGUgZ2l2ZW4gYG9iamAuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9ialxuICogQHJldHVybiB7U3RyaW5nfVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gc2VyaWFsaXplKG9iaikge1xuICBpZiAoIWlzT2JqZWN0KG9iaikpIHJldHVybiBvYmo7XG4gIHZhciBwYWlycyA9IFtdO1xuICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgaWYgKG51bGwgIT0gb2JqW2tleV0pIHtcbiAgICAgIHB1c2hFbmNvZGVkS2V5VmFsdWVQYWlyKHBhaXJzLCBrZXksIG9ialtrZXldKTtcbiAgICAgICAgfVxuICAgICAgfVxuICByZXR1cm4gcGFpcnMuam9pbignJicpO1xufVxuXG4vKipcbiAqIEhlbHBzICdzZXJpYWxpemUnIHdpdGggc2VyaWFsaXppbmcgYXJyYXlzLlxuICogTXV0YXRlcyB0aGUgcGFpcnMgYXJyYXkuXG4gKlxuICogQHBhcmFtIHtBcnJheX0gcGFpcnNcbiAqIEBwYXJhbSB7U3RyaW5nfSBrZXlcbiAqIEBwYXJhbSB7TWl4ZWR9IHZhbFxuICovXG5cbmZ1bmN0aW9uIHB1c2hFbmNvZGVkS2V5VmFsdWVQYWlyKHBhaXJzLCBrZXksIHZhbCkge1xuICBpZiAoQXJyYXkuaXNBcnJheSh2YWwpKSB7XG4gICAgcmV0dXJuIHZhbC5mb3JFYWNoKGZ1bmN0aW9uKHYpIHtcbiAgICAgIHB1c2hFbmNvZGVkS2V5VmFsdWVQYWlyKHBhaXJzLCBrZXksIHYpO1xuICAgIH0pO1xuICB9XG4gIHBhaXJzLnB1c2goZW5jb2RlVVJJQ29tcG9uZW50KGtleSlcbiAgICArICc9JyArIGVuY29kZVVSSUNvbXBvbmVudCh2YWwpKTtcbn1cblxuLyoqXG4gKiBFeHBvc2Ugc2VyaWFsaXphdGlvbiBtZXRob2QuXG4gKi9cblxuIHJlcXVlc3Quc2VyaWFsaXplT2JqZWN0ID0gc2VyaWFsaXplO1xuXG4gLyoqXG4gICogUGFyc2UgdGhlIGdpdmVuIHgtd3d3LWZvcm0tdXJsZW5jb2RlZCBgc3RyYC5cbiAgKlxuICAqIEBwYXJhbSB7U3RyaW5nfSBzdHJcbiAgKiBAcmV0dXJuIHtPYmplY3R9XG4gICogQGFwaSBwcml2YXRlXG4gICovXG5cbmZ1bmN0aW9uIHBhcnNlU3RyaW5nKHN0cikge1xuICB2YXIgb2JqID0ge307XG4gIHZhciBwYWlycyA9IHN0ci5zcGxpdCgnJicpO1xuICB2YXIgcGFydHM7XG4gIHZhciBwYWlyO1xuXG4gIGZvciAodmFyIGkgPSAwLCBsZW4gPSBwYWlycy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xuICAgIHBhaXIgPSBwYWlyc1tpXTtcbiAgICBwYXJ0cyA9IHBhaXIuc3BsaXQoJz0nKTtcbiAgICBvYmpbZGVjb2RlVVJJQ29tcG9uZW50KHBhcnRzWzBdKV0gPSBkZWNvZGVVUklDb21wb25lbnQocGFydHNbMV0pO1xuICB9XG5cbiAgcmV0dXJuIG9iajtcbn1cblxuLyoqXG4gKiBFeHBvc2UgcGFyc2VyLlxuICovXG5cbnJlcXVlc3QucGFyc2VTdHJpbmcgPSBwYXJzZVN0cmluZztcblxuLyoqXG4gKiBEZWZhdWx0IE1JTUUgdHlwZSBtYXAuXG4gKlxuICogICAgIHN1cGVyYWdlbnQudHlwZXMueG1sID0gJ2FwcGxpY2F0aW9uL3htbCc7XG4gKlxuICovXG5cbnJlcXVlc3QudHlwZXMgPSB7XG4gIGh0bWw6ICd0ZXh0L2h0bWwnLFxuICBqc29uOiAnYXBwbGljYXRpb24vanNvbicsXG4gIHhtbDogJ2FwcGxpY2F0aW9uL3htbCcsXG4gIHVybGVuY29kZWQ6ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnLFxuICAnZm9ybSc6ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnLFxuICAnZm9ybS1kYXRhJzogJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCdcbn07XG5cbi8qKlxuICogRGVmYXVsdCBzZXJpYWxpemF0aW9uIG1hcC5cbiAqXG4gKiAgICAgc3VwZXJhZ2VudC5zZXJpYWxpemVbJ2FwcGxpY2F0aW9uL3htbCddID0gZnVuY3Rpb24ob2JqKXtcbiAqICAgICAgIHJldHVybiAnZ2VuZXJhdGVkIHhtbCBoZXJlJztcbiAqICAgICB9O1xuICpcbiAqL1xuXG4gcmVxdWVzdC5zZXJpYWxpemUgPSB7XG4gICAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJzogc2VyaWFsaXplLFxuICAgJ2FwcGxpY2F0aW9uL2pzb24nOiBKU09OLnN0cmluZ2lmeVxuIH07XG5cbiAvKipcbiAgKiBEZWZhdWx0IHBhcnNlcnMuXG4gICpcbiAgKiAgICAgc3VwZXJhZ2VudC5wYXJzZVsnYXBwbGljYXRpb24veG1sJ10gPSBmdW5jdGlvbihzdHIpe1xuICAqICAgICAgIHJldHVybiB7IG9iamVjdCBwYXJzZWQgZnJvbSBzdHIgfTtcbiAgKiAgICAgfTtcbiAgKlxuICAqL1xuXG5yZXF1ZXN0LnBhcnNlID0ge1xuICAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJzogcGFyc2VTdHJpbmcsXG4gICdhcHBsaWNhdGlvbi9qc29uJzogSlNPTi5wYXJzZVxufTtcblxuLyoqXG4gKiBQYXJzZSB0aGUgZ2l2ZW4gaGVhZGVyIGBzdHJgIGludG9cbiAqIGFuIG9iamVjdCBjb250YWluaW5nIHRoZSBtYXBwZWQgZmllbGRzLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBzdHJcbiAqIEByZXR1cm4ge09iamVjdH1cbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbmZ1bmN0aW9uIHBhcnNlSGVhZGVyKHN0cikge1xuICB2YXIgbGluZXMgPSBzdHIuc3BsaXQoL1xccj9cXG4vKTtcbiAgdmFyIGZpZWxkcyA9IHt9O1xuICB2YXIgaW5kZXg7XG4gIHZhciBsaW5lO1xuICB2YXIgZmllbGQ7XG4gIHZhciB2YWw7XG5cbiAgbGluZXMucG9wKCk7IC8vIHRyYWlsaW5nIENSTEZcblxuICBmb3IgKHZhciBpID0gMCwgbGVuID0gbGluZXMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcbiAgICBsaW5lID0gbGluZXNbaV07XG4gICAgaW5kZXggPSBsaW5lLmluZGV4T2YoJzonKTtcbiAgICBmaWVsZCA9IGxpbmUuc2xpY2UoMCwgaW5kZXgpLnRvTG93ZXJDYXNlKCk7XG4gICAgdmFsID0gdHJpbShsaW5lLnNsaWNlKGluZGV4ICsgMSkpO1xuICAgIGZpZWxkc1tmaWVsZF0gPSB2YWw7XG4gIH1cblxuICByZXR1cm4gZmllbGRzO1xufVxuXG4vKipcbiAqIENoZWNrIGlmIGBtaW1lYCBpcyBqc29uIG9yIGhhcyAranNvbiBzdHJ1Y3R1cmVkIHN5bnRheCBzdWZmaXguXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1pbWVcbiAqIEByZXR1cm4ge0Jvb2xlYW59XG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5mdW5jdGlvbiBpc0pTT04obWltZSkge1xuICByZXR1cm4gL1tcXC8rXWpzb25cXGIvLnRlc3QobWltZSk7XG59XG5cbi8qKlxuICogUmV0dXJuIHRoZSBtaW1lIHR5cGUgZm9yIHRoZSBnaXZlbiBgc3RyYC5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gc3RyXG4gKiBAcmV0dXJuIHtTdHJpbmd9XG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5mdW5jdGlvbiB0eXBlKHN0cil7XG4gIHJldHVybiBzdHIuc3BsaXQoLyAqOyAqLykuc2hpZnQoKTtcbn07XG5cbi8qKlxuICogUmV0dXJuIGhlYWRlciBmaWVsZCBwYXJhbWV0ZXJzLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBzdHJcbiAqIEByZXR1cm4ge09iamVjdH1cbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbmZ1bmN0aW9uIHBhcmFtcyhzdHIpe1xuICByZXR1cm4gcmVkdWNlKHN0ci5zcGxpdCgvICo7ICovKSwgZnVuY3Rpb24ob2JqLCBzdHIpe1xuICAgIHZhciBwYXJ0cyA9IHN0ci5zcGxpdCgvICo9ICovKVxuICAgICAgLCBrZXkgPSBwYXJ0cy5zaGlmdCgpXG4gICAgICAsIHZhbCA9IHBhcnRzLnNoaWZ0KCk7XG5cbiAgICBpZiAoa2V5ICYmIHZhbCkgb2JqW2tleV0gPSB2YWw7XG4gICAgcmV0dXJuIG9iajtcbiAgfSwge30pO1xufTtcblxuLyoqXG4gKiBJbml0aWFsaXplIGEgbmV3IGBSZXNwb25zZWAgd2l0aCB0aGUgZ2l2ZW4gYHhocmAuXG4gKlxuICogIC0gc2V0IGZsYWdzICgub2ssIC5lcnJvciwgZXRjKVxuICogIC0gcGFyc2UgaGVhZGVyXG4gKlxuICogRXhhbXBsZXM6XG4gKlxuICogIEFsaWFzaW5nIGBzdXBlcmFnZW50YCBhcyBgcmVxdWVzdGAgaXMgbmljZTpcbiAqXG4gKiAgICAgIHJlcXVlc3QgPSBzdXBlcmFnZW50O1xuICpcbiAqICBXZSBjYW4gdXNlIHRoZSBwcm9taXNlLWxpa2UgQVBJLCBvciBwYXNzIGNhbGxiYWNrczpcbiAqXG4gKiAgICAgIHJlcXVlc3QuZ2V0KCcvJykuZW5kKGZ1bmN0aW9uKHJlcyl7fSk7XG4gKiAgICAgIHJlcXVlc3QuZ2V0KCcvJywgZnVuY3Rpb24ocmVzKXt9KTtcbiAqXG4gKiAgU2VuZGluZyBkYXRhIGNhbiBiZSBjaGFpbmVkOlxuICpcbiAqICAgICAgcmVxdWVzdFxuICogICAgICAgIC5wb3N0KCcvdXNlcicpXG4gKiAgICAgICAgLnNlbmQoeyBuYW1lOiAndGonIH0pXG4gKiAgICAgICAgLmVuZChmdW5jdGlvbihyZXMpe30pO1xuICpcbiAqICBPciBwYXNzZWQgdG8gYC5zZW5kKClgOlxuICpcbiAqICAgICAgcmVxdWVzdFxuICogICAgICAgIC5wb3N0KCcvdXNlcicpXG4gKiAgICAgICAgLnNlbmQoeyBuYW1lOiAndGonIH0sIGZ1bmN0aW9uKHJlcyl7fSk7XG4gKlxuICogIE9yIHBhc3NlZCB0byBgLnBvc3QoKWA6XG4gKlxuICogICAgICByZXF1ZXN0XG4gKiAgICAgICAgLnBvc3QoJy91c2VyJywgeyBuYW1lOiAndGonIH0pXG4gKiAgICAgICAgLmVuZChmdW5jdGlvbihyZXMpe30pO1xuICpcbiAqIE9yIGZ1cnRoZXIgcmVkdWNlZCB0byBhIHNpbmdsZSBjYWxsIGZvciBzaW1wbGUgY2FzZXM6XG4gKlxuICogICAgICByZXF1ZXN0XG4gKiAgICAgICAgLnBvc3QoJy91c2VyJywgeyBuYW1lOiAndGonIH0sIGZ1bmN0aW9uKHJlcyl7fSk7XG4gKlxuICogQHBhcmFtIHtYTUxIVFRQUmVxdWVzdH0geGhyXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gUmVzcG9uc2UocmVxLCBvcHRpb25zKSB7XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICB0aGlzLnJlcSA9IHJlcTtcbiAgdGhpcy54aHIgPSB0aGlzLnJlcS54aHI7XG4gIC8vIHJlc3BvbnNlVGV4dCBpcyBhY2Nlc3NpYmxlIG9ubHkgaWYgcmVzcG9uc2VUeXBlIGlzICcnIG9yICd0ZXh0JyBhbmQgb24gb2xkZXIgYnJvd3NlcnNcbiAgdGhpcy50ZXh0ID0gKCh0aGlzLnJlcS5tZXRob2QgIT0nSEVBRCcgJiYgKHRoaXMueGhyLnJlc3BvbnNlVHlwZSA9PT0gJycgfHwgdGhpcy54aHIucmVzcG9uc2VUeXBlID09PSAndGV4dCcpKSB8fCB0eXBlb2YgdGhpcy54aHIucmVzcG9uc2VUeXBlID09PSAndW5kZWZpbmVkJylcbiAgICAgPyB0aGlzLnhoci5yZXNwb25zZVRleHRcbiAgICAgOiBudWxsO1xuICB0aGlzLnN0YXR1c1RleHQgPSB0aGlzLnJlcS54aHIuc3RhdHVzVGV4dDtcbiAgdGhpcy5zZXRTdGF0dXNQcm9wZXJ0aWVzKHRoaXMueGhyLnN0YXR1cyk7XG4gIHRoaXMuaGVhZGVyID0gdGhpcy5oZWFkZXJzID0gcGFyc2VIZWFkZXIodGhpcy54aHIuZ2V0QWxsUmVzcG9uc2VIZWFkZXJzKCkpO1xuICAvLyBnZXRBbGxSZXNwb25zZUhlYWRlcnMgc29tZXRpbWVzIGZhbHNlbHkgcmV0dXJucyBcIlwiIGZvciBDT1JTIHJlcXVlc3RzLCBidXRcbiAgLy8gZ2V0UmVzcG9uc2VIZWFkZXIgc3RpbGwgd29ya3MuIHNvIHdlIGdldCBjb250ZW50LXR5cGUgZXZlbiBpZiBnZXR0aW5nXG4gIC8vIG90aGVyIGhlYWRlcnMgZmFpbHMuXG4gIHRoaXMuaGVhZGVyWydjb250ZW50LXR5cGUnXSA9IHRoaXMueGhyLmdldFJlc3BvbnNlSGVhZGVyKCdjb250ZW50LXR5cGUnKTtcbiAgdGhpcy5zZXRIZWFkZXJQcm9wZXJ0aWVzKHRoaXMuaGVhZGVyKTtcbiAgdGhpcy5ib2R5ID0gdGhpcy5yZXEubWV0aG9kICE9ICdIRUFEJ1xuICAgID8gdGhpcy5wYXJzZUJvZHkodGhpcy50ZXh0ID8gdGhpcy50ZXh0IDogdGhpcy54aHIucmVzcG9uc2UpXG4gICAgOiBudWxsO1xufVxuXG4vKipcbiAqIEdldCBjYXNlLWluc2Vuc2l0aXZlIGBmaWVsZGAgdmFsdWUuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGZpZWxkXG4gKiBAcmV0dXJuIHtTdHJpbmd9XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblJlc3BvbnNlLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbihmaWVsZCl7XG4gIHJldHVybiB0aGlzLmhlYWRlcltmaWVsZC50b0xvd2VyQ2FzZSgpXTtcbn07XG5cbi8qKlxuICogU2V0IGhlYWRlciByZWxhdGVkIHByb3BlcnRpZXM6XG4gKlxuICogICAtIGAudHlwZWAgdGhlIGNvbnRlbnQgdHlwZSB3aXRob3V0IHBhcmFtc1xuICpcbiAqIEEgcmVzcG9uc2Ugb2YgXCJDb250ZW50LVR5cGU6IHRleHQvcGxhaW47IGNoYXJzZXQ9dXRmLThcIlxuICogd2lsbCBwcm92aWRlIHlvdSB3aXRoIGEgYC50eXBlYCBvZiBcInRleHQvcGxhaW5cIi5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gaGVhZGVyXG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5SZXNwb25zZS5wcm90b3R5cGUuc2V0SGVhZGVyUHJvcGVydGllcyA9IGZ1bmN0aW9uKGhlYWRlcil7XG4gIC8vIGNvbnRlbnQtdHlwZVxuICB2YXIgY3QgPSB0aGlzLmhlYWRlclsnY29udGVudC10eXBlJ10gfHwgJyc7XG4gIHRoaXMudHlwZSA9IHR5cGUoY3QpO1xuXG4gIC8vIHBhcmFtc1xuICB2YXIgb2JqID0gcGFyYW1zKGN0KTtcbiAgZm9yICh2YXIga2V5IGluIG9iaikgdGhpc1trZXldID0gb2JqW2tleV07XG59O1xuXG4vKipcbiAqIFBhcnNlIHRoZSBnaXZlbiBib2R5IGBzdHJgLlxuICpcbiAqIFVzZWQgZm9yIGF1dG8tcGFyc2luZyBvZiBib2RpZXMuIFBhcnNlcnNcbiAqIGFyZSBkZWZpbmVkIG9uIHRoZSBgc3VwZXJhZ2VudC5wYXJzZWAgb2JqZWN0LlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBzdHJcbiAqIEByZXR1cm4ge01peGVkfVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuUmVzcG9uc2UucHJvdG90eXBlLnBhcnNlQm9keSA9IGZ1bmN0aW9uKHN0cil7XG4gIHZhciBwYXJzZSA9IHJlcXVlc3QucGFyc2VbdGhpcy50eXBlXTtcbiAgaWYgKCFwYXJzZSAmJiBpc0pTT04odGhpcy50eXBlKSkge1xuICAgIHBhcnNlID0gcmVxdWVzdC5wYXJzZVsnYXBwbGljYXRpb24vanNvbiddO1xuICB9XG4gIHJldHVybiBwYXJzZSAmJiBzdHIgJiYgKHN0ci5sZW5ndGggfHwgc3RyIGluc3RhbmNlb2YgT2JqZWN0KVxuICAgID8gcGFyc2Uoc3RyKVxuICAgIDogbnVsbDtcbn07XG5cbi8qKlxuICogU2V0IGZsYWdzIHN1Y2ggYXMgYC5va2AgYmFzZWQgb24gYHN0YXR1c2AuXG4gKlxuICogRm9yIGV4YW1wbGUgYSAyeHggcmVzcG9uc2Ugd2lsbCBnaXZlIHlvdSBhIGAub2tgIG9mIF9fdHJ1ZV9fXG4gKiB3aGVyZWFzIDV4eCB3aWxsIGJlIF9fZmFsc2VfXyBhbmQgYC5lcnJvcmAgd2lsbCBiZSBfX3RydWVfXy4gVGhlXG4gKiBgLmNsaWVudEVycm9yYCBhbmQgYC5zZXJ2ZXJFcnJvcmAgYXJlIGFsc28gYXZhaWxhYmxlIHRvIGJlIG1vcmVcbiAqIHNwZWNpZmljLCBhbmQgYC5zdGF0dXNUeXBlYCBpcyB0aGUgY2xhc3Mgb2YgZXJyb3IgcmFuZ2luZyBmcm9tIDEuLjVcbiAqIHNvbWV0aW1lcyB1c2VmdWwgZm9yIG1hcHBpbmcgcmVzcG9uZCBjb2xvcnMgZXRjLlxuICpcbiAqIFwic3VnYXJcIiBwcm9wZXJ0aWVzIGFyZSBhbHNvIGRlZmluZWQgZm9yIGNvbW1vbiBjYXNlcy4gQ3VycmVudGx5IHByb3ZpZGluZzpcbiAqXG4gKiAgIC0gLm5vQ29udGVudFxuICogICAtIC5iYWRSZXF1ZXN0XG4gKiAgIC0gLnVuYXV0aG9yaXplZFxuICogICAtIC5ub3RBY2NlcHRhYmxlXG4gKiAgIC0gLm5vdEZvdW5kXG4gKlxuICogQHBhcmFtIHtOdW1iZXJ9IHN0YXR1c1xuICogQGFwaSBwcml2YXRlXG4gKi9cblxuUmVzcG9uc2UucHJvdG90eXBlLnNldFN0YXR1c1Byb3BlcnRpZXMgPSBmdW5jdGlvbihzdGF0dXMpe1xuICAvLyBoYW5kbGUgSUU5IGJ1ZzogaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8xMDA0Njk3Mi9tc2llLXJldHVybnMtc3RhdHVzLWNvZGUtb2YtMTIyMy1mb3ItYWpheC1yZXF1ZXN0XG4gIGlmIChzdGF0dXMgPT09IDEyMjMpIHtcbiAgICBzdGF0dXMgPSAyMDQ7XG4gIH1cblxuICB2YXIgdHlwZSA9IHN0YXR1cyAvIDEwMCB8IDA7XG5cbiAgLy8gc3RhdHVzIC8gY2xhc3NcbiAgdGhpcy5zdGF0dXMgPSB0aGlzLnN0YXR1c0NvZGUgPSBzdGF0dXM7XG4gIHRoaXMuc3RhdHVzVHlwZSA9IHR5cGU7XG5cbiAgLy8gYmFzaWNzXG4gIHRoaXMuaW5mbyA9IDEgPT0gdHlwZTtcbiAgdGhpcy5vayA9IDIgPT0gdHlwZTtcbiAgdGhpcy5jbGllbnRFcnJvciA9IDQgPT0gdHlwZTtcbiAgdGhpcy5zZXJ2ZXJFcnJvciA9IDUgPT0gdHlwZTtcbiAgdGhpcy5lcnJvciA9ICg0ID09IHR5cGUgfHwgNSA9PSB0eXBlKVxuICAgID8gdGhpcy50b0Vycm9yKClcbiAgICA6IGZhbHNlO1xuXG4gIC8vIHN1Z2FyXG4gIHRoaXMuYWNjZXB0ZWQgPSAyMDIgPT0gc3RhdHVzO1xuICB0aGlzLm5vQ29udGVudCA9IDIwNCA9PSBzdGF0dXM7XG4gIHRoaXMuYmFkUmVxdWVzdCA9IDQwMCA9PSBzdGF0dXM7XG4gIHRoaXMudW5hdXRob3JpemVkID0gNDAxID09IHN0YXR1cztcbiAgdGhpcy5ub3RBY2NlcHRhYmxlID0gNDA2ID09IHN0YXR1cztcbiAgdGhpcy5ub3RGb3VuZCA9IDQwNCA9PSBzdGF0dXM7XG4gIHRoaXMuZm9yYmlkZGVuID0gNDAzID09IHN0YXR1cztcbn07XG5cbi8qKlxuICogUmV0dXJuIGFuIGBFcnJvcmAgcmVwcmVzZW50YXRpdmUgb2YgdGhpcyByZXNwb25zZS5cbiAqXG4gKiBAcmV0dXJuIHtFcnJvcn1cbiAqIEBhcGkgcHVibGljXG4gKi9cblxuUmVzcG9uc2UucHJvdG90eXBlLnRvRXJyb3IgPSBmdW5jdGlvbigpe1xuICB2YXIgcmVxID0gdGhpcy5yZXE7XG4gIHZhciBtZXRob2QgPSByZXEubWV0aG9kO1xuICB2YXIgdXJsID0gcmVxLnVybDtcblxuICB2YXIgbXNnID0gJ2Nhbm5vdCAnICsgbWV0aG9kICsgJyAnICsgdXJsICsgJyAoJyArIHRoaXMuc3RhdHVzICsgJyknO1xuICB2YXIgZXJyID0gbmV3IEVycm9yKG1zZyk7XG4gIGVyci5zdGF0dXMgPSB0aGlzLnN0YXR1cztcbiAgZXJyLm1ldGhvZCA9IG1ldGhvZDtcbiAgZXJyLnVybCA9IHVybDtcblxuICByZXR1cm4gZXJyO1xufTtcblxuLyoqXG4gKiBFeHBvc2UgYFJlc3BvbnNlYC5cbiAqL1xuXG5yZXF1ZXN0LlJlc3BvbnNlID0gUmVzcG9uc2U7XG5cbi8qKlxuICogSW5pdGlhbGl6ZSBhIG5ldyBgUmVxdWVzdGAgd2l0aCB0aGUgZ2l2ZW4gYG1ldGhvZGAgYW5kIGB1cmxgLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2RcbiAqIEBwYXJhbSB7U3RyaW5nfSB1cmxcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuZnVuY3Rpb24gUmVxdWVzdChtZXRob2QsIHVybCkge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHRoaXMuX3F1ZXJ5ID0gdGhpcy5fcXVlcnkgfHwgW107XG4gIHRoaXMubWV0aG9kID0gbWV0aG9kO1xuICB0aGlzLnVybCA9IHVybDtcbiAgdGhpcy5oZWFkZXIgPSB7fTsgLy8gcHJlc2VydmVzIGhlYWRlciBuYW1lIGNhc2VcbiAgdGhpcy5faGVhZGVyID0ge307IC8vIGNvZXJjZXMgaGVhZGVyIG5hbWVzIHRvIGxvd2VyY2FzZVxuICB0aGlzLm9uKCdlbmQnLCBmdW5jdGlvbigpe1xuICAgIHZhciBlcnIgPSBudWxsO1xuICAgIHZhciByZXMgPSBudWxsO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlcyA9IG5ldyBSZXNwb25zZShzZWxmKTtcbiAgICB9IGNhdGNoKGUpIHtcbiAgICAgIGVyciA9IG5ldyBFcnJvcignUGFyc2VyIGlzIHVuYWJsZSB0byBwYXJzZSB0aGUgcmVzcG9uc2UnKTtcbiAgICAgIGVyci5wYXJzZSA9IHRydWU7XG4gICAgICBlcnIub3JpZ2luYWwgPSBlO1xuICAgICAgLy8gaXNzdWUgIzY3NTogcmV0dXJuIHRoZSByYXcgcmVzcG9uc2UgaWYgdGhlIHJlc3BvbnNlIHBhcnNpbmcgZmFpbHNcbiAgICAgIGVyci5yYXdSZXNwb25zZSA9IHNlbGYueGhyICYmIHNlbGYueGhyLnJlc3BvbnNlVGV4dCA/IHNlbGYueGhyLnJlc3BvbnNlVGV4dCA6IG51bGw7XG4gICAgICAvLyBpc3N1ZSAjODc2OiByZXR1cm4gdGhlIGh0dHAgc3RhdHVzIGNvZGUgaWYgdGhlIHJlc3BvbnNlIHBhcnNpbmcgZmFpbHNcbiAgICAgIGVyci5zdGF0dXNDb2RlID0gc2VsZi54aHIgJiYgc2VsZi54aHIuc3RhdHVzID8gc2VsZi54aHIuc3RhdHVzIDogbnVsbDtcbiAgICAgIHJldHVybiBzZWxmLmNhbGxiYWNrKGVycik7XG4gICAgfVxuXG4gICAgc2VsZi5lbWl0KCdyZXNwb25zZScsIHJlcyk7XG5cbiAgICBpZiAoZXJyKSB7XG4gICAgICByZXR1cm4gc2VsZi5jYWxsYmFjayhlcnIsIHJlcyk7XG4gICAgfVxuXG4gICAgaWYgKHJlcy5zdGF0dXMgPj0gMjAwICYmIHJlcy5zdGF0dXMgPCAzMDApIHtcbiAgICAgIHJldHVybiBzZWxmLmNhbGxiYWNrKGVyciwgcmVzKTtcbiAgICB9XG5cbiAgICB2YXIgbmV3X2VyciA9IG5ldyBFcnJvcihyZXMuc3RhdHVzVGV4dCB8fCAnVW5zdWNjZXNzZnVsIEhUVFAgcmVzcG9uc2UnKTtcbiAgICBuZXdfZXJyLm9yaWdpbmFsID0gZXJyO1xuICAgIG5ld19lcnIucmVzcG9uc2UgPSByZXM7XG4gICAgbmV3X2Vyci5zdGF0dXMgPSByZXMuc3RhdHVzO1xuXG4gICAgc2VsZi5jYWxsYmFjayhuZXdfZXJyLCByZXMpO1xuICB9KTtcbn1cblxuLyoqXG4gKiBNaXhpbiBgRW1pdHRlcmAgYW5kIGByZXF1ZXN0QmFzZWAuXG4gKi9cblxuRW1pdHRlcihSZXF1ZXN0LnByb3RvdHlwZSk7XG5mb3IgKHZhciBrZXkgaW4gcmVxdWVzdEJhc2UpIHtcbiAgUmVxdWVzdC5wcm90b3R5cGVba2V5XSA9IHJlcXVlc3RCYXNlW2tleV07XG59XG5cbi8qKlxuICogQWJvcnQgdGhlIHJlcXVlc3QsIGFuZCBjbGVhciBwb3RlbnRpYWwgdGltZW91dC5cbiAqXG4gKiBAcmV0dXJuIHtSZXF1ZXN0fVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5SZXF1ZXN0LnByb3RvdHlwZS5hYm9ydCA9IGZ1bmN0aW9uKCl7XG4gIGlmICh0aGlzLmFib3J0ZWQpIHJldHVybjtcbiAgdGhpcy5hYm9ydGVkID0gdHJ1ZTtcbiAgdGhpcy54aHIuYWJvcnQoKTtcbiAgdGhpcy5jbGVhclRpbWVvdXQoKTtcbiAgdGhpcy5lbWl0KCdhYm9ydCcpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogU2V0IENvbnRlbnQtVHlwZSB0byBgdHlwZWAsIG1hcHBpbmcgdmFsdWVzIGZyb20gYHJlcXVlc3QudHlwZXNgLlxuICpcbiAqIEV4YW1wbGVzOlxuICpcbiAqICAgICAgc3VwZXJhZ2VudC50eXBlcy54bWwgPSAnYXBwbGljYXRpb24veG1sJztcbiAqXG4gKiAgICAgIHJlcXVlc3QucG9zdCgnLycpXG4gKiAgICAgICAgLnR5cGUoJ3htbCcpXG4gKiAgICAgICAgLnNlbmQoeG1sc3RyaW5nKVxuICogICAgICAgIC5lbmQoY2FsbGJhY2spO1xuICpcbiAqICAgICAgcmVxdWVzdC5wb3N0KCcvJylcbiAqICAgICAgICAudHlwZSgnYXBwbGljYXRpb24veG1sJylcbiAqICAgICAgICAuc2VuZCh4bWxzdHJpbmcpXG4gKiAgICAgICAgLmVuZChjYWxsYmFjayk7XG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHR5cGVcbiAqIEByZXR1cm4ge1JlcXVlc3R9IGZvciBjaGFpbmluZ1xuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5SZXF1ZXN0LnByb3RvdHlwZS50eXBlID0gZnVuY3Rpb24odHlwZSl7XG4gIHRoaXMuc2V0KCdDb250ZW50LVR5cGUnLCByZXF1ZXN0LnR5cGVzW3R5cGVdIHx8IHR5cGUpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogU2V0IHJlc3BvbnNlVHlwZSB0byBgdmFsYC4gUHJlc2VudGx5IHZhbGlkIHJlc3BvbnNlVHlwZXMgYXJlICdibG9iJyBhbmQgXG4gKiAnYXJyYXlidWZmZXInLlxuICpcbiAqIEV4YW1wbGVzOlxuICpcbiAqICAgICAgcmVxLmdldCgnLycpXG4gKiAgICAgICAgLnJlc3BvbnNlVHlwZSgnYmxvYicpXG4gKiAgICAgICAgLmVuZChjYWxsYmFjayk7XG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHZhbFxuICogQHJldHVybiB7UmVxdWVzdH0gZm9yIGNoYWluaW5nXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblJlcXVlc3QucHJvdG90eXBlLnJlc3BvbnNlVHlwZSA9IGZ1bmN0aW9uKHZhbCl7XG4gIHRoaXMuX3Jlc3BvbnNlVHlwZSA9IHZhbDtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFNldCBBY2NlcHQgdG8gYHR5cGVgLCBtYXBwaW5nIHZhbHVlcyBmcm9tIGByZXF1ZXN0LnR5cGVzYC5cbiAqXG4gKiBFeGFtcGxlczpcbiAqXG4gKiAgICAgIHN1cGVyYWdlbnQudHlwZXMuanNvbiA9ICdhcHBsaWNhdGlvbi9qc29uJztcbiAqXG4gKiAgICAgIHJlcXVlc3QuZ2V0KCcvYWdlbnQnKVxuICogICAgICAgIC5hY2NlcHQoJ2pzb24nKVxuICogICAgICAgIC5lbmQoY2FsbGJhY2spO1xuICpcbiAqICAgICAgcmVxdWVzdC5nZXQoJy9hZ2VudCcpXG4gKiAgICAgICAgLmFjY2VwdCgnYXBwbGljYXRpb24vanNvbicpXG4gKiAgICAgICAgLmVuZChjYWxsYmFjayk7XG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGFjY2VwdFxuICogQHJldHVybiB7UmVxdWVzdH0gZm9yIGNoYWluaW5nXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblJlcXVlc3QucHJvdG90eXBlLmFjY2VwdCA9IGZ1bmN0aW9uKHR5cGUpe1xuICB0aGlzLnNldCgnQWNjZXB0JywgcmVxdWVzdC50eXBlc1t0eXBlXSB8fCB0eXBlKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFNldCBBdXRob3JpemF0aW9uIGZpZWxkIHZhbHVlIHdpdGggYHVzZXJgIGFuZCBgcGFzc2AuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHVzZXJcbiAqIEBwYXJhbSB7U3RyaW5nfSBwYXNzXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyB3aXRoICd0eXBlJyBwcm9wZXJ0eSAnYXV0bycgb3IgJ2Jhc2ljJyAoZGVmYXVsdCAnYmFzaWMnKVxuICogQHJldHVybiB7UmVxdWVzdH0gZm9yIGNoYWluaW5nXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblJlcXVlc3QucHJvdG90eXBlLmF1dGggPSBmdW5jdGlvbih1c2VyLCBwYXNzLCBvcHRpb25zKXtcbiAgaWYgKCFvcHRpb25zKSB7XG4gICAgb3B0aW9ucyA9IHtcbiAgICAgIHR5cGU6ICdiYXNpYydcbiAgICB9XG4gIH1cblxuICBzd2l0Y2ggKG9wdGlvbnMudHlwZSkge1xuICAgIGNhc2UgJ2Jhc2ljJzpcbiAgICAgIHZhciBzdHIgPSBidG9hKHVzZXIgKyAnOicgKyBwYXNzKTtcbiAgICAgIHRoaXMuc2V0KCdBdXRob3JpemF0aW9uJywgJ0Jhc2ljICcgKyBzdHIpO1xuICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnYXV0byc6XG4gICAgICB0aGlzLnVzZXJuYW1lID0gdXNlcjtcbiAgICAgIHRoaXMucGFzc3dvcmQgPSBwYXNzO1xuICAgIGJyZWFrO1xuICB9XG4gIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4qIEFkZCBxdWVyeS1zdHJpbmcgYHZhbGAuXG4qXG4qIEV4YW1wbGVzOlxuKlxuKiAgIHJlcXVlc3QuZ2V0KCcvc2hvZXMnKVxuKiAgICAgLnF1ZXJ5KCdzaXplPTEwJylcbiogICAgIC5xdWVyeSh7IGNvbG9yOiAnYmx1ZScgfSlcbipcbiogQHBhcmFtIHtPYmplY3R8U3RyaW5nfSB2YWxcbiogQHJldHVybiB7UmVxdWVzdH0gZm9yIGNoYWluaW5nXG4qIEBhcGkgcHVibGljXG4qL1xuXG5SZXF1ZXN0LnByb3RvdHlwZS5xdWVyeSA9IGZ1bmN0aW9uKHZhbCl7XG4gIGlmICgnc3RyaW5nJyAhPSB0eXBlb2YgdmFsKSB2YWwgPSBzZXJpYWxpemUodmFsKTtcbiAgaWYgKHZhbCkgdGhpcy5fcXVlcnkucHVzaCh2YWwpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogUXVldWUgdGhlIGdpdmVuIGBmaWxlYCBhcyBhbiBhdHRhY2htZW50IHRvIHRoZSBzcGVjaWZpZWQgYGZpZWxkYCxcbiAqIHdpdGggb3B0aW9uYWwgYGZpbGVuYW1lYC5cbiAqXG4gKiBgYGAganNcbiAqIHJlcXVlc3QucG9zdCgnL3VwbG9hZCcpXG4gKiAgIC5hdHRhY2gobmV3IEJsb2IoWyc8YSBpZD1cImFcIj48YiBpZD1cImJcIj5oZXkhPC9iPjwvYT4nXSwgeyB0eXBlOiBcInRleHQvaHRtbFwifSkpXG4gKiAgIC5lbmQoY2FsbGJhY2spO1xuICogYGBgXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGZpZWxkXG4gKiBAcGFyYW0ge0Jsb2J8RmlsZX0gZmlsZVxuICogQHBhcmFtIHtTdHJpbmd9IGZpbGVuYW1lXG4gKiBAcmV0dXJuIHtSZXF1ZXN0fSBmb3IgY2hhaW5pbmdcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuUmVxdWVzdC5wcm90b3R5cGUuYXR0YWNoID0gZnVuY3Rpb24oZmllbGQsIGZpbGUsIGZpbGVuYW1lKXtcbiAgdGhpcy5fZ2V0Rm9ybURhdGEoKS5hcHBlbmQoZmllbGQsIGZpbGUsIGZpbGVuYW1lIHx8IGZpbGUubmFtZSk7XG4gIHJldHVybiB0aGlzO1xufTtcblxuUmVxdWVzdC5wcm90b3R5cGUuX2dldEZvcm1EYXRhID0gZnVuY3Rpb24oKXtcbiAgaWYgKCF0aGlzLl9mb3JtRGF0YSkge1xuICAgIHRoaXMuX2Zvcm1EYXRhID0gbmV3IHJvb3QuRm9ybURhdGEoKTtcbiAgfVxuICByZXR1cm4gdGhpcy5fZm9ybURhdGE7XG59O1xuXG4vKipcbiAqIFNlbmQgYGRhdGFgIGFzIHRoZSByZXF1ZXN0IGJvZHksIGRlZmF1bHRpbmcgdGhlIGAudHlwZSgpYCB0byBcImpzb25cIiB3aGVuXG4gKiBhbiBvYmplY3QgaXMgZ2l2ZW4uXG4gKlxuICogRXhhbXBsZXM6XG4gKlxuICogICAgICAgLy8gbWFudWFsIGpzb25cbiAqICAgICAgIHJlcXVlc3QucG9zdCgnL3VzZXInKVxuICogICAgICAgICAudHlwZSgnanNvbicpXG4gKiAgICAgICAgIC5zZW5kKCd7XCJuYW1lXCI6XCJ0alwifScpXG4gKiAgICAgICAgIC5lbmQoY2FsbGJhY2spXG4gKlxuICogICAgICAgLy8gYXV0byBqc29uXG4gKiAgICAgICByZXF1ZXN0LnBvc3QoJy91c2VyJylcbiAqICAgICAgICAgLnNlbmQoeyBuYW1lOiAndGonIH0pXG4gKiAgICAgICAgIC5lbmQoY2FsbGJhY2spXG4gKlxuICogICAgICAgLy8gbWFudWFsIHgtd3d3LWZvcm0tdXJsZW5jb2RlZFxuICogICAgICAgcmVxdWVzdC5wb3N0KCcvdXNlcicpXG4gKiAgICAgICAgIC50eXBlKCdmb3JtJylcbiAqICAgICAgICAgLnNlbmQoJ25hbWU9dGonKVxuICogICAgICAgICAuZW5kKGNhbGxiYWNrKVxuICpcbiAqICAgICAgIC8vIGF1dG8geC13d3ctZm9ybS11cmxlbmNvZGVkXG4gKiAgICAgICByZXF1ZXN0LnBvc3QoJy91c2VyJylcbiAqICAgICAgICAgLnR5cGUoJ2Zvcm0nKVxuICogICAgICAgICAuc2VuZCh7IG5hbWU6ICd0aicgfSlcbiAqICAgICAgICAgLmVuZChjYWxsYmFjaylcbiAqXG4gKiAgICAgICAvLyBkZWZhdWx0cyB0byB4LXd3dy1mb3JtLXVybGVuY29kZWRcbiAgKiAgICAgIHJlcXVlc3QucG9zdCgnL3VzZXInKVxuICAqICAgICAgICAuc2VuZCgnbmFtZT10b2JpJylcbiAgKiAgICAgICAgLnNlbmQoJ3NwZWNpZXM9ZmVycmV0JylcbiAgKiAgICAgICAgLmVuZChjYWxsYmFjaylcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R9IGRhdGFcbiAqIEByZXR1cm4ge1JlcXVlc3R9IGZvciBjaGFpbmluZ1xuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5SZXF1ZXN0LnByb3RvdHlwZS5zZW5kID0gZnVuY3Rpb24oZGF0YSl7XG4gIHZhciBvYmogPSBpc09iamVjdChkYXRhKTtcbiAgdmFyIHR5cGUgPSB0aGlzLl9oZWFkZXJbJ2NvbnRlbnQtdHlwZSddO1xuXG4gIC8vIG1lcmdlXG4gIGlmIChvYmogJiYgaXNPYmplY3QodGhpcy5fZGF0YSkpIHtcbiAgICBmb3IgKHZhciBrZXkgaW4gZGF0YSkge1xuICAgICAgdGhpcy5fZGF0YVtrZXldID0gZGF0YVtrZXldO1xuICAgIH1cbiAgfSBlbHNlIGlmICgnc3RyaW5nJyA9PSB0eXBlb2YgZGF0YSkge1xuICAgIGlmICghdHlwZSkgdGhpcy50eXBlKCdmb3JtJyk7XG4gICAgdHlwZSA9IHRoaXMuX2hlYWRlclsnY29udGVudC10eXBlJ107XG4gICAgaWYgKCdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnID09IHR5cGUpIHtcbiAgICAgIHRoaXMuX2RhdGEgPSB0aGlzLl9kYXRhXG4gICAgICAgID8gdGhpcy5fZGF0YSArICcmJyArIGRhdGFcbiAgICAgICAgOiBkYXRhO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9kYXRhID0gKHRoaXMuX2RhdGEgfHwgJycpICsgZGF0YTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGhpcy5fZGF0YSA9IGRhdGE7XG4gIH1cblxuICBpZiAoIW9iaiB8fCBpc0hvc3QoZGF0YSkpIHJldHVybiB0aGlzO1xuICBpZiAoIXR5cGUpIHRoaXMudHlwZSgnanNvbicpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogQGRlcHJlY2F0ZWRcbiAqL1xuUmVzcG9uc2UucHJvdG90eXBlLnBhcnNlID0gZnVuY3Rpb24gc2VyaWFsaXplKGZuKXtcbiAgaWYgKHJvb3QuY29uc29sZSkge1xuICAgIGNvbnNvbGUud2FybihcIkNsaWVudC1zaWRlIHBhcnNlKCkgbWV0aG9kIGhhcyBiZWVuIHJlbmFtZWQgdG8gc2VyaWFsaXplKCkuIFRoaXMgbWV0aG9kIGlzIG5vdCBjb21wYXRpYmxlIHdpdGggc3VwZXJhZ2VudCB2Mi4wXCIpO1xuICB9XG4gIHRoaXMuc2VyaWFsaXplKGZuKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5SZXNwb25zZS5wcm90b3R5cGUuc2VyaWFsaXplID0gZnVuY3Rpb24gc2VyaWFsaXplKGZuKXtcbiAgdGhpcy5fcGFyc2VyID0gZm47XG4gIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4gKiBJbnZva2UgdGhlIGNhbGxiYWNrIHdpdGggYGVycmAgYW5kIGByZXNgXG4gKiBhbmQgaGFuZGxlIGFyaXR5IGNoZWNrLlxuICpcbiAqIEBwYXJhbSB7RXJyb3J9IGVyclxuICogQHBhcmFtIHtSZXNwb25zZX0gcmVzXG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5SZXF1ZXN0LnByb3RvdHlwZS5jYWxsYmFjayA9IGZ1bmN0aW9uKGVyciwgcmVzKXtcbiAgdmFyIGZuID0gdGhpcy5fY2FsbGJhY2s7XG4gIHRoaXMuY2xlYXJUaW1lb3V0KCk7XG4gIGZuKGVyciwgcmVzKTtcbn07XG5cbi8qKlxuICogSW52b2tlIGNhbGxiYWNrIHdpdGggeC1kb21haW4gZXJyb3IuXG4gKlxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuUmVxdWVzdC5wcm90b3R5cGUuY3Jvc3NEb21haW5FcnJvciA9IGZ1bmN0aW9uKCl7XG4gIHZhciBlcnIgPSBuZXcgRXJyb3IoJ1JlcXVlc3QgaGFzIGJlZW4gdGVybWluYXRlZFxcblBvc3NpYmxlIGNhdXNlczogdGhlIG5ldHdvcmsgaXMgb2ZmbGluZSwgT3JpZ2luIGlzIG5vdCBhbGxvd2VkIGJ5IEFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbiwgdGhlIHBhZ2UgaXMgYmVpbmcgdW5sb2FkZWQsIGV0Yy4nKTtcbiAgZXJyLmNyb3NzRG9tYWluID0gdHJ1ZTtcblxuICBlcnIuc3RhdHVzID0gdGhpcy5zdGF0dXM7XG4gIGVyci5tZXRob2QgPSB0aGlzLm1ldGhvZDtcbiAgZXJyLnVybCA9IHRoaXMudXJsO1xuXG4gIHRoaXMuY2FsbGJhY2soZXJyKTtcbn07XG5cbi8qKlxuICogSW52b2tlIGNhbGxiYWNrIHdpdGggdGltZW91dCBlcnJvci5cbiAqXG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5SZXF1ZXN0LnByb3RvdHlwZS50aW1lb3V0RXJyb3IgPSBmdW5jdGlvbigpe1xuICB2YXIgdGltZW91dCA9IHRoaXMuX3RpbWVvdXQ7XG4gIHZhciBlcnIgPSBuZXcgRXJyb3IoJ3RpbWVvdXQgb2YgJyArIHRpbWVvdXQgKyAnbXMgZXhjZWVkZWQnKTtcbiAgZXJyLnRpbWVvdXQgPSB0aW1lb3V0O1xuICB0aGlzLmNhbGxiYWNrKGVycik7XG59O1xuXG4vKipcbiAqIEVuYWJsZSB0cmFuc21pc3Npb24gb2YgY29va2llcyB3aXRoIHgtZG9tYWluIHJlcXVlc3RzLlxuICpcbiAqIE5vdGUgdGhhdCBmb3IgdGhpcyB0byB3b3JrIHRoZSBvcmlnaW4gbXVzdCBub3QgYmVcbiAqIHVzaW5nIFwiQWNjZXNzLUNvbnRyb2wtQWxsb3ctT3JpZ2luXCIgd2l0aCBhIHdpbGRjYXJkLFxuICogYW5kIGFsc28gbXVzdCBzZXQgXCJBY2Nlc3MtQ29udHJvbC1BbGxvdy1DcmVkZW50aWFsc1wiXG4gKiB0byBcInRydWVcIi5cbiAqXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblJlcXVlc3QucHJvdG90eXBlLndpdGhDcmVkZW50aWFscyA9IGZ1bmN0aW9uKCl7XG4gIHRoaXMuX3dpdGhDcmVkZW50aWFscyA9IHRydWU7XG4gIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4gKiBJbml0aWF0ZSByZXF1ZXN0LCBpbnZva2luZyBjYWxsYmFjayBgZm4ocmVzKWBcbiAqIHdpdGggYW4gaW5zdGFuY2VvZiBgUmVzcG9uc2VgLlxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuXG4gKiBAcmV0dXJuIHtSZXF1ZXN0fSBmb3IgY2hhaW5pbmdcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuUmVxdWVzdC5wcm90b3R5cGUuZW5kID0gZnVuY3Rpb24oZm4pe1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciB4aHIgPSB0aGlzLnhociA9IHJlcXVlc3QuZ2V0WEhSKCk7XG4gIHZhciBxdWVyeSA9IHRoaXMuX3F1ZXJ5LmpvaW4oJyYnKTtcbiAgdmFyIHRpbWVvdXQgPSB0aGlzLl90aW1lb3V0O1xuICB2YXIgZGF0YSA9IHRoaXMuX2Zvcm1EYXRhIHx8IHRoaXMuX2RhdGE7XG5cbiAgLy8gc3RvcmUgY2FsbGJhY2tcbiAgdGhpcy5fY2FsbGJhY2sgPSBmbiB8fCBub29wO1xuXG4gIC8vIHN0YXRlIGNoYW5nZVxuICB4aHIub25yZWFkeXN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKXtcbiAgICBpZiAoNCAhPSB4aHIucmVhZHlTdGF0ZSkgcmV0dXJuO1xuXG4gICAgLy8gSW4gSUU5LCByZWFkcyB0byBhbnkgcHJvcGVydHkgKGUuZy4gc3RhdHVzKSBvZmYgb2YgYW4gYWJvcnRlZCBYSFIgd2lsbFxuICAgIC8vIHJlc3VsdCBpbiB0aGUgZXJyb3IgXCJDb3VsZCBub3QgY29tcGxldGUgdGhlIG9wZXJhdGlvbiBkdWUgdG8gZXJyb3IgYzAwYzAyM2ZcIlxuICAgIHZhciBzdGF0dXM7XG4gICAgdHJ5IHsgc3RhdHVzID0geGhyLnN0YXR1cyB9IGNhdGNoKGUpIHsgc3RhdHVzID0gMDsgfVxuXG4gICAgaWYgKDAgPT0gc3RhdHVzKSB7XG4gICAgICBpZiAoc2VsZi50aW1lZG91dCkgcmV0dXJuIHNlbGYudGltZW91dEVycm9yKCk7XG4gICAgICBpZiAoc2VsZi5hYm9ydGVkKSByZXR1cm47XG4gICAgICByZXR1cm4gc2VsZi5jcm9zc0RvbWFpbkVycm9yKCk7XG4gICAgfVxuICAgIHNlbGYuZW1pdCgnZW5kJyk7XG4gIH07XG5cbiAgLy8gcHJvZ3Jlc3NcbiAgdmFyIGhhbmRsZVByb2dyZXNzID0gZnVuY3Rpb24oZSl7XG4gICAgaWYgKGUudG90YWwgPiAwKSB7XG4gICAgICBlLnBlcmNlbnQgPSBlLmxvYWRlZCAvIGUudG90YWwgKiAxMDA7XG4gICAgfVxuICAgIGUuZGlyZWN0aW9uID0gJ2Rvd25sb2FkJztcbiAgICBzZWxmLmVtaXQoJ3Byb2dyZXNzJywgZSk7XG4gIH07XG4gIGlmICh0aGlzLmhhc0xpc3RlbmVycygncHJvZ3Jlc3MnKSkge1xuICAgIHhoci5vbnByb2dyZXNzID0gaGFuZGxlUHJvZ3Jlc3M7XG4gIH1cbiAgdHJ5IHtcbiAgICBpZiAoeGhyLnVwbG9hZCAmJiB0aGlzLmhhc0xpc3RlbmVycygncHJvZ3Jlc3MnKSkge1xuICAgICAgeGhyLnVwbG9hZC5vbnByb2dyZXNzID0gaGFuZGxlUHJvZ3Jlc3M7XG4gICAgfVxuICB9IGNhdGNoKGUpIHtcbiAgICAvLyBBY2Nlc3NpbmcgeGhyLnVwbG9hZCBmYWlscyBpbiBJRSBmcm9tIGEgd2ViIHdvcmtlciwgc28ganVzdCBwcmV0ZW5kIGl0IGRvZXNuJ3QgZXhpc3QuXG4gICAgLy8gUmVwb3J0ZWQgaGVyZTpcbiAgICAvLyBodHRwczovL2Nvbm5lY3QubWljcm9zb2Z0LmNvbS9JRS9mZWVkYmFjay9kZXRhaWxzLzgzNzI0NS94bWxodHRwcmVxdWVzdC11cGxvYWQtdGhyb3dzLWludmFsaWQtYXJndW1lbnQtd2hlbi11c2VkLWZyb20td2ViLXdvcmtlci1jb250ZXh0XG4gIH1cblxuICAvLyB0aW1lb3V0XG4gIGlmICh0aW1lb3V0ICYmICF0aGlzLl90aW1lcikge1xuICAgIHRoaXMuX3RpbWVyID0gc2V0VGltZW91dChmdW5jdGlvbigpe1xuICAgICAgc2VsZi50aW1lZG91dCA9IHRydWU7XG4gICAgICBzZWxmLmFib3J0KCk7XG4gICAgfSwgdGltZW91dCk7XG4gIH1cblxuICAvLyBxdWVyeXN0cmluZ1xuICBpZiAocXVlcnkpIHtcbiAgICBxdWVyeSA9IHJlcXVlc3Quc2VyaWFsaXplT2JqZWN0KHF1ZXJ5KTtcbiAgICB0aGlzLnVybCArPSB+dGhpcy51cmwuaW5kZXhPZignPycpXG4gICAgICA/ICcmJyArIHF1ZXJ5XG4gICAgICA6ICc/JyArIHF1ZXJ5O1xuICB9XG5cbiAgLy8gaW5pdGlhdGUgcmVxdWVzdFxuICBpZiAodGhpcy51c2VybmFtZSAmJiB0aGlzLnBhc3N3b3JkKSB7XG4gICAgeGhyLm9wZW4odGhpcy5tZXRob2QsIHRoaXMudXJsLCB0cnVlLCB0aGlzLnVzZXJuYW1lLCB0aGlzLnBhc3N3b3JkKTtcbiAgfSBlbHNlIHtcbiAgICB4aHIub3Blbih0aGlzLm1ldGhvZCwgdGhpcy51cmwsIHRydWUpO1xuICB9XG5cbiAgLy8gQ09SU1xuICBpZiAodGhpcy5fd2l0aENyZWRlbnRpYWxzKSB4aHIud2l0aENyZWRlbnRpYWxzID0gdHJ1ZTtcblxuICAvLyBib2R5XG4gIGlmICgnR0VUJyAhPSB0aGlzLm1ldGhvZCAmJiAnSEVBRCcgIT0gdGhpcy5tZXRob2QgJiYgJ3N0cmluZycgIT0gdHlwZW9mIGRhdGEgJiYgIWlzSG9zdChkYXRhKSkge1xuICAgIC8vIHNlcmlhbGl6ZSBzdHVmZlxuICAgIHZhciBjb250ZW50VHlwZSA9IHRoaXMuX2hlYWRlclsnY29udGVudC10eXBlJ107XG4gICAgdmFyIHNlcmlhbGl6ZSA9IHRoaXMuX3BhcnNlciB8fCByZXF1ZXN0LnNlcmlhbGl6ZVtjb250ZW50VHlwZSA/IGNvbnRlbnRUeXBlLnNwbGl0KCc7JylbMF0gOiAnJ107XG4gICAgaWYgKCFzZXJpYWxpemUgJiYgaXNKU09OKGNvbnRlbnRUeXBlKSkgc2VyaWFsaXplID0gcmVxdWVzdC5zZXJpYWxpemVbJ2FwcGxpY2F0aW9uL2pzb24nXTtcbiAgICBpZiAoc2VyaWFsaXplKSBkYXRhID0gc2VyaWFsaXplKGRhdGEpO1xuICB9XG5cbiAgLy8gc2V0IGhlYWRlciBmaWVsZHNcbiAgZm9yICh2YXIgZmllbGQgaW4gdGhpcy5oZWFkZXIpIHtcbiAgICBpZiAobnVsbCA9PSB0aGlzLmhlYWRlcltmaWVsZF0pIGNvbnRpbnVlO1xuICAgIHhoci5zZXRSZXF1ZXN0SGVhZGVyKGZpZWxkLCB0aGlzLmhlYWRlcltmaWVsZF0pO1xuICB9XG5cbiAgaWYgKHRoaXMuX3Jlc3BvbnNlVHlwZSkge1xuICAgIHhoci5yZXNwb25zZVR5cGUgPSB0aGlzLl9yZXNwb25zZVR5cGU7XG4gIH1cblxuICAvLyBzZW5kIHN0dWZmXG4gIHRoaXMuZW1pdCgncmVxdWVzdCcsIHRoaXMpO1xuXG4gIC8vIElFMTEgeGhyLnNlbmQodW5kZWZpbmVkKSBzZW5kcyAndW5kZWZpbmVkJyBzdHJpbmcgYXMgUE9TVCBwYXlsb2FkIChpbnN0ZWFkIG9mIG5vdGhpbmcpXG4gIC8vIFdlIG5lZWQgbnVsbCBoZXJlIGlmIGRhdGEgaXMgdW5kZWZpbmVkXG4gIHhoci5zZW5kKHR5cGVvZiBkYXRhICE9PSAndW5kZWZpbmVkJyA/IGRhdGEgOiBudWxsKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5cbi8qKlxuICogRXhwb3NlIGBSZXF1ZXN0YC5cbiAqL1xuXG5yZXF1ZXN0LlJlcXVlc3QgPSBSZXF1ZXN0O1xuXG4vKipcbiAqIEdFVCBgdXJsYCB3aXRoIG9wdGlvbmFsIGNhbGxiYWNrIGBmbihyZXMpYC5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gdXJsXG4gKiBAcGFyYW0ge01peGVkfEZ1bmN0aW9ufSBkYXRhIG9yIGZuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmblxuICogQHJldHVybiB7UmVxdWVzdH1cbiAqIEBhcGkgcHVibGljXG4gKi9cblxucmVxdWVzdC5nZXQgPSBmdW5jdGlvbih1cmwsIGRhdGEsIGZuKXtcbiAgdmFyIHJlcSA9IHJlcXVlc3QoJ0dFVCcsIHVybCk7XG4gIGlmICgnZnVuY3Rpb24nID09IHR5cGVvZiBkYXRhKSBmbiA9IGRhdGEsIGRhdGEgPSBudWxsO1xuICBpZiAoZGF0YSkgcmVxLnF1ZXJ5KGRhdGEpO1xuICBpZiAoZm4pIHJlcS5lbmQoZm4pO1xuICByZXR1cm4gcmVxO1xufTtcblxuLyoqXG4gKiBIRUFEIGB1cmxgIHdpdGggb3B0aW9uYWwgY2FsbGJhY2sgYGZuKHJlcylgLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSB1cmxcbiAqIEBwYXJhbSB7TWl4ZWR8RnVuY3Rpb259IGRhdGEgb3IgZm5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuXG4gKiBAcmV0dXJuIHtSZXF1ZXN0fVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5yZXF1ZXN0LmhlYWQgPSBmdW5jdGlvbih1cmwsIGRhdGEsIGZuKXtcbiAgdmFyIHJlcSA9IHJlcXVlc3QoJ0hFQUQnLCB1cmwpO1xuICBpZiAoJ2Z1bmN0aW9uJyA9PSB0eXBlb2YgZGF0YSkgZm4gPSBkYXRhLCBkYXRhID0gbnVsbDtcbiAgaWYgKGRhdGEpIHJlcS5zZW5kKGRhdGEpO1xuICBpZiAoZm4pIHJlcS5lbmQoZm4pO1xuICByZXR1cm4gcmVxO1xufTtcblxuLyoqXG4gKiBERUxFVEUgYHVybGAgd2l0aCBvcHRpb25hbCBjYWxsYmFjayBgZm4ocmVzKWAuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHVybFxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm5cbiAqIEByZXR1cm4ge1JlcXVlc3R9XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmZ1bmN0aW9uIGRlbCh1cmwsIGZuKXtcbiAgdmFyIHJlcSA9IHJlcXVlc3QoJ0RFTEVURScsIHVybCk7XG4gIGlmIChmbikgcmVxLmVuZChmbik7XG4gIHJldHVybiByZXE7XG59O1xuXG5yZXF1ZXN0WydkZWwnXSA9IGRlbDtcbnJlcXVlc3RbJ2RlbGV0ZSddID0gZGVsO1xuXG4vKipcbiAqIFBBVENIIGB1cmxgIHdpdGggb3B0aW9uYWwgYGRhdGFgIGFuZCBjYWxsYmFjayBgZm4ocmVzKWAuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHVybFxuICogQHBhcmFtIHtNaXhlZH0gZGF0YVxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm5cbiAqIEByZXR1cm4ge1JlcXVlc3R9XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbnJlcXVlc3QucGF0Y2ggPSBmdW5jdGlvbih1cmwsIGRhdGEsIGZuKXtcbiAgdmFyIHJlcSA9IHJlcXVlc3QoJ1BBVENIJywgdXJsKTtcbiAgaWYgKCdmdW5jdGlvbicgPT0gdHlwZW9mIGRhdGEpIGZuID0gZGF0YSwgZGF0YSA9IG51bGw7XG4gIGlmIChkYXRhKSByZXEuc2VuZChkYXRhKTtcbiAgaWYgKGZuKSByZXEuZW5kKGZuKTtcbiAgcmV0dXJuIHJlcTtcbn07XG5cbi8qKlxuICogUE9TVCBgdXJsYCB3aXRoIG9wdGlvbmFsIGBkYXRhYCBhbmQgY2FsbGJhY2sgYGZuKHJlcylgLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSB1cmxcbiAqIEBwYXJhbSB7TWl4ZWR9IGRhdGFcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuXG4gKiBAcmV0dXJuIHtSZXF1ZXN0fVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5yZXF1ZXN0LnBvc3QgPSBmdW5jdGlvbih1cmwsIGRhdGEsIGZuKXtcbiAgdmFyIHJlcSA9IHJlcXVlc3QoJ1BPU1QnLCB1cmwpO1xuICBpZiAoJ2Z1bmN0aW9uJyA9PSB0eXBlb2YgZGF0YSkgZm4gPSBkYXRhLCBkYXRhID0gbnVsbDtcbiAgaWYgKGRhdGEpIHJlcS5zZW5kKGRhdGEpO1xuICBpZiAoZm4pIHJlcS5lbmQoZm4pO1xuICByZXR1cm4gcmVxO1xufTtcblxuLyoqXG4gKiBQVVQgYHVybGAgd2l0aCBvcHRpb25hbCBgZGF0YWAgYW5kIGNhbGxiYWNrIGBmbihyZXMpYC5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gdXJsXG4gKiBAcGFyYW0ge01peGVkfEZ1bmN0aW9ufSBkYXRhIG9yIGZuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmblxuICogQHJldHVybiB7UmVxdWVzdH1cbiAqIEBhcGkgcHVibGljXG4gKi9cblxucmVxdWVzdC5wdXQgPSBmdW5jdGlvbih1cmwsIGRhdGEsIGZuKXtcbiAgdmFyIHJlcSA9IHJlcXVlc3QoJ1BVVCcsIHVybCk7XG4gIGlmICgnZnVuY3Rpb24nID09IHR5cGVvZiBkYXRhKSBmbiA9IGRhdGEsIGRhdGEgPSBudWxsO1xuICBpZiAoZGF0YSkgcmVxLnNlbmQoZGF0YSk7XG4gIGlmIChmbikgcmVxLmVuZChmbik7XG4gIHJldHVybiByZXE7XG59O1xuIiwiLyoqXG4gKiBDaGVjayBpZiBgb2JqYCBpcyBhbiBvYmplY3QuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9ialxuICogQHJldHVybiB7Qm9vbGVhbn1cbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbmZ1bmN0aW9uIGlzT2JqZWN0KG9iaikge1xuICByZXR1cm4gbnVsbCAhPSBvYmogJiYgJ29iamVjdCcgPT0gdHlwZW9mIG9iajtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpc09iamVjdDtcbiIsIi8qKlxuICogTW9kdWxlIG9mIG1peGVkLWluIGZ1bmN0aW9ucyBzaGFyZWQgYmV0d2VlbiBub2RlIGFuZCBjbGllbnQgY29kZVxuICovXG52YXIgaXNPYmplY3QgPSByZXF1aXJlKCcuL2lzLW9iamVjdCcpO1xuXG4vKipcbiAqIENsZWFyIHByZXZpb3VzIHRpbWVvdXQuXG4gKlxuICogQHJldHVybiB7UmVxdWVzdH0gZm9yIGNoYWluaW5nXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmV4cG9ydHMuY2xlYXJUaW1lb3V0ID0gZnVuY3Rpb24gX2NsZWFyVGltZW91dCgpe1xuICB0aGlzLl90aW1lb3V0ID0gMDtcbiAgY2xlYXJUaW1lb3V0KHRoaXMuX3RpbWVyKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIEZvcmNlIGdpdmVuIHBhcnNlclxuICpcbiAqIFNldHMgdGhlIGJvZHkgcGFyc2VyIG5vIG1hdHRlciB0eXBlLlxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmV4cG9ydHMucGFyc2UgPSBmdW5jdGlvbiBwYXJzZShmbil7XG4gIHRoaXMuX3BhcnNlciA9IGZuO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogU2V0IHRpbWVvdXQgdG8gYG1zYC5cbiAqXG4gKiBAcGFyYW0ge051bWJlcn0gbXNcbiAqIEByZXR1cm4ge1JlcXVlc3R9IGZvciBjaGFpbmluZ1xuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5leHBvcnRzLnRpbWVvdXQgPSBmdW5jdGlvbiB0aW1lb3V0KG1zKXtcbiAgdGhpcy5fdGltZW91dCA9IG1zO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogRmF1eCBwcm9taXNlIHN1cHBvcnRcbiAqXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdWxmaWxsXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSByZWplY3RcbiAqIEByZXR1cm4ge1JlcXVlc3R9XG4gKi9cblxuZXhwb3J0cy50aGVuID0gZnVuY3Rpb24gdGhlbihmdWxmaWxsLCByZWplY3QpIHtcbiAgcmV0dXJuIHRoaXMuZW5kKGZ1bmN0aW9uKGVyciwgcmVzKSB7XG4gICAgZXJyID8gcmVqZWN0KGVycikgOiBmdWxmaWxsKHJlcyk7XG4gIH0pO1xufVxuXG4vKipcbiAqIEFsbG93IGZvciBleHRlbnNpb25cbiAqL1xuXG5leHBvcnRzLnVzZSA9IGZ1bmN0aW9uIHVzZShmbikge1xuICBmbih0aGlzKTtcbiAgcmV0dXJuIHRoaXM7XG59XG5cblxuLyoqXG4gKiBHZXQgcmVxdWVzdCBoZWFkZXIgYGZpZWxkYC5cbiAqIENhc2UtaW5zZW5zaXRpdmUuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGZpZWxkXG4gKiBAcmV0dXJuIHtTdHJpbmd9XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmV4cG9ydHMuZ2V0ID0gZnVuY3Rpb24oZmllbGQpe1xuICByZXR1cm4gdGhpcy5faGVhZGVyW2ZpZWxkLnRvTG93ZXJDYXNlKCldO1xufTtcblxuLyoqXG4gKiBHZXQgY2FzZS1pbnNlbnNpdGl2ZSBoZWFkZXIgYGZpZWxkYCB2YWx1ZS5cbiAqIFRoaXMgaXMgYSBkZXByZWNhdGVkIGludGVybmFsIEFQSS4gVXNlIGAuZ2V0KGZpZWxkKWAgaW5zdGVhZC5cbiAqXG4gKiAoZ2V0SGVhZGVyIGlzIG5vIGxvbmdlciB1c2VkIGludGVybmFsbHkgYnkgdGhlIHN1cGVyYWdlbnQgY29kZSBiYXNlKVxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBmaWVsZFxuICogQHJldHVybiB7U3RyaW5nfVxuICogQGFwaSBwcml2YXRlXG4gKiBAZGVwcmVjYXRlZFxuICovXG5cbmV4cG9ydHMuZ2V0SGVhZGVyID0gZXhwb3J0cy5nZXQ7XG5cbi8qKlxuICogU2V0IGhlYWRlciBgZmllbGRgIHRvIGB2YWxgLCBvciBtdWx0aXBsZSBmaWVsZHMgd2l0aCBvbmUgb2JqZWN0LlxuICogQ2FzZS1pbnNlbnNpdGl2ZS5cbiAqXG4gKiBFeGFtcGxlczpcbiAqXG4gKiAgICAgIHJlcS5nZXQoJy8nKVxuICogICAgICAgIC5zZXQoJ0FjY2VwdCcsICdhcHBsaWNhdGlvbi9qc29uJylcbiAqICAgICAgICAuc2V0KCdYLUFQSS1LZXknLCAnZm9vYmFyJylcbiAqICAgICAgICAuZW5kKGNhbGxiYWNrKTtcbiAqXG4gKiAgICAgIHJlcS5nZXQoJy8nKVxuICogICAgICAgIC5zZXQoeyBBY2NlcHQ6ICdhcHBsaWNhdGlvbi9qc29uJywgJ1gtQVBJLUtleSc6ICdmb29iYXInIH0pXG4gKiAgICAgICAgLmVuZChjYWxsYmFjayk7XG4gKlxuICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fSBmaWVsZFxuICogQHBhcmFtIHtTdHJpbmd9IHZhbFxuICogQHJldHVybiB7UmVxdWVzdH0gZm9yIGNoYWluaW5nXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmV4cG9ydHMuc2V0ID0gZnVuY3Rpb24oZmllbGQsIHZhbCl7XG4gIGlmIChpc09iamVjdChmaWVsZCkpIHtcbiAgICBmb3IgKHZhciBrZXkgaW4gZmllbGQpIHtcbiAgICAgIHRoaXMuc2V0KGtleSwgZmllbGRba2V5XSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG4gIHRoaXMuX2hlYWRlcltmaWVsZC50b0xvd2VyQ2FzZSgpXSA9IHZhbDtcbiAgdGhpcy5oZWFkZXJbZmllbGRdID0gdmFsO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogUmVtb3ZlIGhlYWRlciBgZmllbGRgLlxuICogQ2FzZS1pbnNlbnNpdGl2ZS5cbiAqXG4gKiBFeGFtcGxlOlxuICpcbiAqICAgICAgcmVxLmdldCgnLycpXG4gKiAgICAgICAgLnVuc2V0KCdVc2VyLUFnZW50JylcbiAqICAgICAgICAuZW5kKGNhbGxiYWNrKTtcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gZmllbGRcbiAqL1xuZXhwb3J0cy51bnNldCA9IGZ1bmN0aW9uKGZpZWxkKXtcbiAgZGVsZXRlIHRoaXMuX2hlYWRlcltmaWVsZC50b0xvd2VyQ2FzZSgpXTtcbiAgZGVsZXRlIHRoaXMuaGVhZGVyW2ZpZWxkXTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFdyaXRlIHRoZSBmaWVsZCBgbmFtZWAgYW5kIGB2YWxgIGZvciBcIm11bHRpcGFydC9mb3JtLWRhdGFcIlxuICogcmVxdWVzdCBib2RpZXMuXG4gKlxuICogYGBgIGpzXG4gKiByZXF1ZXN0LnBvc3QoJy91cGxvYWQnKVxuICogICAuZmllbGQoJ2ZvbycsICdiYXInKVxuICogICAuZW5kKGNhbGxiYWNrKTtcbiAqIGBgYFxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gKiBAcGFyYW0ge1N0cmluZ3xCbG9ifEZpbGV8QnVmZmVyfGZzLlJlYWRTdHJlYW19IHZhbFxuICogQHJldHVybiB7UmVxdWVzdH0gZm9yIGNoYWluaW5nXG4gKiBAYXBpIHB1YmxpY1xuICovXG5leHBvcnRzLmZpZWxkID0gZnVuY3Rpb24obmFtZSwgdmFsKSB7XG4gIHRoaXMuX2dldEZvcm1EYXRhKCkuYXBwZW5kKG5hbWUsIHZhbCk7XG4gIHJldHVybiB0aGlzO1xufTtcbiIsIi8vIFRoZSBub2RlIGFuZCBicm93c2VyIG1vZHVsZXMgZXhwb3NlIHZlcnNpb25zIG9mIHRoaXMgd2l0aCB0aGVcbi8vIGFwcHJvcHJpYXRlIGNvbnN0cnVjdG9yIGZ1bmN0aW9uIGJvdW5kIGFzIGZpcnN0IGFyZ3VtZW50XG4vKipcbiAqIElzc3VlIGEgcmVxdWVzdDpcbiAqXG4gKiBFeGFtcGxlczpcbiAqXG4gKiAgICByZXF1ZXN0KCdHRVQnLCAnL3VzZXJzJykuZW5kKGNhbGxiYWNrKVxuICogICAgcmVxdWVzdCgnL3VzZXJzJykuZW5kKGNhbGxiYWNrKVxuICogICAgcmVxdWVzdCgnL3VzZXJzJywgY2FsbGJhY2spXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZFxuICogQHBhcmFtIHtTdHJpbmd8RnVuY3Rpb259IHVybCBvciBjYWxsYmFja1xuICogQHJldHVybiB7UmVxdWVzdH1cbiAqIEBhcGkgcHVibGljXG4gKi9cblxuZnVuY3Rpb24gcmVxdWVzdChSZXF1ZXN0Q29uc3RydWN0b3IsIG1ldGhvZCwgdXJsKSB7XG4gIC8vIGNhbGxiYWNrXG4gIGlmICgnZnVuY3Rpb24nID09IHR5cGVvZiB1cmwpIHtcbiAgICByZXR1cm4gbmV3IFJlcXVlc3RDb25zdHJ1Y3RvcignR0VUJywgbWV0aG9kKS5lbmQodXJsKTtcbiAgfVxuXG4gIC8vIHVybCBmaXJzdFxuICBpZiAoMiA9PSBhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgcmV0dXJuIG5ldyBSZXF1ZXN0Q29uc3RydWN0b3IoJ0dFVCcsIG1ldGhvZCk7XG4gIH1cblxuICByZXR1cm4gbmV3IFJlcXVlc3RDb25zdHJ1Y3RvcihtZXRob2QsIHVybCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWVzdDtcbiIsIi8qISBodHRwczovL210aHMuYmUvcHVueWNvZGUgdjEuMy4yIGJ5IEBtYXRoaWFzLCBtb2RpZmllZCBmb3IgVVJJLmpzICovXHJcblxyXG52YXIgcHVueWNvZGUgPSAoZnVuY3Rpb24gKCkge1xyXG5cclxuXHQvKipcclxuXHQgKiBUaGUgYHB1bnljb2RlYCBvYmplY3QuXHJcblx0ICogQG5hbWUgcHVueWNvZGVcclxuXHQgKiBAdHlwZSBPYmplY3RcclxuXHQgKi9cclxuXHR2YXIgcHVueWNvZGUsXHJcblxyXG5cdC8qKiBIaWdoZXN0IHBvc2l0aXZlIHNpZ25lZCAzMi1iaXQgZmxvYXQgdmFsdWUgKi9cclxuXHRtYXhJbnQgPSAyMTQ3NDgzNjQ3LCAvLyBha2EuIDB4N0ZGRkZGRkYgb3IgMl4zMS0xXHJcblxyXG5cdC8qKiBCb290c3RyaW5nIHBhcmFtZXRlcnMgKi9cclxuXHRiYXNlID0gMzYsXHJcblx0dE1pbiA9IDEsXHJcblx0dE1heCA9IDI2LFxyXG5cdHNrZXcgPSAzOCxcclxuXHRkYW1wID0gNzAwLFxyXG5cdGluaXRpYWxCaWFzID0gNzIsXHJcblx0aW5pdGlhbE4gPSAxMjgsIC8vIDB4ODBcclxuXHRkZWxpbWl0ZXIgPSAnLScsIC8vICdcXHgyRCdcclxuXHJcblx0LyoqIFJlZ3VsYXIgZXhwcmVzc2lvbnMgKi9cclxuXHRyZWdleFB1bnljb2RlID0gL154bi0tLyxcclxuXHRyZWdleE5vbkFTQ0lJID0gL1teXFx4MjAtXFx4N0VdLywgLy8gdW5wcmludGFibGUgQVNDSUkgY2hhcnMgKyBub24tQVNDSUkgY2hhcnNcclxuXHRyZWdleFNlcGFyYXRvcnMgPSAvW1xceDJFXFx1MzAwMlxcdUZGMEVcXHVGRjYxXS9nLCAvLyBSRkMgMzQ5MCBzZXBhcmF0b3JzXHJcblxyXG5cdC8qKiBFcnJvciBtZXNzYWdlcyAqL1xyXG5cdGVycm9ycyA9IHtcclxuXHRcdCdvdmVyZmxvdyc6ICdPdmVyZmxvdzogaW5wdXQgbmVlZHMgd2lkZXIgaW50ZWdlcnMgdG8gcHJvY2VzcycsXHJcblx0XHQnbm90LWJhc2ljJzogJ0lsbGVnYWwgaW5wdXQgPj0gMHg4MCAobm90IGEgYmFzaWMgY29kZSBwb2ludCknLFxyXG5cdFx0J2ludmFsaWQtaW5wdXQnOiAnSW52YWxpZCBpbnB1dCdcclxuXHR9LFxyXG5cclxuXHQvKiogQ29udmVuaWVuY2Ugc2hvcnRjdXRzICovXHJcblx0YmFzZU1pbnVzVE1pbiA9IGJhc2UgLSB0TWluLFxyXG5cdGZsb29yID0gTWF0aC5mbG9vcixcclxuXHRzdHJpbmdGcm9tQ2hhckNvZGUgPSBTdHJpbmcuZnJvbUNoYXJDb2RlLFxyXG5cclxuXHQvKiogVGVtcG9yYXJ5IHZhcmlhYmxlICovXHJcblx0a2V5O1xyXG5cclxuXHQvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cclxuXHJcblx0LyoqXHJcblx0ICogQSBnZW5lcmljIGVycm9yIHV0aWxpdHkgZnVuY3Rpb24uXHJcblx0ICogQHByaXZhdGVcclxuXHQgKiBAcGFyYW0ge1N0cmluZ30gdHlwZSBUaGUgZXJyb3IgdHlwZS5cclxuXHQgKiBAcmV0dXJucyB7RXJyb3J9IFRocm93cyBhIGBSYW5nZUVycm9yYCB3aXRoIHRoZSBhcHBsaWNhYmxlIGVycm9yIG1lc3NhZ2UuXHJcblx0ICovXHJcblx0ZnVuY3Rpb24gZXJyb3IodHlwZSkge1xyXG5cdFx0dGhyb3cgbmV3IFJhbmdlRXJyb3IoZXJyb3JzW3R5cGVdKTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEEgZ2VuZXJpYyBgQXJyYXkjbWFwYCB1dGlsaXR5IGZ1bmN0aW9uLlxyXG5cdCAqIEBwcml2YXRlXHJcblx0ICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cclxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gdGhhdCBnZXRzIGNhbGxlZCBmb3IgZXZlcnkgYXJyYXlcclxuXHQgKiBpdGVtLlxyXG5cdCAqIEByZXR1cm5zIHtBcnJheX0gQSBuZXcgYXJyYXkgb2YgdmFsdWVzIHJldHVybmVkIGJ5IHRoZSBjYWxsYmFjayBmdW5jdGlvbi5cclxuXHQgKi9cclxuXHRmdW5jdGlvbiBtYXAoYXJyYXksIGZuKSB7XHJcblx0XHR2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xyXG5cdFx0dmFyIHJlc3VsdCA9IFtdO1xyXG5cdFx0d2hpbGUgKGxlbmd0aC0tKSB7XHJcblx0XHRcdHJlc3VsdFtsZW5ndGhdID0gZm4oYXJyYXlbbGVuZ3RoXSk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gcmVzdWx0O1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogQSBzaW1wbGUgYEFycmF5I21hcGAtbGlrZSB3cmFwcGVyIHRvIHdvcmsgd2l0aCBkb21haW4gbmFtZSBzdHJpbmdzIG9yIGVtYWlsXHJcblx0ICogYWRkcmVzc2VzLlxyXG5cdCAqIEBwcml2YXRlXHJcblx0ICogQHBhcmFtIHtTdHJpbmd9IGRvbWFpbiBUaGUgZG9tYWluIG5hbWUgb3IgZW1haWwgYWRkcmVzcy5cclxuXHQgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gdGhhdCBnZXRzIGNhbGxlZCBmb3IgZXZlcnlcclxuXHQgKiBjaGFyYWN0ZXIuXHJcblx0ICogQHJldHVybnMge0FycmF5fSBBIG5ldyBzdHJpbmcgb2YgY2hhcmFjdGVycyByZXR1cm5lZCBieSB0aGUgY2FsbGJhY2tcclxuXHQgKiBmdW5jdGlvbi5cclxuXHQgKi9cclxuXHRmdW5jdGlvbiBtYXBEb21haW4oc3RyaW5nLCBmbikge1xyXG5cdFx0dmFyIHBhcnRzID0gc3RyaW5nLnNwbGl0KCdAJyk7XHJcblx0XHR2YXIgcmVzdWx0ID0gJyc7XHJcblx0XHRpZiAocGFydHMubGVuZ3RoID4gMSkge1xyXG5cdFx0XHQvLyBJbiBlbWFpbCBhZGRyZXNzZXMsIG9ubHkgdGhlIGRvbWFpbiBuYW1lIHNob3VsZCBiZSBwdW55Y29kZWQuIExlYXZlXHJcblx0XHRcdC8vIHRoZSBsb2NhbCBwYXJ0IChpLmUuIGV2ZXJ5dGhpbmcgdXAgdG8gYEBgKSBpbnRhY3QuXHJcblx0XHRcdHJlc3VsdCA9IHBhcnRzWzBdICsgJ0AnO1xyXG5cdFx0XHRzdHJpbmcgPSBwYXJ0c1sxXTtcclxuXHRcdH1cclxuXHRcdC8vIEF2b2lkIGBzcGxpdChyZWdleClgIGZvciBJRTggY29tcGF0aWJpbGl0eS4gU2VlICMxNy5cclxuXHRcdHN0cmluZyA9IHN0cmluZy5yZXBsYWNlKHJlZ2V4U2VwYXJhdG9ycywgJ1xceDJFJyk7XHJcblx0XHR2YXIgbGFiZWxzID0gc3RyaW5nLnNwbGl0KCcuJyk7XHJcblx0XHR2YXIgZW5jb2RlZCA9IG1hcChsYWJlbHMsIGZuKS5qb2luKCcuJyk7XHJcblx0XHRyZXR1cm4gcmVzdWx0ICsgZW5jb2RlZDtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIENyZWF0ZXMgYW4gYXJyYXkgY29udGFpbmluZyB0aGUgbnVtZXJpYyBjb2RlIHBvaW50cyBvZiBlYWNoIFVuaWNvZGVcclxuXHQgKiBjaGFyYWN0ZXIgaW4gdGhlIHN0cmluZy4gV2hpbGUgSmF2YVNjcmlwdCB1c2VzIFVDUy0yIGludGVybmFsbHksXHJcblx0ICogdGhpcyBmdW5jdGlvbiB3aWxsIGNvbnZlcnQgYSBwYWlyIG9mIHN1cnJvZ2F0ZSBoYWx2ZXMgKGVhY2ggb2Ygd2hpY2hcclxuXHQgKiBVQ1MtMiBleHBvc2VzIGFzIHNlcGFyYXRlIGNoYXJhY3RlcnMpIGludG8gYSBzaW5nbGUgY29kZSBwb2ludCxcclxuXHQgKiBtYXRjaGluZyBVVEYtMTYuXHJcblx0ICogQHNlZSBgcHVueWNvZGUudWNzMi5lbmNvZGVgXHJcblx0ICogQHNlZSA8aHR0cHM6Ly9tYXRoaWFzYnluZW5zLmJlL25vdGVzL2phdmFzY3JpcHQtZW5jb2Rpbmc+XHJcblx0ICogQG1lbWJlck9mIHB1bnljb2RlLnVjczJcclxuXHQgKiBAbmFtZSBkZWNvZGVcclxuXHQgKiBAcGFyYW0ge1N0cmluZ30gc3RyaW5nIFRoZSBVbmljb2RlIGlucHV0IHN0cmluZyAoVUNTLTIpLlxyXG5cdCAqIEByZXR1cm5zIHtBcnJheX0gVGhlIG5ldyBhcnJheSBvZiBjb2RlIHBvaW50cy5cclxuXHQgKi9cclxuXHRmdW5jdGlvbiB1Y3MyZGVjb2RlKHN0cmluZykge1xyXG5cdFx0dmFyIG91dHB1dCA9IFtdLFxyXG5cdFx0ICAgIGNvdW50ZXIgPSAwLFxyXG5cdFx0ICAgIGxlbmd0aCA9IHN0cmluZy5sZW5ndGgsXHJcblx0XHQgICAgdmFsdWUsXHJcblx0XHQgICAgZXh0cmE7XHJcblx0XHR3aGlsZSAoY291bnRlciA8IGxlbmd0aCkge1xyXG5cdFx0XHR2YWx1ZSA9IHN0cmluZy5jaGFyQ29kZUF0KGNvdW50ZXIrKyk7XHJcblx0XHRcdGlmICh2YWx1ZSA+PSAweEQ4MDAgJiYgdmFsdWUgPD0gMHhEQkZGICYmIGNvdW50ZXIgPCBsZW5ndGgpIHtcclxuXHRcdFx0XHQvLyBoaWdoIHN1cnJvZ2F0ZSwgYW5kIHRoZXJlIGlzIGEgbmV4dCBjaGFyYWN0ZXJcclxuXHRcdFx0XHRleHRyYSA9IHN0cmluZy5jaGFyQ29kZUF0KGNvdW50ZXIrKyk7XHJcblx0XHRcdFx0aWYgKChleHRyYSAmIDB4RkMwMCkgPT0gMHhEQzAwKSB7IC8vIGxvdyBzdXJyb2dhdGVcclxuXHRcdFx0XHRcdG91dHB1dC5wdXNoKCgodmFsdWUgJiAweDNGRikgPDwgMTApICsgKGV4dHJhICYgMHgzRkYpICsgMHgxMDAwMCk7XHJcblx0XHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRcdC8vIHVubWF0Y2hlZCBzdXJyb2dhdGU7IG9ubHkgYXBwZW5kIHRoaXMgY29kZSB1bml0LCBpbiBjYXNlIHRoZSBuZXh0XHJcblx0XHRcdFx0XHQvLyBjb2RlIHVuaXQgaXMgdGhlIGhpZ2ggc3Vycm9nYXRlIG9mIGEgc3Vycm9nYXRlIHBhaXJcclxuXHRcdFx0XHRcdG91dHB1dC5wdXNoKHZhbHVlKTtcclxuXHRcdFx0XHRcdGNvdW50ZXItLTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0b3V0cHV0LnB1c2godmFsdWUpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gb3V0cHV0O1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogQ3JlYXRlcyBhIHN0cmluZyBiYXNlZCBvbiBhbiBhcnJheSBvZiBudW1lcmljIGNvZGUgcG9pbnRzLlxyXG5cdCAqIEBzZWUgYHB1bnljb2RlLnVjczIuZGVjb2RlYFxyXG5cdCAqIEBtZW1iZXJPZiBwdW55Y29kZS51Y3MyXHJcblx0ICogQG5hbWUgZW5jb2RlXHJcblx0ICogQHBhcmFtIHtBcnJheX0gY29kZVBvaW50cyBUaGUgYXJyYXkgb2YgbnVtZXJpYyBjb2RlIHBvaW50cy5cclxuXHQgKiBAcmV0dXJucyB7U3RyaW5nfSBUaGUgbmV3IFVuaWNvZGUgc3RyaW5nIChVQ1MtMikuXHJcblx0ICovXHJcblx0ZnVuY3Rpb24gdWNzMmVuY29kZShhcnJheSkge1xyXG5cdFx0cmV0dXJuIG1hcChhcnJheSwgZnVuY3Rpb24odmFsdWUpIHtcclxuXHRcdFx0dmFyIG91dHB1dCA9ICcnO1xyXG5cdFx0XHRpZiAodmFsdWUgPiAweEZGRkYpIHtcclxuXHRcdFx0XHR2YWx1ZSAtPSAweDEwMDAwO1xyXG5cdFx0XHRcdG91dHB1dCArPSBzdHJpbmdGcm9tQ2hhckNvZGUodmFsdWUgPj4+IDEwICYgMHgzRkYgfCAweEQ4MDApO1xyXG5cdFx0XHRcdHZhbHVlID0gMHhEQzAwIHwgdmFsdWUgJiAweDNGRjtcclxuXHRcdFx0fVxyXG5cdFx0XHRvdXRwdXQgKz0gc3RyaW5nRnJvbUNoYXJDb2RlKHZhbHVlKTtcclxuXHRcdFx0cmV0dXJuIG91dHB1dDtcclxuXHRcdH0pLmpvaW4oJycpO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogQ29udmVydHMgYSBiYXNpYyBjb2RlIHBvaW50IGludG8gYSBkaWdpdC9pbnRlZ2VyLlxyXG5cdCAqIEBzZWUgYGRpZ2l0VG9CYXNpYygpYFxyXG5cdCAqIEBwcml2YXRlXHJcblx0ICogQHBhcmFtIHtOdW1iZXJ9IGNvZGVQb2ludCBUaGUgYmFzaWMgbnVtZXJpYyBjb2RlIHBvaW50IHZhbHVlLlxyXG5cdCAqIEByZXR1cm5zIHtOdW1iZXJ9IFRoZSBudW1lcmljIHZhbHVlIG9mIGEgYmFzaWMgY29kZSBwb2ludCAoZm9yIHVzZSBpblxyXG5cdCAqIHJlcHJlc2VudGluZyBpbnRlZ2VycykgaW4gdGhlIHJhbmdlIGAwYCB0byBgYmFzZSAtIDFgLCBvciBgYmFzZWAgaWZcclxuXHQgKiB0aGUgY29kZSBwb2ludCBkb2VzIG5vdCByZXByZXNlbnQgYSB2YWx1ZS5cclxuXHQgKi9cclxuXHRmdW5jdGlvbiBiYXNpY1RvRGlnaXQoY29kZVBvaW50KSB7XHJcblx0XHRpZiAoY29kZVBvaW50IC0gNDggPCAxMCkge1xyXG5cdFx0XHRyZXR1cm4gY29kZVBvaW50IC0gMjI7XHJcblx0XHR9XHJcblx0XHRpZiAoY29kZVBvaW50IC0gNjUgPCAyNikge1xyXG5cdFx0XHRyZXR1cm4gY29kZVBvaW50IC0gNjU7XHJcblx0XHR9XHJcblx0XHRpZiAoY29kZVBvaW50IC0gOTcgPCAyNikge1xyXG5cdFx0XHRyZXR1cm4gY29kZVBvaW50IC0gOTc7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gYmFzZTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIENvbnZlcnRzIGEgZGlnaXQvaW50ZWdlciBpbnRvIGEgYmFzaWMgY29kZSBwb2ludC5cclxuXHQgKiBAc2VlIGBiYXNpY1RvRGlnaXQoKWBcclxuXHQgKiBAcHJpdmF0ZVxyXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSBkaWdpdCBUaGUgbnVtZXJpYyB2YWx1ZSBvZiBhIGJhc2ljIGNvZGUgcG9pbnQuXHJcblx0ICogQHJldHVybnMge051bWJlcn0gVGhlIGJhc2ljIGNvZGUgcG9pbnQgd2hvc2UgdmFsdWUgKHdoZW4gdXNlZCBmb3JcclxuXHQgKiByZXByZXNlbnRpbmcgaW50ZWdlcnMpIGlzIGBkaWdpdGAsIHdoaWNoIG5lZWRzIHRvIGJlIGluIHRoZSByYW5nZVxyXG5cdCAqIGAwYCB0byBgYmFzZSAtIDFgLiBJZiBgZmxhZ2AgaXMgbm9uLXplcm8sIHRoZSB1cHBlcmNhc2UgZm9ybSBpc1xyXG5cdCAqIHVzZWQ7IGVsc2UsIHRoZSBsb3dlcmNhc2UgZm9ybSBpcyB1c2VkLiBUaGUgYmVoYXZpb3IgaXMgdW5kZWZpbmVkXHJcblx0ICogaWYgYGZsYWdgIGlzIG5vbi16ZXJvIGFuZCBgZGlnaXRgIGhhcyBubyB1cHBlcmNhc2UgZm9ybS5cclxuXHQgKi9cclxuXHRmdW5jdGlvbiBkaWdpdFRvQmFzaWMoZGlnaXQsIGZsYWcpIHtcclxuXHRcdC8vICAwLi4yNSBtYXAgdG8gQVNDSUkgYS4ueiBvciBBLi5aXHJcblx0XHQvLyAyNi4uMzUgbWFwIHRvIEFTQ0lJIDAuLjlcclxuXHRcdHJldHVybiBkaWdpdCArIDIyICsgNzUgKiAoZGlnaXQgPCAyNikgLSAoKGZsYWcgIT0gMCkgPDwgNSk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBCaWFzIGFkYXB0YXRpb24gZnVuY3Rpb24gYXMgcGVyIHNlY3Rpb24gMy40IG9mIFJGQyAzNDkyLlxyXG5cdCAqIGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmMzNDkyI3NlY3Rpb24tMy40XHJcblx0ICogQHByaXZhdGVcclxuXHQgKi9cclxuXHRmdW5jdGlvbiBhZGFwdChkZWx0YSwgbnVtUG9pbnRzLCBmaXJzdFRpbWUpIHtcclxuXHRcdHZhciBrID0gMDtcclxuXHRcdGRlbHRhID0gZmlyc3RUaW1lID8gZmxvb3IoZGVsdGEgLyBkYW1wKSA6IGRlbHRhID4+IDE7XHJcblx0XHRkZWx0YSArPSBmbG9vcihkZWx0YSAvIG51bVBvaW50cyk7XHJcblx0XHRmb3IgKC8qIG5vIGluaXRpYWxpemF0aW9uICovOyBkZWx0YSA+IGJhc2VNaW51c1RNaW4gKiB0TWF4ID4+IDE7IGsgKz0gYmFzZSkge1xyXG5cdFx0XHRkZWx0YSA9IGZsb29yKGRlbHRhIC8gYmFzZU1pbnVzVE1pbik7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gZmxvb3IoayArIChiYXNlTWludXNUTWluICsgMSkgKiBkZWx0YSAvIChkZWx0YSArIHNrZXcpKTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIENvbnZlcnRzIGEgUHVueWNvZGUgc3RyaW5nIG9mIEFTQ0lJLW9ubHkgc3ltYm9scyB0byBhIHN0cmluZyBvZiBVbmljb2RlXHJcblx0ICogc3ltYm9scy5cclxuXHQgKiBAbWVtYmVyT2YgcHVueWNvZGVcclxuXHQgKiBAcGFyYW0ge1N0cmluZ30gaW5wdXQgVGhlIFB1bnljb2RlIHN0cmluZyBvZiBBU0NJSS1vbmx5IHN5bWJvbHMuXHJcblx0ICogQHJldHVybnMge1N0cmluZ30gVGhlIHJlc3VsdGluZyBzdHJpbmcgb2YgVW5pY29kZSBzeW1ib2xzLlxyXG5cdCAqL1xyXG5cdGZ1bmN0aW9uIGRlY29kZShpbnB1dCkge1xyXG5cdFx0Ly8gRG9uJ3QgdXNlIFVDUy0yXHJcblx0XHR2YXIgb3V0cHV0ID0gW10sXHJcblx0XHQgICAgaW5wdXRMZW5ndGggPSBpbnB1dC5sZW5ndGgsXHJcblx0XHQgICAgb3V0LFxyXG5cdFx0ICAgIGkgPSAwLFxyXG5cdFx0ICAgIG4gPSBpbml0aWFsTixcclxuXHRcdCAgICBiaWFzID0gaW5pdGlhbEJpYXMsXHJcblx0XHQgICAgYmFzaWMsXHJcblx0XHQgICAgaixcclxuXHRcdCAgICBpbmRleCxcclxuXHRcdCAgICBvbGRpLFxyXG5cdFx0ICAgIHcsXHJcblx0XHQgICAgayxcclxuXHRcdCAgICBkaWdpdCxcclxuXHRcdCAgICB0LFxyXG5cdFx0ICAgIC8qKiBDYWNoZWQgY2FsY3VsYXRpb24gcmVzdWx0cyAqL1xyXG5cdFx0ICAgIGJhc2VNaW51c1Q7XHJcblxyXG5cdFx0Ly8gSGFuZGxlIHRoZSBiYXNpYyBjb2RlIHBvaW50czogbGV0IGBiYXNpY2AgYmUgdGhlIG51bWJlciBvZiBpbnB1dCBjb2RlXHJcblx0XHQvLyBwb2ludHMgYmVmb3JlIHRoZSBsYXN0IGRlbGltaXRlciwgb3IgYDBgIGlmIHRoZXJlIGlzIG5vbmUsIHRoZW4gY29weVxyXG5cdFx0Ly8gdGhlIGZpcnN0IGJhc2ljIGNvZGUgcG9pbnRzIHRvIHRoZSBvdXRwdXQuXHJcblxyXG5cdFx0YmFzaWMgPSBpbnB1dC5sYXN0SW5kZXhPZihkZWxpbWl0ZXIpO1xyXG5cdFx0aWYgKGJhc2ljIDwgMCkge1xyXG5cdFx0XHRiYXNpYyA9IDA7XHJcblx0XHR9XHJcblxyXG5cdFx0Zm9yIChqID0gMDsgaiA8IGJhc2ljOyArK2opIHtcclxuXHRcdFx0Ly8gaWYgaXQncyBub3QgYSBiYXNpYyBjb2RlIHBvaW50XHJcblx0XHRcdGlmIChpbnB1dC5jaGFyQ29kZUF0KGopID49IDB4ODApIHtcclxuXHRcdFx0XHRlcnJvcignbm90LWJhc2ljJyk7XHJcblx0XHRcdH1cclxuXHRcdFx0b3V0cHV0LnB1c2goaW5wdXQuY2hhckNvZGVBdChqKSk7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gTWFpbiBkZWNvZGluZyBsb29wOiBzdGFydCBqdXN0IGFmdGVyIHRoZSBsYXN0IGRlbGltaXRlciBpZiBhbnkgYmFzaWMgY29kZVxyXG5cdFx0Ly8gcG9pbnRzIHdlcmUgY29waWVkOyBzdGFydCBhdCB0aGUgYmVnaW5uaW5nIG90aGVyd2lzZS5cclxuXHJcblx0XHRmb3IgKGluZGV4ID0gYmFzaWMgPiAwID8gYmFzaWMgKyAxIDogMDsgaW5kZXggPCBpbnB1dExlbmd0aDsgLyogbm8gZmluYWwgZXhwcmVzc2lvbiAqLykge1xyXG5cclxuXHRcdFx0Ly8gYGluZGV4YCBpcyB0aGUgaW5kZXggb2YgdGhlIG5leHQgY2hhcmFjdGVyIHRvIGJlIGNvbnN1bWVkLlxyXG5cdFx0XHQvLyBEZWNvZGUgYSBnZW5lcmFsaXplZCB2YXJpYWJsZS1sZW5ndGggaW50ZWdlciBpbnRvIGBkZWx0YWAsXHJcblx0XHRcdC8vIHdoaWNoIGdldHMgYWRkZWQgdG8gYGlgLiBUaGUgb3ZlcmZsb3cgY2hlY2tpbmcgaXMgZWFzaWVyXHJcblx0XHRcdC8vIGlmIHdlIGluY3JlYXNlIGBpYCBhcyB3ZSBnbywgdGhlbiBzdWJ0cmFjdCBvZmYgaXRzIHN0YXJ0aW5nXHJcblx0XHRcdC8vIHZhbHVlIGF0IHRoZSBlbmQgdG8gb2J0YWluIGBkZWx0YWAuXHJcblx0XHRcdGZvciAob2xkaSA9IGksIHcgPSAxLCBrID0gYmFzZTsgLyogbm8gY29uZGl0aW9uICovOyBrICs9IGJhc2UpIHtcclxuXHJcblx0XHRcdFx0aWYgKGluZGV4ID49IGlucHV0TGVuZ3RoKSB7XHJcblx0XHRcdFx0XHRlcnJvcignaW52YWxpZC1pbnB1dCcpO1xyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0ZGlnaXQgPSBiYXNpY1RvRGlnaXQoaW5wdXQuY2hhckNvZGVBdChpbmRleCsrKSk7XHJcblxyXG5cdFx0XHRcdGlmIChkaWdpdCA+PSBiYXNlIHx8IGRpZ2l0ID4gZmxvb3IoKG1heEludCAtIGkpIC8gdykpIHtcclxuXHRcdFx0XHRcdGVycm9yKCdvdmVyZmxvdycpO1xyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0aSArPSBkaWdpdCAqIHc7XHJcblx0XHRcdFx0dCA9IGsgPD0gYmlhcyA/IHRNaW4gOiAoayA+PSBiaWFzICsgdE1heCA/IHRNYXggOiBrIC0gYmlhcyk7XHJcblxyXG5cdFx0XHRcdGlmIChkaWdpdCA8IHQpIHtcclxuXHRcdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0YmFzZU1pbnVzVCA9IGJhc2UgLSB0O1xyXG5cdFx0XHRcdGlmICh3ID4gZmxvb3IobWF4SW50IC8gYmFzZU1pbnVzVCkpIHtcclxuXHRcdFx0XHRcdGVycm9yKCdvdmVyZmxvdycpO1xyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0dyAqPSBiYXNlTWludXNUO1xyXG5cclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0b3V0ID0gb3V0cHV0Lmxlbmd0aCArIDE7XHJcblx0XHRcdGJpYXMgPSBhZGFwdChpIC0gb2xkaSwgb3V0LCBvbGRpID09IDApO1xyXG5cclxuXHRcdFx0Ly8gYGlgIHdhcyBzdXBwb3NlZCB0byB3cmFwIGFyb3VuZCBmcm9tIGBvdXRgIHRvIGAwYCxcclxuXHRcdFx0Ly8gaW5jcmVtZW50aW5nIGBuYCBlYWNoIHRpbWUsIHNvIHdlJ2xsIGZpeCB0aGF0IG5vdzpcclxuXHRcdFx0aWYgKGZsb29yKGkgLyBvdXQpID4gbWF4SW50IC0gbikge1xyXG5cdFx0XHRcdGVycm9yKCdvdmVyZmxvdycpO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHRuICs9IGZsb29yKGkgLyBvdXQpO1xyXG5cdFx0XHRpICU9IG91dDtcclxuXHJcblx0XHRcdC8vIEluc2VydCBgbmAgYXQgcG9zaXRpb24gYGlgIG9mIHRoZSBvdXRwdXRcclxuXHRcdFx0b3V0cHV0LnNwbGljZShpKyssIDAsIG4pO1xyXG5cclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gdWNzMmVuY29kZShvdXRwdXQpO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogQ29udmVydHMgYSBzdHJpbmcgb2YgVW5pY29kZSBzeW1ib2xzIChlLmcuIGEgZG9tYWluIG5hbWUgbGFiZWwpIHRvIGFcclxuXHQgKiBQdW55Y29kZSBzdHJpbmcgb2YgQVNDSUktb25seSBzeW1ib2xzLlxyXG5cdCAqIEBtZW1iZXJPZiBwdW55Y29kZVxyXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSBpbnB1dCBUaGUgc3RyaW5nIG9mIFVuaWNvZGUgc3ltYm9scy5cclxuXHQgKiBAcmV0dXJucyB7U3RyaW5nfSBUaGUgcmVzdWx0aW5nIFB1bnljb2RlIHN0cmluZyBvZiBBU0NJSS1vbmx5IHN5bWJvbHMuXHJcblx0ICovXHJcblx0ZnVuY3Rpb24gZW5jb2RlKGlucHV0KSB7XHJcblx0XHR2YXIgbixcclxuXHRcdCAgICBkZWx0YSxcclxuXHRcdCAgICBoYW5kbGVkQ1BDb3VudCxcclxuXHRcdCAgICBiYXNpY0xlbmd0aCxcclxuXHRcdCAgICBiaWFzLFxyXG5cdFx0ICAgIGosXHJcblx0XHQgICAgbSxcclxuXHRcdCAgICBxLFxyXG5cdFx0ICAgIGssXHJcblx0XHQgICAgdCxcclxuXHRcdCAgICBjdXJyZW50VmFsdWUsXHJcblx0XHQgICAgb3V0cHV0ID0gW10sXHJcblx0XHQgICAgLyoqIGBpbnB1dExlbmd0aGAgd2lsbCBob2xkIHRoZSBudW1iZXIgb2YgY29kZSBwb2ludHMgaW4gYGlucHV0YC4gKi9cclxuXHRcdCAgICBpbnB1dExlbmd0aCxcclxuXHRcdCAgICAvKiogQ2FjaGVkIGNhbGN1bGF0aW9uIHJlc3VsdHMgKi9cclxuXHRcdCAgICBoYW5kbGVkQ1BDb3VudFBsdXNPbmUsXHJcblx0XHQgICAgYmFzZU1pbnVzVCxcclxuXHRcdCAgICBxTWludXNUO1xyXG5cclxuXHRcdC8vIENvbnZlcnQgdGhlIGlucHV0IGluIFVDUy0yIHRvIFVuaWNvZGVcclxuXHRcdGlucHV0ID0gdWNzMmRlY29kZShpbnB1dCk7XHJcblxyXG5cdFx0Ly8gQ2FjaGUgdGhlIGxlbmd0aFxyXG5cdFx0aW5wdXRMZW5ndGggPSBpbnB1dC5sZW5ndGg7XHJcblxyXG5cdFx0Ly8gSW5pdGlhbGl6ZSB0aGUgc3RhdGVcclxuXHRcdG4gPSBpbml0aWFsTjtcclxuXHRcdGRlbHRhID0gMDtcclxuXHRcdGJpYXMgPSBpbml0aWFsQmlhcztcclxuXHJcblx0XHQvLyBIYW5kbGUgdGhlIGJhc2ljIGNvZGUgcG9pbnRzXHJcblx0XHRmb3IgKGogPSAwOyBqIDwgaW5wdXRMZW5ndGg7ICsraikge1xyXG5cdFx0XHRjdXJyZW50VmFsdWUgPSBpbnB1dFtqXTtcclxuXHRcdFx0aWYgKGN1cnJlbnRWYWx1ZSA8IDB4ODApIHtcclxuXHRcdFx0XHRvdXRwdXQucHVzaChzdHJpbmdGcm9tQ2hhckNvZGUoY3VycmVudFZhbHVlKSk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRoYW5kbGVkQ1BDb3VudCA9IGJhc2ljTGVuZ3RoID0gb3V0cHV0Lmxlbmd0aDtcclxuXHJcblx0XHQvLyBgaGFuZGxlZENQQ291bnRgIGlzIHRoZSBudW1iZXIgb2YgY29kZSBwb2ludHMgdGhhdCBoYXZlIGJlZW4gaGFuZGxlZDtcclxuXHRcdC8vIGBiYXNpY0xlbmd0aGAgaXMgdGhlIG51bWJlciBvZiBiYXNpYyBjb2RlIHBvaW50cy5cclxuXHJcblx0XHQvLyBGaW5pc2ggdGhlIGJhc2ljIHN0cmluZyAtIGlmIGl0IGlzIG5vdCBlbXB0eSAtIHdpdGggYSBkZWxpbWl0ZXJcclxuXHRcdGlmIChiYXNpY0xlbmd0aCkge1xyXG5cdFx0XHRvdXRwdXQucHVzaChkZWxpbWl0ZXIpO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIE1haW4gZW5jb2RpbmcgbG9vcDpcclxuXHRcdHdoaWxlIChoYW5kbGVkQ1BDb3VudCA8IGlucHV0TGVuZ3RoKSB7XHJcblxyXG5cdFx0XHQvLyBBbGwgbm9uLWJhc2ljIGNvZGUgcG9pbnRzIDwgbiBoYXZlIGJlZW4gaGFuZGxlZCBhbHJlYWR5LiBGaW5kIHRoZSBuZXh0XHJcblx0XHRcdC8vIGxhcmdlciBvbmU6XHJcblx0XHRcdGZvciAobSA9IG1heEludCwgaiA9IDA7IGogPCBpbnB1dExlbmd0aDsgKytqKSB7XHJcblx0XHRcdFx0Y3VycmVudFZhbHVlID0gaW5wdXRbal07XHJcblx0XHRcdFx0aWYgKGN1cnJlbnRWYWx1ZSA+PSBuICYmIGN1cnJlbnRWYWx1ZSA8IG0pIHtcclxuXHRcdFx0XHRcdG0gPSBjdXJyZW50VmFsdWU7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHQvLyBJbmNyZWFzZSBgZGVsdGFgIGVub3VnaCB0byBhZHZhbmNlIHRoZSBkZWNvZGVyJ3MgPG4saT4gc3RhdGUgdG8gPG0sMD4sXHJcblx0XHRcdC8vIGJ1dCBndWFyZCBhZ2FpbnN0IG92ZXJmbG93XHJcblx0XHRcdGhhbmRsZWRDUENvdW50UGx1c09uZSA9IGhhbmRsZWRDUENvdW50ICsgMTtcclxuXHRcdFx0aWYgKG0gLSBuID4gZmxvb3IoKG1heEludCAtIGRlbHRhKSAvIGhhbmRsZWRDUENvdW50UGx1c09uZSkpIHtcclxuXHRcdFx0XHRlcnJvcignb3ZlcmZsb3cnKTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0ZGVsdGEgKz0gKG0gLSBuKSAqIGhhbmRsZWRDUENvdW50UGx1c09uZTtcclxuXHRcdFx0biA9IG07XHJcblxyXG5cdFx0XHRmb3IgKGogPSAwOyBqIDwgaW5wdXRMZW5ndGg7ICsraikge1xyXG5cdFx0XHRcdGN1cnJlbnRWYWx1ZSA9IGlucHV0W2pdO1xyXG5cclxuXHRcdFx0XHRpZiAoY3VycmVudFZhbHVlIDwgbiAmJiArK2RlbHRhID4gbWF4SW50KSB7XHJcblx0XHRcdFx0XHRlcnJvcignb3ZlcmZsb3cnKTtcclxuXHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdGlmIChjdXJyZW50VmFsdWUgPT0gbikge1xyXG5cdFx0XHRcdFx0Ly8gUmVwcmVzZW50IGRlbHRhIGFzIGEgZ2VuZXJhbGl6ZWQgdmFyaWFibGUtbGVuZ3RoIGludGVnZXJcclxuXHRcdFx0XHRcdGZvciAocSA9IGRlbHRhLCBrID0gYmFzZTsgLyogbm8gY29uZGl0aW9uICovOyBrICs9IGJhc2UpIHtcclxuXHRcdFx0XHRcdFx0dCA9IGsgPD0gYmlhcyA/IHRNaW4gOiAoayA+PSBiaWFzICsgdE1heCA/IHRNYXggOiBrIC0gYmlhcyk7XHJcblx0XHRcdFx0XHRcdGlmIChxIDwgdCkge1xyXG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdHFNaW51c1QgPSBxIC0gdDtcclxuXHRcdFx0XHRcdFx0YmFzZU1pbnVzVCA9IGJhc2UgLSB0O1xyXG5cdFx0XHRcdFx0XHRvdXRwdXQucHVzaChcclxuXHRcdFx0XHRcdFx0XHRzdHJpbmdGcm9tQ2hhckNvZGUoZGlnaXRUb0Jhc2ljKHQgKyBxTWludXNUICUgYmFzZU1pbnVzVCwgMCkpXHJcblx0XHRcdFx0XHRcdCk7XHJcblx0XHRcdFx0XHRcdHEgPSBmbG9vcihxTWludXNUIC8gYmFzZU1pbnVzVCk7XHJcblx0XHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdFx0b3V0cHV0LnB1c2goc3RyaW5nRnJvbUNoYXJDb2RlKGRpZ2l0VG9CYXNpYyhxLCAwKSkpO1xyXG5cdFx0XHRcdFx0YmlhcyA9IGFkYXB0KGRlbHRhLCBoYW5kbGVkQ1BDb3VudFBsdXNPbmUsIGhhbmRsZWRDUENvdW50ID09IGJhc2ljTGVuZ3RoKTtcclxuXHRcdFx0XHRcdGRlbHRhID0gMDtcclxuXHRcdFx0XHRcdCsraGFuZGxlZENQQ291bnQ7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHQrK2RlbHRhO1xyXG5cdFx0XHQrK247XHJcblxyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIG91dHB1dC5qb2luKCcnKTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIENvbnZlcnRzIGEgUHVueWNvZGUgc3RyaW5nIHJlcHJlc2VudGluZyBhIGRvbWFpbiBuYW1lIG9yIGFuIGVtYWlsIGFkZHJlc3NcclxuXHQgKiB0byBVbmljb2RlLiBPbmx5IHRoZSBQdW55Y29kZWQgcGFydHMgb2YgdGhlIGlucHV0IHdpbGwgYmUgY29udmVydGVkLCBpLmUuXHJcblx0ICogaXQgZG9lc24ndCBtYXR0ZXIgaWYgeW91IGNhbGwgaXQgb24gYSBzdHJpbmcgdGhhdCBoYXMgYWxyZWFkeSBiZWVuXHJcblx0ICogY29udmVydGVkIHRvIFVuaWNvZGUuXHJcblx0ICogQG1lbWJlck9mIHB1bnljb2RlXHJcblx0ICogQHBhcmFtIHtTdHJpbmd9IGlucHV0IFRoZSBQdW55Y29kZWQgZG9tYWluIG5hbWUgb3IgZW1haWwgYWRkcmVzcyB0b1xyXG5cdCAqIGNvbnZlcnQgdG8gVW5pY29kZS5cclxuXHQgKiBAcmV0dXJucyB7U3RyaW5nfSBUaGUgVW5pY29kZSByZXByZXNlbnRhdGlvbiBvZiB0aGUgZ2l2ZW4gUHVueWNvZGVcclxuXHQgKiBzdHJpbmcuXHJcblx0ICovXHJcblx0ZnVuY3Rpb24gdG9Vbmljb2RlKGlucHV0KSB7XHJcblx0XHRyZXR1cm4gbWFwRG9tYWluKGlucHV0LCBmdW5jdGlvbihzdHJpbmcpIHtcclxuXHRcdFx0cmV0dXJuIHJlZ2V4UHVueWNvZGUudGVzdChzdHJpbmcpXHJcblx0XHRcdFx0PyBkZWNvZGUoc3RyaW5nLnNsaWNlKDQpLnRvTG93ZXJDYXNlKCkpXHJcblx0XHRcdFx0OiBzdHJpbmc7XHJcblx0XHR9KTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIENvbnZlcnRzIGEgVW5pY29kZSBzdHJpbmcgcmVwcmVzZW50aW5nIGEgZG9tYWluIG5hbWUgb3IgYW4gZW1haWwgYWRkcmVzcyB0b1xyXG5cdCAqIFB1bnljb2RlLiBPbmx5IHRoZSBub24tQVNDSUkgcGFydHMgb2YgdGhlIGRvbWFpbiBuYW1lIHdpbGwgYmUgY29udmVydGVkLFxyXG5cdCAqIGkuZS4gaXQgZG9lc24ndCBtYXR0ZXIgaWYgeW91IGNhbGwgaXQgd2l0aCBhIGRvbWFpbiB0aGF0J3MgYWxyZWFkeSBpblxyXG5cdCAqIEFTQ0lJLlxyXG5cdCAqIEBtZW1iZXJPZiBwdW55Y29kZVxyXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSBpbnB1dCBUaGUgZG9tYWluIG5hbWUgb3IgZW1haWwgYWRkcmVzcyB0byBjb252ZXJ0LCBhcyBhXHJcblx0ICogVW5pY29kZSBzdHJpbmcuXHJcblx0ICogQHJldHVybnMge1N0cmluZ30gVGhlIFB1bnljb2RlIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBnaXZlbiBkb21haW4gbmFtZSBvclxyXG5cdCAqIGVtYWlsIGFkZHJlc3MuXHJcblx0ICovXHJcblx0ZnVuY3Rpb24gdG9BU0NJSShpbnB1dCkge1xyXG5cdFx0cmV0dXJuIG1hcERvbWFpbihpbnB1dCwgZnVuY3Rpb24oc3RyaW5nKSB7XHJcblx0XHRcdHJldHVybiByZWdleE5vbkFTQ0lJLnRlc3Qoc3RyaW5nKVxyXG5cdFx0XHRcdD8gJ3huLS0nICsgZW5jb2RlKHN0cmluZylcclxuXHRcdFx0XHQ6IHN0cmluZztcclxuXHRcdH0pO1xyXG5cdH1cclxuXHJcblx0LyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXHJcblxyXG5cdC8qKiBEZWZpbmUgdGhlIHB1YmxpYyBBUEkgKi9cclxuXHRwdW55Y29kZSA9IHtcclxuXHRcdC8qKlxyXG5cdFx0ICogQSBzdHJpbmcgcmVwcmVzZW50aW5nIHRoZSBjdXJyZW50IFB1bnljb2RlLmpzIHZlcnNpb24gbnVtYmVyLlxyXG5cdFx0ICogQG1lbWJlck9mIHB1bnljb2RlXHJcblx0XHQgKiBAdHlwZSBTdHJpbmdcclxuXHRcdCAqL1xyXG5cdFx0dmVyc2lvbjogJzEuMy4yJyxcclxuXHRcdC8qKlxyXG5cdFx0ICogQW4gb2JqZWN0IG9mIG1ldGhvZHMgdG8gY29udmVydCBmcm9tIEphdmFTY3JpcHQncyBpbnRlcm5hbCBjaGFyYWN0ZXJcclxuXHRcdCAqIHJlcHJlc2VudGF0aW9uIChVQ1MtMikgdG8gVW5pY29kZSBjb2RlIHBvaW50cywgYW5kIGJhY2suXHJcblx0XHQgKiBAc2VlIDxodHRwczovL21hdGhpYXNieW5lbnMuYmUvbm90ZXMvamF2YXNjcmlwdC1lbmNvZGluZz5cclxuXHRcdCAqIEBtZW1iZXJPZiBwdW55Y29kZVxyXG5cdFx0ICogQHR5cGUgT2JqZWN0XHJcblx0XHQgKi9cclxuXHRcdHVjczI6IHtcclxuXHRcdFx0ZGVjb2RlOiB1Y3MyZGVjb2RlLFxyXG5cdFx0XHRlbmNvZGU6IHVjczJlbmNvZGVcclxuXHRcdH0sXHJcblx0XHRkZWNvZGU6IGRlY29kZSxcclxuXHRcdGVuY29kZTogZW5jb2RlLFxyXG5cdFx0dG9BU0NJSTogdG9BU0NJSSxcclxuXHRcdHRvVW5pY29kZTogdG9Vbmljb2RlXHJcblx0fTtcclxuXHJcblx0cmV0dXJuIHB1bnljb2RlO1xyXG59KCkpO1xyXG5cclxuaWYgKHR5cGVvZiBDT01QSUxFRCA9PT0gXCJ1bmRlZmluZWRcIiAmJiB0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiKSBtb2R1bGUuZXhwb3J0cyA9IHB1bnljb2RlOyIsIi8vLzxyZWZlcmVuY2UgcGF0aD1cImNvbW1vbmpzLmQudHNcIi8+XHJcbnJlcXVpcmUoXCIuL3NjaGVtZXMvaHR0cFwiKTtcclxucmVxdWlyZShcIi4vc2NoZW1lcy91cm5cIik7XHJcbnJlcXVpcmUoXCIuL3NjaGVtZXMvbWFpbHRvXCIpO1xyXG4iLCIvLy88cmVmZXJlbmNlIHBhdGg9XCIuLi91cmkudHNcIi8+XHJcbmlmICh0eXBlb2YgQ09NUElMRUQgPT09IFwidW5kZWZpbmVkXCIgJiYgdHlwZW9mIFVSSSA9PT0gXCJ1bmRlZmluZWRcIiAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gXCJmdW5jdGlvblwiKVxyXG4gICAgdmFyIFVSSSA9IHJlcXVpcmUoXCIuLi91cmlcIik7XHJcblVSSS5TQ0hFTUVTW1wiaHR0cFwiXSA9IFVSSS5TQ0hFTUVTW1wiaHR0cHNcIl0gPSB7XHJcbiAgICBkb21haW5Ib3N0OiB0cnVlLFxyXG4gICAgcGFyc2U6IGZ1bmN0aW9uIChjb21wb25lbnRzLCBvcHRpb25zKSB7XHJcbiAgICAgICAgLy9yZXBvcnQgbWlzc2luZyBob3N0XHJcbiAgICAgICAgaWYgKCFjb21wb25lbnRzLmhvc3QpIHtcclxuICAgICAgICAgICAgY29tcG9uZW50cy5lcnJvciA9IGNvbXBvbmVudHMuZXJyb3IgfHwgXCJIVFRQIFVSSXMgbXVzdCBoYXZlIGEgaG9zdC5cIjtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGNvbXBvbmVudHM7XHJcbiAgICB9LFxyXG4gICAgc2VyaWFsaXplOiBmdW5jdGlvbiAoY29tcG9uZW50cywgb3B0aW9ucykge1xyXG4gICAgICAgIC8vbm9ybWFsaXplIHRoZSBkZWZhdWx0IHBvcnRcclxuICAgICAgICBpZiAoY29tcG9uZW50cy5wb3J0ID09PSAoU3RyaW5nKGNvbXBvbmVudHMuc2NoZW1lKS50b0xvd2VyQ2FzZSgpICE9PSBcImh0dHBzXCIgPyA4MCA6IDQ0MykgfHwgY29tcG9uZW50cy5wb3J0ID09PSBcIlwiKSB7XHJcbiAgICAgICAgICAgIGNvbXBvbmVudHMucG9ydCA9IHVuZGVmaW5lZDtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy9ub3JtYWxpemUgdGhlIGVtcHR5IHBhdGhcclxuICAgICAgICBpZiAoIWNvbXBvbmVudHMucGF0aCkge1xyXG4gICAgICAgICAgICBjb21wb25lbnRzLnBhdGggPSBcIi9cIjtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy9OT1RFOiBXZSBkbyBub3QgcGFyc2UgcXVlcnkgc3RyaW5ncyBmb3IgSFRUUCBVUklzXHJcbiAgICAgICAgLy9hcyBXV1cgRm9ybSBVcmwgRW5jb2RlZCBxdWVyeSBzdHJpbmdzIGFyZSBwYXJ0IG9mIHRoZSBIVE1MNCsgc3BlYyxcclxuICAgICAgICAvL2FuZCBub3QgdGhlIEhUVFAgc3BlYy4gXHJcbiAgICAgICAgcmV0dXJuIGNvbXBvbmVudHM7XHJcbiAgICB9XHJcbn07XHJcbiIsIi8vLzxyZWZlcmVuY2UgcGF0aD1cIi4uL3VyaS50c1wiLz5cclxuaWYgKHR5cGVvZiBDT01QSUxFRCA9PT0gXCJ1bmRlZmluZWRcIiAmJiB0eXBlb2YgVVJJID09PSBcInVuZGVmaW5lZFwiICYmIHR5cGVvZiByZXF1aXJlID09PSBcImZ1bmN0aW9uXCIpIHtcclxuICAgIHZhciBVUkkgPSByZXF1aXJlKFwiLi4vdXJpXCIpLCBwdW55Y29kZSA9IHJlcXVpcmUoXCIuLi9wdW55Y29kZVwiKTtcclxufVxyXG4oZnVuY3Rpb24gKCkge1xyXG4gICAgZnVuY3Rpb24gbWVyZ2UoKSB7XHJcbiAgICAgICAgdmFyIHNldHMgPSBbXTtcclxuICAgICAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgYXJndW1lbnRzLmxlbmd0aDsgX2krKykge1xyXG4gICAgICAgICAgICBzZXRzW19pIC0gMF0gPSBhcmd1bWVudHNbX2ldO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoc2V0cy5sZW5ndGggPiAxKSB7XHJcbiAgICAgICAgICAgIHNldHNbMF0gPSBzZXRzWzBdLnNsaWNlKDAsIC0xKTtcclxuICAgICAgICAgICAgdmFyIHhsID0gc2V0cy5sZW5ndGggLSAxO1xyXG4gICAgICAgICAgICBmb3IgKHZhciB4ID0gMTsgeCA8IHhsOyArK3gpIHtcclxuICAgICAgICAgICAgICAgIHNldHNbeF0gPSBzZXRzW3hdLnNsaWNlKDEsIC0xKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBzZXRzW3hsXSA9IHNldHNbeGxdLnNsaWNlKDEpO1xyXG4gICAgICAgICAgICByZXR1cm4gc2V0cy5qb2luKCcnKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgIHJldHVybiBzZXRzWzBdO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIGZ1bmN0aW9uIHN1YmV4cChzdHIpIHtcclxuICAgICAgICByZXR1cm4gXCIoPzpcIiArIHN0ciArIFwiKVwiO1xyXG4gICAgfVxyXG4gICAgdmFyIE8gPSB7fSwgaXNJUkkgPSBVUkkuSVJJX1NVUFBPUlQsIFxyXG4gICAgLy9SRkMgMzk4NlxyXG4gICAgVU5SRVNFUlZFRCQkID0gXCJbQS1aYS16MC05XFxcXC1cXFxcLlxcXFxfXFxcXH5cIiArIChpc0lSSSA/IFwiXFxcXHhBMC1cXFxcdTIwMERcXFxcdTIwMTAtXFxcXHUyMDI5XFxcXHUyMDJGLVxcXFx1RDdGRlxcXFx1RjkwMC1cXFxcdUZEQ0ZcXFxcdUZERjAtXFxcXHVGRkVGXCIgOiBcIlwiKSArIFwiXVwiLCBIRVhESUckJCA9IFwiWzAtOUEtRmEtZl1cIiwgUENUX0VOQ09ERUQkID0gc3ViZXhwKHN1YmV4cChcIiVbRUZlZl1cIiArIEhFWERJRyQkICsgXCIlXCIgKyBIRVhESUckJCArIEhFWERJRyQkICsgXCIlXCIgKyBIRVhESUckJCArIEhFWERJRyQkKSArIFwifFwiICsgc3ViZXhwKFwiJVs4OUEtRmEtZl1cIiArIEhFWERJRyQkICsgXCIlXCIgKyBIRVhESUckJCArIEhFWERJRyQkKSArIFwifFwiICsgc3ViZXhwKFwiJVwiICsgSEVYRElHJCQgKyBIRVhESUckJCkpLCBcclxuICAgIC8vUkZDIDUzMjIsIGV4Y2VwdCB0aGVzZSBzeW1ib2xzIGFzIHBlciBSRkMgNjA2ODogQCA6IC8gPyAjIFsgXSAmIDsgPSBcclxuICAgIC8vQVRFWFQkJCA9IFwiW0EtWmEtejAtOVxcXFwhXFxcXCNcXFxcJFxcXFwlXFxcXCZcXFxcJ1xcXFwqXFxcXCtcXFxcLVxcXFwvXFxcXD1cXFxcP1xcXFxeXFxcXF9cXFxcYFxcXFx7XFxcXHxcXFxcfVxcXFx+XVwiLFxyXG4gICAgLy9XU1AkJCA9IFwiW1xcXFx4MjBcXFxceDA5XVwiLFxyXG4gICAgLy9PQlNfUVRFWFQkJCA9IFwiW1xcXFx4MDEtXFxcXHgwOFxcXFx4MEJcXFxceDBDXFxcXHgwRS1cXFxceDFGXFxcXHg3Rl1cIiwgIC8vKCVkMS04IC8gJWQxMS0xMiAvICVkMTQtMzEgLyAlZDEyNylcclxuICAgIC8vUVRFWFQkJCA9IG1lcmdlKFwiW1xcXFx4MjFcXFxceDIzLVxcXFx4NUJcXFxceDVELVxcXFx4N0VdXCIsIE9CU19RVEVYVCQkKSwgIC8vJWQzMyAvICVkMzUtOTEgLyAlZDkzLTEyNiAvIG9icy1xdGV4dFxyXG4gICAgLy9WQ0hBUiQkID0gXCJbXFxcXHgyMS1cXFxceDdFXVwiLFxyXG4gICAgLy9XU1AkJCA9IFwiW1xcXFx4MjBcXFxceDA5XVwiLFxyXG4gICAgLy9PQlNfUVAkID0gc3ViZXhwKFwiXFxcXFxcXFxcIiArIG1lcmdlKFwiW1xcXFx4MDBcXFxceDBEXFxcXHgwQV1cIiwgT0JTX1FURVhUJCQpKSwgIC8vJWQwIC8gQ1IgLyBMRiAvIG9icy1xdGV4dFxyXG4gICAgLy9GV1MkID0gc3ViZXhwKHN1YmV4cChXU1AkJCArIFwiKlwiICsgXCJcXFxceDBEXFxcXHgwQVwiKSArIFwiP1wiICsgV1NQJCQgKyBcIitcIiksXHJcbiAgICAvL1FVT1RFRF9QQUlSJCA9IHN1YmV4cChzdWJleHAoXCJcXFxcXFxcXFwiICsgc3ViZXhwKFZDSEFSJCQgKyBcInxcIiArIFdTUCQkKSkgKyBcInxcIiArIE9CU19RUCQpLFxyXG4gICAgLy9RVU9URURfU1RSSU5HJCA9IHN1YmV4cCgnXFxcXFwiJyArIHN1YmV4cChGV1MkICsgXCI/XCIgKyBRQ09OVEVOVCQpICsgXCIqXCIgKyBGV1MkICsgXCI/XCIgKyAnXFxcXFwiJyksXHJcbiAgICBBVEVYVCQkID0gXCJbQS1aYS16MC05XFxcXCFcXFxcJFxcXFwlXFxcXCdcXFxcKlxcXFwrXFxcXC1cXFxcXlxcXFxfXFxcXGBcXFxce1xcXFx8XFxcXH1cXFxcfl1cIiwgUVRFWFQkJCA9IFwiW1xcXFwhXFxcXCRcXFxcJVxcXFwnXFxcXChcXFxcKVxcXFwqXFxcXCtcXFxcLFxcXFwtXFxcXC4wLTlcXFxcPFxcXFw+QS1aXFxcXHg1RS1cXFxceDdFXVwiLCBWQ0hBUiQkID0gbWVyZ2UoUVRFWFQkJCwgXCJbXFxcXFxcXCJcXFxcXFxcXF1cIiksIERPVF9BVE9NX1RFWFQkID0gc3ViZXhwKEFURVhUJCQgKyBcIitcIiArIHN1YmV4cChcIlxcXFwuXCIgKyBBVEVYVCQkICsgXCIrXCIpICsgXCIqXCIpLCBRVU9URURfUEFJUiQgPSBzdWJleHAoXCJcXFxcXFxcXFwiICsgVkNIQVIkJCksIFFDT05URU5UJCA9IHN1YmV4cChRVEVYVCQkICsgXCJ8XCIgKyBRVU9URURfUEFJUiQpLCBRVU9URURfU1RSSU5HJCA9IHN1YmV4cCgnXFxcXFwiJyArIFFDT05URU5UJCArIFwiKlwiICsgJ1xcXFxcIicpLCBcclxuICAgIC8vUkZDIDYwNjhcclxuICAgIERURVhUX05PX09CUyQkID0gXCJbXFxcXHgyMS1cXFxceDVBXFxcXHg1RS1cXFxceDdFXVwiLCBTT01FX0RFTElNUyQkID0gXCJbXFxcXCFcXFxcJFxcXFwnXFxcXChcXFxcKVxcXFwqXFxcXCtcXFxcLFxcXFw7XFxcXDpcXFxcQF1cIiwgUUNIQVIkID0gc3ViZXhwKFVOUkVTRVJWRUQkJCArIFwifFwiICsgUENUX0VOQ09ERUQkICsgXCJ8XCIgKyBTT01FX0RFTElNUyQkKSwgRE9NQUlOJCA9IHN1YmV4cChET1RfQVRPTV9URVhUJCArIFwifFwiICsgXCJcXFxcW1wiICsgRFRFWFRfTk9fT0JTJCQgKyBcIipcIiArIFwiXFxcXF1cIiksIExPQ0FMX1BBUlQkID0gc3ViZXhwKERPVF9BVE9NX1RFWFQkICsgXCJ8XCIgKyBRVU9URURfU1RSSU5HJCksIEFERFJfU1BFQyQgPSBzdWJleHAoTE9DQUxfUEFSVCQgKyBcIlxcXFxAXCIgKyBET01BSU4kKSwgVE8kID0gc3ViZXhwKEFERFJfU1BFQyQgKyBzdWJleHAoXCJcXFxcLFwiICsgQUREUl9TUEVDJCkgKyBcIipcIiksIEhGTkFNRSQgPSBzdWJleHAoUUNIQVIkICsgXCIqXCIpLCBIRlZBTFVFJCA9IEhGTkFNRSQsIEhGSUVMRCQgPSBzdWJleHAoSEZOQU1FJCArIFwiXFxcXD1cIiArIEhGVkFMVUUkKSwgSEZJRUxEUzIkID0gc3ViZXhwKEhGSUVMRCQgKyBzdWJleHAoXCJcXFxcJlwiICsgSEZJRUxEJCkgKyBcIipcIiksIEhGSUVMRFMkID0gc3ViZXhwKFwiXFxcXD9cIiArIEhGSUVMRFMyJCksIE1BSUxUT19VUkkgPSBVUkkuVkFMSURBVEVfU1VQUE9SVCAmJiBuZXcgUmVnRXhwKFwiXm1haWx0b1xcXFw6XCIgKyBUTyQgKyBcIj9cIiArIEhGSUVMRFMkICsgXCI/JFwiKSwgVU5SRVNFUlZFRCA9IG5ldyBSZWdFeHAoVU5SRVNFUlZFRCQkLCBcImdcIiksIFBDVF9FTkNPREVEID0gbmV3IFJlZ0V4cChQQ1RfRU5DT0RFRCQsIFwiZ1wiKSwgTk9UX0xPQ0FMX1BBUlQgPSBuZXcgUmVnRXhwKG1lcmdlKFwiW15dXCIsIEFURVhUJCQsIFwiW1xcXFwuXVwiLCAnW1xcXFxcIl0nLCBWQ0hBUiQkKSwgXCJnXCIpLCBOT1RfRE9NQUlOID0gbmV3IFJlZ0V4cChtZXJnZShcIlteXVwiLCBBVEVYVCQkLCBcIltcXFxcLl1cIiwgXCJbXFxcXFtdXCIsIERURVhUX05PX09CUyQkLCBcIltcXFxcXV1cIiksIFwiZ1wiKSwgTk9UX0hGTkFNRSA9IG5ldyBSZWdFeHAobWVyZ2UoXCJbXl1cIiwgVU5SRVNFUlZFRCQkLCBTT01FX0RFTElNUyQkKSwgXCJnXCIpLCBOT1RfSEZWQUxVRSA9IE5PVF9IRk5BTUUsIFRPID0gVVJJLlZBTElEQVRFX1NVUFBPUlQgJiYgbmV3IFJlZ0V4cChcIl5cIiArIFRPJCArIFwiJFwiKSwgSEZJRUxEUyA9IFVSSS5WQUxJREFURV9TVVBQT1JUICYmIG5ldyBSZWdFeHAoXCJeXCIgKyBIRklFTERTMiQgKyBcIiRcIik7XHJcbiAgICBmdW5jdGlvbiB0b1VwcGVyQ2FzZShzdHIpIHtcclxuICAgICAgICByZXR1cm4gc3RyLnRvVXBwZXJDYXNlKCk7XHJcbiAgICB9XHJcbiAgICBmdW5jdGlvbiBkZWNvZGVVbnJlc2VydmVkKHN0cikge1xyXG4gICAgICAgIHZhciBkZWNTdHIgPSBVUkkucGN0RGVjQ2hhcnMoc3RyKTtcclxuICAgICAgICByZXR1cm4gKCFkZWNTdHIubWF0Y2goVU5SRVNFUlZFRCkgPyBzdHIgOiBkZWNTdHIpO1xyXG4gICAgfVxyXG4gICAgZnVuY3Rpb24gdG9BcnJheShvYmopIHtcclxuICAgICAgICByZXR1cm4gb2JqICE9PSB1bmRlZmluZWQgJiYgb2JqICE9PSBudWxsID8gKG9iaiBpbnN0YW5jZW9mIEFycmF5ICYmICFvYmouY2FsbGVlID8gb2JqIDogKHR5cGVvZiBvYmoubGVuZ3RoICE9PSBcIm51bWJlclwiIHx8IG9iai5zcGxpdCB8fCBvYmouc2V0SW50ZXJ2YWwgfHwgb2JqLmNhbGwgPyBbb2JqXSA6IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKG9iaikpKSA6IFtdO1xyXG4gICAgfVxyXG4gICAgVVJJLlNDSEVNRVNbXCJtYWlsdG9cIl0gPSB7XHJcbiAgICAgICAgcGFyc2U6IGZ1bmN0aW9uIChjb21wb25lbnRzLCBvcHRpb25zKSB7XHJcbiAgICAgICAgICAgIGlmIChVUkkuVkFMSURBVEVfU1VQUE9SVCAmJiAhY29tcG9uZW50cy5lcnJvcikge1xyXG4gICAgICAgICAgICAgICAgaWYgKGNvbXBvbmVudHMucGF0aCAmJiAhVE8udGVzdChjb21wb25lbnRzLnBhdGgpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50cy5lcnJvciA9IFwiRW1haWwgYWRkcmVzcyBpcyBub3QgdmFsaWRcIjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGNvbXBvbmVudHMucXVlcnkgJiYgIUhGSUVMRFMudGVzdChjb21wb25lbnRzLnF1ZXJ5KSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudHMuZXJyb3IgPSBcIkhlYWRlciBmaWVsZHMgYXJlIGludmFsaWRcIjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB2YXIgdG8gPSBjb21wb25lbnRzLnRvID0gKGNvbXBvbmVudHMucGF0aCA/IGNvbXBvbmVudHMucGF0aC5zcGxpdChcIixcIikgOiBbXSk7XHJcbiAgICAgICAgICAgIGNvbXBvbmVudHMucGF0aCA9IHVuZGVmaW5lZDtcclxuICAgICAgICAgICAgaWYgKGNvbXBvbmVudHMucXVlcnkpIHtcclxuICAgICAgICAgICAgICAgIHZhciB1bmtub3duSGVhZGVycyA9IGZhbHNlLCBoZWFkZXJzID0ge307XHJcbiAgICAgICAgICAgICAgICB2YXIgaGZpZWxkcyA9IGNvbXBvbmVudHMucXVlcnkuc3BsaXQoXCImXCIpO1xyXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgeCA9IDAsIHhsID0gaGZpZWxkcy5sZW5ndGg7IHggPCB4bDsgKyt4KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIGhmaWVsZCA9IGhmaWVsZHNbeF0uc3BsaXQoXCI9XCIpO1xyXG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoaGZpZWxkWzBdKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJ0b1wiOlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRvQWRkcnMgPSBoZmllbGRbMV0uc3BsaXQoXCIsXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgeF8xID0gMCwgeGxfMSA9IHRvQWRkcnMubGVuZ3RoOyB4XzEgPCB4bF8xOyArK3hfMSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvLnB1c2godG9BZGRyc1t4XzFdKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwic3ViamVjdFwiOlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50cy5zdWJqZWN0ID0gVVJJLnVuZXNjYXBlQ29tcG9uZW50KGhmaWVsZFsxXSwgb3B0aW9ucyk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImJvZHlcIjpcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudHMuYm9keSA9IFVSSS51bmVzY2FwZUNvbXBvbmVudChoZmllbGRbMV0sIG9wdGlvbnMpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmtub3duSGVhZGVycyA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXJzW1VSSS51bmVzY2FwZUNvbXBvbmVudChoZmllbGRbMF0sIG9wdGlvbnMpXSA9IFVSSS51bmVzY2FwZUNvbXBvbmVudChoZmllbGRbMV0sIG9wdGlvbnMpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKHVua25vd25IZWFkZXJzKVxyXG4gICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudHMuaGVhZGVycyA9IGhlYWRlcnM7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY29tcG9uZW50cy5xdWVyeSA9IHVuZGVmaW5lZDtcclxuICAgICAgICAgICAgZm9yICh2YXIgeCA9IDAsIHhsID0gdG8ubGVuZ3RoOyB4IDwgeGw7ICsreCkge1xyXG4gICAgICAgICAgICAgICAgdmFyIGFkZHIgPSB0b1t4XS5zcGxpdChcIkBcIik7XHJcbiAgICAgICAgICAgICAgICBhZGRyWzBdID0gVVJJLnVuZXNjYXBlQ29tcG9uZW50KGFkZHJbMF0pO1xyXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBwdW55Y29kZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiAhb3B0aW9ucy51bmljb2RlU3VwcG9ydCkge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vY29udmVydCBVbmljb2RlIElETiAtPiBBU0NJSSBJRE5cclxuICAgICAgICAgICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRyWzFdID0gcHVueWNvZGUudG9BU0NJSShVUkkudW5lc2NhcGVDb21wb25lbnQoYWRkclsxXSwgb3B0aW9ucykudG9Mb3dlckNhc2UoKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudHMuZXJyb3IgPSBjb21wb25lbnRzLmVycm9yIHx8IFwiRW1haWwgYWRkcmVzcydzIGRvbWFpbiBuYW1lIGNhbiBub3QgYmUgY29udmVydGVkIHRvIEFTQ0lJIHZpYSBwdW55Y29kZTogXCIgKyBlO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIGFkZHJbMV0gPSBVUkkudW5lc2NhcGVDb21wb25lbnQoYWRkclsxXSwgb3B0aW9ucykudG9Mb3dlckNhc2UoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHRvW3hdID0gYWRkci5qb2luKFwiQFwiKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gY29tcG9uZW50cztcclxuICAgICAgICB9LFxyXG4gICAgICAgIHNlcmlhbGl6ZTogZnVuY3Rpb24gKGNvbXBvbmVudHMsIG9wdGlvbnMpIHtcclxuICAgICAgICAgICAgdmFyIHRvID0gdG9BcnJheShjb21wb25lbnRzLnRvKTtcclxuICAgICAgICAgICAgaWYgKHRvKSB7XHJcbiAgICAgICAgICAgICAgICBmb3IgKHZhciB4ID0gMCwgeGwgPSB0by5sZW5ndGg7IHggPCB4bDsgKyt4KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRvQWRkciA9IFN0cmluZyh0b1t4XSk7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIGF0SWR4ID0gdG9BZGRyLmxhc3RJbmRleE9mKFwiQFwiKTtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgbG9jYWxQYXJ0ID0gdG9BZGRyLnNsaWNlKDAsIGF0SWR4KTtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgZG9tYWluID0gdG9BZGRyLnNsaWNlKGF0SWR4ICsgMSk7XHJcbiAgICAgICAgICAgICAgICAgICAgbG9jYWxQYXJ0ID0gbG9jYWxQYXJ0LnJlcGxhY2UoUENUX0VOQ09ERUQsIGRlY29kZVVucmVzZXJ2ZWQpLnJlcGxhY2UoUENUX0VOQ09ERUQsIHRvVXBwZXJDYXNlKS5yZXBsYWNlKE5PVF9MT0NBTF9QQVJULCBVUkkucGN0RW5jQ2hhcik7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBwdW55Y29kZSAhPT0gXCJ1bmRlZmluZWRcIikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvL2NvbnZlcnQgSUROIHZpYSBwdW55Y29kZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9tYWluID0gKCFvcHRpb25zLmlyaSA/IHB1bnljb2RlLnRvQVNDSUkoVVJJLnVuZXNjYXBlQ29tcG9uZW50KGRvbWFpbiwgb3B0aW9ucykudG9Mb3dlckNhc2UoKSkgOiBwdW55Y29kZS50b1VuaWNvZGUoZG9tYWluKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudHMuZXJyb3IgPSBjb21wb25lbnRzLmVycm9yIHx8IFwiRW1haWwgYWRkcmVzcydzIGRvbWFpbiBuYW1lIGNhbiBub3QgYmUgY29udmVydGVkIHRvIFwiICsgKCFvcHRpb25zLmlyaSA/IFwiQVNDSUlcIiA6IFwiVW5pY29kZVwiKSArIFwiIHZpYSBwdW55Y29kZTogXCIgKyBlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBkb21haW4gPSBkb21haW4ucmVwbGFjZShQQ1RfRU5DT0RFRCwgZGVjb2RlVW5yZXNlcnZlZCkudG9Mb3dlckNhc2UoKS5yZXBsYWNlKFBDVF9FTkNPREVELCB0b1VwcGVyQ2FzZSkucmVwbGFjZShOT1RfRE9NQUlOLCBVUkkucGN0RW5jQ2hhcik7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIHRvW3hdID0gbG9jYWxQYXJ0ICsgXCJAXCIgKyBkb21haW47XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBjb21wb25lbnRzLnBhdGggPSB0by5qb2luKFwiLFwiKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB2YXIgaGVhZGVycyA9IGNvbXBvbmVudHMuaGVhZGVycyA9IGNvbXBvbmVudHMuaGVhZGVycyB8fCB7fTtcclxuICAgICAgICAgICAgaWYgKGNvbXBvbmVudHMuc3ViamVjdClcclxuICAgICAgICAgICAgICAgIGhlYWRlcnNbXCJzdWJqZWN0XCJdID0gY29tcG9uZW50cy5zdWJqZWN0O1xyXG4gICAgICAgICAgICBpZiAoY29tcG9uZW50cy5ib2R5KVxyXG4gICAgICAgICAgICAgICAgaGVhZGVyc1tcImJvZHlcIl0gPSBjb21wb25lbnRzLmJvZHk7XHJcbiAgICAgICAgICAgIHZhciBmaWVsZHMgPSBbXTtcclxuICAgICAgICAgICAgZm9yICh2YXIgbmFtZV8xIGluIGhlYWRlcnMpIHtcclxuICAgICAgICAgICAgICAgIGlmIChoZWFkZXJzW25hbWVfMV0gIT09IE9bbmFtZV8xXSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGZpZWxkcy5wdXNoKG5hbWVfMS5yZXBsYWNlKFBDVF9FTkNPREVELCBkZWNvZGVVbnJlc2VydmVkKS5yZXBsYWNlKFBDVF9FTkNPREVELCB0b1VwcGVyQ2FzZSkucmVwbGFjZShOT1RfSEZOQU1FLCBVUkkucGN0RW5jQ2hhcikgK1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBcIj1cIiArXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRlcnNbbmFtZV8xXS5yZXBsYWNlKFBDVF9FTkNPREVELCBkZWNvZGVVbnJlc2VydmVkKS5yZXBsYWNlKFBDVF9FTkNPREVELCB0b1VwcGVyQ2FzZSkucmVwbGFjZShOT1RfSEZWQUxVRSwgVVJJLnBjdEVuY0NoYXIpKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAoZmllbGRzLmxlbmd0aCkge1xyXG4gICAgICAgICAgICAgICAgY29tcG9uZW50cy5xdWVyeSA9IGZpZWxkcy5qb2luKFwiJlwiKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gY29tcG9uZW50cztcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG59KSgpO1xyXG4iLCIvLy88cmVmZXJlbmNlIHBhdGg9XCIuLi91cmkudHNcIi8+XHJcbmlmICh0eXBlb2YgQ09NUElMRUQgPT09IFwidW5kZWZpbmVkXCIgJiYgdHlwZW9mIFVSSSA9PT0gXCJ1bmRlZmluZWRcIiAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gXCJmdW5jdGlvblwiKVxyXG4gICAgdmFyIFVSSSA9IHJlcXVpcmUoXCIuLi91cmlcIik7XHJcbihmdW5jdGlvbiAoKSB7XHJcbiAgICB2YXIgcGN0RW5jQ2hhciA9IFVSSS5wY3RFbmNDaGFyLCBOSUQkID0gXCIoPzpbMC05QS1aYS16XVswLTlBLVphLXpcXFxcLV17MSwzMX0pXCIsIFBDVF9FTkNPREVEJCA9IFwiKD86XFxcXCVbMC05QS1GYS1mXXsyfSlcIiwgVFJBTlMkJCA9IFwiWzAtOUEtWmEtelxcXFwoXFxcXClcXFxcK1xcXFwsXFxcXC1cXFxcLlxcXFw6XFxcXD1cXFxcQFxcXFw7XFxcXCRcXFxcX1xcXFwhXFxcXCpcXFxcJ1xcXFwvXFxcXD9cXFxcI11cIiwgTlNTJCA9IFwiKD86KD86XCIgKyBQQ1RfRU5DT0RFRCQgKyBcInxcIiArIFRSQU5TJCQgKyBcIikrKVwiLCBVUk5fU0NIRU1FID0gbmV3IFJlZ0V4cChcIl51cm5cXFxcOihcIiArIE5JRCQgKyBcIikkXCIpLCBVUk5fUEFUSCA9IG5ldyBSZWdFeHAoXCJeKFwiICsgTklEJCArIFwiKVxcXFw6KFwiICsgTlNTJCArIFwiKSRcIiksIFVSTl9QQVJTRSA9IC9eKFteXFw6XSspXFw6KC4qKS8sIFVSTl9FWENMVURFRCA9IC9bXFx4MDAtXFx4MjBcXFxcXFxcIlxcJlxcPFxcPlxcW1xcXVxcXlxcYFxce1xcfFxcfVxcflxceDdGLVxceEZGXS9nLCBVVUlEID0gL15bMC05QS1GYS1mXXs4fSg/OlxcLVswLTlBLUZhLWZdezR9KXszfVxcLVswLTlBLUZhLWZdezEyfSQvO1xyXG4gICAgLy9SRkMgMjE0MVxyXG4gICAgVVJJLlNDSEVNRVNbXCJ1cm5cIl0gPSB7XHJcbiAgICAgICAgcGFyc2U6IGZ1bmN0aW9uIChjb21wb25lbnRzLCBvcHRpb25zKSB7XHJcbiAgICAgICAgICAgIHZhciBtYXRjaGVzID0gY29tcG9uZW50cy5wYXRoLm1hdGNoKFVSTl9QQVRIKSwgc2NoZW1lLCBzY2hlbWVIYW5kbGVyO1xyXG4gICAgICAgICAgICBpZiAoIW1hdGNoZXMpIHtcclxuICAgICAgICAgICAgICAgIGlmICghb3B0aW9ucy50b2xlcmFudCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudHMuZXJyb3IgPSBjb21wb25lbnRzLmVycm9yIHx8IFwiVVJOIGlzIG5vdCBzdHJpY3RseSB2YWxpZC5cIjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIG1hdGNoZXMgPSBjb21wb25lbnRzLnBhdGgubWF0Y2goVVJOX1BBUlNFKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAobWF0Y2hlcykge1xyXG4gICAgICAgICAgICAgICAgc2NoZW1lID0gXCJ1cm46XCIgKyBtYXRjaGVzWzFdLnRvTG93ZXJDYXNlKCk7XHJcbiAgICAgICAgICAgICAgICBzY2hlbWVIYW5kbGVyID0gVVJJLlNDSEVNRVNbc2NoZW1lXTtcclxuICAgICAgICAgICAgICAgIC8vaW4gb3JkZXIgdG8gc2VyaWFsaXplIHByb3Blcmx5LCBcclxuICAgICAgICAgICAgICAgIC8vZXZlcnkgVVJOIG11c3QgaGF2ZSBhIHNlcmlhbGl6ZXIgdGhhdCBjYWxscyB0aGUgVVJOIHNlcmlhbGl6ZXIgXHJcbiAgICAgICAgICAgICAgICBpZiAoIXNjaGVtZUhhbmRsZXIpIHtcclxuICAgICAgICAgICAgICAgICAgICAvL2NyZWF0ZSBmYWtlIHNjaGVtZSBoYW5kbGVyXHJcbiAgICAgICAgICAgICAgICAgICAgc2NoZW1lSGFuZGxlciA9IFVSSS5TQ0hFTUVTW3NjaGVtZV0gPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcnNlOiBmdW5jdGlvbiAoY29tcG9uZW50cywgb3B0aW9ucykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvbXBvbmVudHM7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcmlhbGl6ZTogVVJJLlNDSEVNRVNbXCJ1cm5cIl0uc2VyaWFsaXplXHJcbiAgICAgICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGNvbXBvbmVudHMuc2NoZW1lID0gc2NoZW1lO1xyXG4gICAgICAgICAgICAgICAgY29tcG9uZW50cy5wYXRoID0gbWF0Y2hlc1syXTtcclxuICAgICAgICAgICAgICAgIGNvbXBvbmVudHMgPSBzY2hlbWVIYW5kbGVyLnBhcnNlKGNvbXBvbmVudHMsIG9wdGlvbnMpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgY29tcG9uZW50cy5lcnJvciA9IGNvbXBvbmVudHMuZXJyb3IgfHwgXCJVUk4gY2FuIG5vdCBiZSBwYXJzZWQuXCI7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIGNvbXBvbmVudHM7XHJcbiAgICAgICAgfSxcclxuICAgICAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIChjb21wb25lbnRzLCBvcHRpb25zKSB7XHJcbiAgICAgICAgICAgIHZhciBzY2hlbWUgPSBjb21wb25lbnRzLnNjaGVtZSB8fCBvcHRpb25zLnNjaGVtZSwgbWF0Y2hlcztcclxuICAgICAgICAgICAgaWYgKHNjaGVtZSAmJiBzY2hlbWUgIT09IFwidXJuXCIpIHtcclxuICAgICAgICAgICAgICAgIHZhciBtYXRjaGVzID0gc2NoZW1lLm1hdGNoKFVSTl9TQ0hFTUUpO1xyXG4gICAgICAgICAgICAgICAgaWYgKCFtYXRjaGVzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcyA9IFtcInVybjpcIiArIHNjaGVtZSwgc2NoZW1lXTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGNvbXBvbmVudHMuc2NoZW1lID0gXCJ1cm5cIjtcclxuICAgICAgICAgICAgICAgIGNvbXBvbmVudHMucGF0aCA9IG1hdGNoZXNbMV0gKyBcIjpcIiArIChjb21wb25lbnRzLnBhdGggPyBjb21wb25lbnRzLnBhdGgucmVwbGFjZShVUk5fRVhDTFVERUQsIHBjdEVuY0NoYXIpIDogXCJcIik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIGNvbXBvbmVudHM7XHJcbiAgICAgICAgfVxyXG4gICAgfTtcclxuICAgIC8vUkZDIDQxMjJcclxuICAgIFVSSS5TQ0hFTUVTW1widXJuOnV1aWRcIl0gPSB7XHJcbiAgICAgICAgcGFyc2U6IGZ1bmN0aW9uIChjb21wb25lbnRzLCBvcHRpb25zKSB7XHJcbiAgICAgICAgICAgIGlmICghb3B0aW9ucy50b2xlcmFudCAmJiAoIWNvbXBvbmVudHMucGF0aCB8fCAhY29tcG9uZW50cy5wYXRoLm1hdGNoKFVVSUQpKSkge1xyXG4gICAgICAgICAgICAgICAgY29tcG9uZW50cy5lcnJvciA9IGNvbXBvbmVudHMuZXJyb3IgfHwgXCJVVUlEIGlzIG5vdCB2YWxpZC5cIjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gY29tcG9uZW50cztcclxuICAgICAgICB9LFxyXG4gICAgICAgIHNlcmlhbGl6ZTogZnVuY3Rpb24gKGNvbXBvbmVudHMsIG9wdGlvbnMpIHtcclxuICAgICAgICAgICAgLy9lbnN1cmUgVVVJRCBpcyB2YWxpZFxyXG4gICAgICAgICAgICBpZiAoIW9wdGlvbnMudG9sZXJhbnQgJiYgKCFjb21wb25lbnRzLnBhdGggfHwgIWNvbXBvbmVudHMucGF0aC5tYXRjaChVVUlEKSkpIHtcclxuICAgICAgICAgICAgICAgIC8vaW52YWxpZCBVVUlEcyBjYW4gbm90IGhhdmUgdGhpcyBzY2hlbWVcclxuICAgICAgICAgICAgICAgIGNvbXBvbmVudHMuc2NoZW1lID0gdW5kZWZpbmVkO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgLy9ub3JtYWxpemUgVVVJRFxyXG4gICAgICAgICAgICAgICAgY29tcG9uZW50cy5wYXRoID0gKGNvbXBvbmVudHMucGF0aCB8fCBcIlwiKS50b0xvd2VyQ2FzZSgpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiBVUkkuU0NIRU1FU1tcInVyblwiXS5zZXJpYWxpemUoY29tcG9uZW50cywgb3B0aW9ucyk7XHJcbiAgICAgICAgfVxyXG4gICAgfTtcclxufSgpKTtcclxuIiwiLyoqXHJcbiAqIFVSSS5qc1xyXG4gKlxyXG4gKiBAZmlsZW92ZXJ2aWV3IEFuIFJGQyAzOTg2IGNvbXBsaWFudCwgc2NoZW1lIGV4dGVuZGFibGUgVVJJIHBhcnNpbmcvdmFsaWRhdGluZy9yZXNvbHZpbmcgbGlicmFyeSBmb3IgSmF2YVNjcmlwdC5cclxuICogQGF1dGhvciA8YSBocmVmPVwibWFpbHRvOmdhcnkuY291cnRAZ21haWwuY29tXCI+R2FyeSBDb3VydDwvYT5cclxuICogQHZlcnNpb24gMi4wLjBcclxuICogQHNlZSBodHRwOi8vZ2l0aHViLmNvbS9nYXJ5Y291cnQvdXJpLWpzXHJcbiAqIEBsaWNlbnNlIFVSSS5qcyB2Mi4wLjAgKGMpIDIwMTEgR2FyeSBDb3VydC4gTGljZW5zZTogaHR0cDovL2dpdGh1Yi5jb20vZ2FyeWNvdXJ0L3VyaS1qc1xyXG4gKi9cclxuLyoqXHJcbiAqIENvcHlyaWdodCAyMDExIEdhcnkgQ291cnQuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbiAqXHJcbiAqIFJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sIGFyZVxyXG4gKiBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcclxuICpcclxuICogICAgMS4gUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzIGxpc3Qgb2ZcclxuICogICAgICAgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxyXG4gKlxyXG4gKiAgICAyLiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXMgbGlzdFxyXG4gKiAgICAgICBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyIG1hdGVyaWFsc1xyXG4gKiAgICAgICBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXHJcbiAqXHJcbiAqIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgR0FSWSBDT1VSVCBgYEFTIElTJycgQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRURcclxuICogV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORFxyXG4gKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUgRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgR0FSWSBDT1VSVCBPUlxyXG4gKiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUlxyXG4gKiBDT05TRVFVRU5USUFMIERBTUFHRVMgKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SXHJcbiAqIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT05cclxuICogQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlQgKElOQ0xVRElOR1xyXG4gKiBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVMgU09GVFdBUkUsIEVWRU4gSUZcclxuICogQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXHJcbiAqXHJcbiAqIFRoZSB2aWV3cyBhbmQgY29uY2x1c2lvbnMgY29udGFpbmVkIGluIHRoZSBzb2Z0d2FyZSBhbmQgZG9jdW1lbnRhdGlvbiBhcmUgdGhvc2Ugb2YgdGhlXHJcbiAqIGF1dGhvcnMgYW5kIHNob3VsZCBub3QgYmUgaW50ZXJwcmV0ZWQgYXMgcmVwcmVzZW50aW5nIG9mZmljaWFsIHBvbGljaWVzLCBlaXRoZXIgZXhwcmVzc2VkXHJcbiAqIG9yIGltcGxpZWQsIG9mIEdhcnkgQ291cnQuXHJcbiAqL1xyXG4vLy88cmVmZXJlbmNlIHBhdGg9XCJwdW55Y29kZS5kLnRzXCIvPlxyXG4vLy88cmVmZXJlbmNlIHBhdGg9XCJjb21tb25qcy5kLnRzXCIvPlxyXG4vKipcclxuICogQ29tcGlsZXIgc3dpdGNoIGZvciBpbmRpY2F0aW5nIGNvZGUgaXMgY29tcGlsZWRcclxuICogQGRlZmluZSB7Ym9vbGVhbn1cclxuICovXHJcbnZhciBDT01QSUxFRCA9IGZhbHNlO1xyXG4vKipcclxuICogQ29tcGlsZXIgc3dpdGNoIGZvciBzdXBwb3J0aW5nIElSSSBVUklzXHJcbiAqIEBkZWZpbmUge2Jvb2xlYW59XHJcbiAqL1xyXG52YXIgVVJJX19JUklfU1VQUE9SVCA9IHRydWU7XHJcbi8qKlxyXG4gKiBDb21waWxlciBzd2l0Y2ggZm9yIHN1cHBvcnRpbmcgVVJJIHZhbGlkYXRpb25cclxuICogQGRlZmluZSB7Ym9vbGVhbn1cclxuICovXHJcbnZhciBVUklfX1ZBTElEQVRFX1NVUFBPUlQgPSB0cnVlO1xyXG52YXIgVVJJID0gKGZ1bmN0aW9uICgpIHtcclxuICAgIGZ1bmN0aW9uIG1lcmdlKCkge1xyXG4gICAgICAgIHZhciBzZXRzID0gW107XHJcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcclxuICAgICAgICAgICAgc2V0c1tfaSAtIDBdID0gYXJndW1lbnRzW19pXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKHNldHMubGVuZ3RoID4gMSkge1xyXG4gICAgICAgICAgICBzZXRzWzBdID0gc2V0c1swXS5zbGljZSgwLCAtMSk7XHJcbiAgICAgICAgICAgIHZhciB4bCA9IHNldHMubGVuZ3RoIC0gMTtcclxuICAgICAgICAgICAgZm9yICh2YXIgeCA9IDE7IHggPCB4bDsgKyt4KSB7XHJcbiAgICAgICAgICAgICAgICBzZXRzW3hdID0gc2V0c1t4XS5zbGljZSgxLCAtMSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgc2V0c1t4bF0gPSBzZXRzW3hsXS5zbGljZSgxKTtcclxuICAgICAgICAgICAgcmV0dXJuIHNldHMuam9pbignJyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gc2V0c1swXTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICBmdW5jdGlvbiBzdWJleHAoc3RyKSB7XHJcbiAgICAgICAgcmV0dXJuIFwiKD86XCIgKyBzdHIgKyBcIilcIjtcclxuICAgIH1cclxuICAgIGZ1bmN0aW9uIGJ1aWxkRXhwcyhpc0lSSSkge1xyXG4gICAgICAgIHZhciBBTFBIQSQkID0gXCJbQS1aYS16XVwiLCBDUiQgPSBcIltcXFxceDBEXVwiLCBESUdJVCQkID0gXCJbMC05XVwiLCBEUVVPVEUkJCA9IFwiW1xcXFx4MjJdXCIsIEhFWERJRyQkID0gbWVyZ2UoRElHSVQkJCwgXCJbQS1GYS1mXVwiKSwgTEYkJCA9IFwiW1xcXFx4MEFdXCIsIFNQJCQgPSBcIltcXFxceDIwXVwiLCBQQ1RfRU5DT0RFRCQgPSBzdWJleHAoc3ViZXhwKFwiJVtFRmVmXVwiICsgSEVYRElHJCQgKyBcIiVcIiArIEhFWERJRyQkICsgSEVYRElHJCQgKyBcIiVcIiArIEhFWERJRyQkICsgSEVYRElHJCQpICsgXCJ8XCIgKyBzdWJleHAoXCIlWzg5QS1GYS1mXVwiICsgSEVYRElHJCQgKyBcIiVcIiArIEhFWERJRyQkICsgSEVYRElHJCQpICsgXCJ8XCIgKyBzdWJleHAoXCIlXCIgKyBIRVhESUckJCArIEhFWERJRyQkKSksIEdFTl9ERUxJTVMkJCA9IFwiW1xcXFw6XFxcXC9cXFxcP1xcXFwjXFxcXFtcXFxcXVxcXFxAXVwiLCBTVUJfREVMSU1TJCQgPSBcIltcXFxcIVxcXFwkXFxcXCZcXFxcJ1xcXFwoXFxcXClcXFxcKlxcXFwrXFxcXCxcXFxcO1xcXFw9XVwiLCBSRVNFUlZFRCQkID0gbWVyZ2UoR0VOX0RFTElNUyQkLCBTVUJfREVMSU1TJCQpLCBVQ1NDSEFSJCQgPSBpc0lSSSA/IFwiW1xcXFx4QTAtXFxcXHUyMDBEXFxcXHUyMDEwLVxcXFx1MjAyOVxcXFx1MjAyRi1cXFxcdUQ3RkZcXFxcdUY5MDAtXFxcXHVGRENGXFxcXHVGREYwLVxcXFx1RkZFRl1cIiA6IFwiW11cIiwgSVBSSVZBVEUkJCA9IGlzSVJJID8gXCJbXFxcXHVFMDAwLVxcXFx1RjhGRl1cIiA6IFwiW11cIiwgVU5SRVNFUlZFRCQkID0gbWVyZ2UoQUxQSEEkJCwgRElHSVQkJCwgXCJbXFxcXC1cXFxcLlxcXFxfXFxcXH5dXCIsIFVDU0NIQVIkJCksIFNDSEVNRSQgPSBzdWJleHAoQUxQSEEkJCArIG1lcmdlKEFMUEhBJCQsIERJR0lUJCQsIFwiW1xcXFwrXFxcXC1cXFxcLl1cIikgKyBcIipcIiksIFVTRVJJTkZPJCA9IHN1YmV4cChzdWJleHAoUENUX0VOQ09ERUQkICsgXCJ8XCIgKyBtZXJnZShVTlJFU0VSVkVEJCQsIFNVQl9ERUxJTVMkJCwgXCJbXFxcXDpdXCIpKSArIFwiKlwiKSwgREVDX09DVEVUJCA9IHN1YmV4cChzdWJleHAoXCIyNVswLTVdXCIpICsgXCJ8XCIgKyBzdWJleHAoXCIyWzAtNF1cIiArIERJR0lUJCQpICsgXCJ8XCIgKyBzdWJleHAoXCIxXCIgKyBESUdJVCQkICsgRElHSVQkJCkgKyBcInxcIiArIHN1YmV4cChcIlsxLTldXCIgKyBESUdJVCQkKSArIFwifFwiICsgRElHSVQkJCksIElQVjRBRERSRVNTJCA9IHN1YmV4cChERUNfT0NURVQkICsgXCJcXFxcLlwiICsgREVDX09DVEVUJCArIFwiXFxcXC5cIiArIERFQ19PQ1RFVCQgKyBcIlxcXFwuXCIgKyBERUNfT0NURVQkKSwgSDE2JCA9IHN1YmV4cChIRVhESUckJCArIFwiezEsNH1cIiksIExTMzIkID0gc3ViZXhwKHN1YmV4cChIMTYkICsgXCJcXFxcOlwiICsgSDE2JCkgKyBcInxcIiArIElQVjRBRERSRVNTJCksIElQVjZBRERSRVNTJCA9IHN1YmV4cChtZXJnZShVTlJFU0VSVkVEJCQsIFNVQl9ERUxJTVMkJCwgXCJbXFxcXDpdXCIpICsgXCIrXCIpLCBJUFZGVVRVUkUkID0gc3ViZXhwKFwidlwiICsgSEVYRElHJCQgKyBcIitcXFxcLlwiICsgbWVyZ2UoVU5SRVNFUlZFRCQkLCBTVUJfREVMSU1TJCQsIFwiW1xcXFw6XVwiKSArIFwiK1wiKSwgSVBfTElURVJBTCQgPSBzdWJleHAoXCJcXFxcW1wiICsgc3ViZXhwKElQVjZBRERSRVNTJCArIFwifFwiICsgSVBWRlVUVVJFJCkgKyBcIlxcXFxdXCIpLCBSRUdfTkFNRSQgPSBzdWJleHAoc3ViZXhwKFBDVF9FTkNPREVEJCArIFwifFwiICsgbWVyZ2UoVU5SRVNFUlZFRCQkLCBTVUJfREVMSU1TJCQpKSArIFwiKlwiKSwgSE9TVCQgPSBzdWJleHAoSVBfTElURVJBTCQgKyBcInxcIiArIElQVjRBRERSRVNTJCArIFwiKD8hXCIgKyBSRUdfTkFNRSQgKyBcIilcIiArIFwifFwiICsgUkVHX05BTUUkKSwgUE9SVCQgPSBzdWJleHAoRElHSVQkJCArIFwiKlwiKSwgQVVUSE9SSVRZJCA9IHN1YmV4cChzdWJleHAoVVNFUklORk8kICsgXCJAXCIpICsgXCI/XCIgKyBIT1NUJCArIHN1YmV4cChcIlxcXFw6XCIgKyBQT1JUJCkgKyBcIj9cIiksIFBDSEFSJCA9IHN1YmV4cChQQ1RfRU5DT0RFRCQgKyBcInxcIiArIG1lcmdlKFVOUkVTRVJWRUQkJCwgU1VCX0RFTElNUyQkLCBcIltcXFxcOlxcXFxAXVwiKSksIFNFR01FTlQkID0gc3ViZXhwKFBDSEFSJCArIFwiKlwiKSwgU0VHTUVOVF9OWiQgPSBzdWJleHAoUENIQVIkICsgXCIrXCIpLCBTRUdNRU5UX05aX05DJCA9IHN1YmV4cChzdWJleHAoUENUX0VOQ09ERUQkICsgXCJ8XCIgKyBtZXJnZShVTlJFU0VSVkVEJCQsIFNVQl9ERUxJTVMkJCwgXCJbXFxcXEBdXCIpKSArIFwiK1wiKSwgUEFUSF9BQkVNUFRZJCA9IHN1YmV4cChzdWJleHAoXCJcXFxcL1wiICsgU0VHTUVOVCQpICsgXCIqXCIpLCBQQVRIX0FCU09MVVRFJCA9IHN1YmV4cChcIlxcXFwvXCIgKyBzdWJleHAoU0VHTUVOVF9OWiQgKyBQQVRIX0FCRU1QVFkkKSArIFwiP1wiKSwgUEFUSF9OT1NDSEVNRSQgPSBzdWJleHAoU0VHTUVOVF9OWl9OQyQgKyBQQVRIX0FCRU1QVFkkKSwgUEFUSF9ST09UTEVTUyQgPSBzdWJleHAoU0VHTUVOVF9OWiQgKyBQQVRIX0FCRU1QVFkkKSwgUEFUSF9FTVBUWSQgPSBcIig/IVwiICsgUENIQVIkICsgXCIpXCIsIFBBVEgkID0gc3ViZXhwKFBBVEhfQUJFTVBUWSQgKyBcInxcIiArIFBBVEhfQUJTT0xVVEUkICsgXCJ8XCIgKyBQQVRIX05PU0NIRU1FJCArIFwifFwiICsgUEFUSF9ST09UTEVTUyQgKyBcInxcIiArIFBBVEhfRU1QVFkkKSwgUVVFUlkkID0gc3ViZXhwKHN1YmV4cChQQ0hBUiQgKyBcInxcIiArIG1lcmdlKFwiW1xcXFwvXFxcXD9dXCIsIElQUklWQVRFJCQpKSArIFwiKlwiKSwgRlJBR01FTlQkID0gc3ViZXhwKHN1YmV4cChQQ0hBUiQgKyBcInxbXFxcXC9cXFxcP11cIikgKyBcIipcIiksIEhJRVJfUEFSVCQgPSBzdWJleHAoc3ViZXhwKFwiXFxcXC9cXFxcL1wiICsgQVVUSE9SSVRZJCArIFBBVEhfQUJFTVBUWSQpICsgXCJ8XCIgKyBQQVRIX0FCU09MVVRFJCArIFwifFwiICsgUEFUSF9ST09UTEVTUyQgKyBcInxcIiArIFBBVEhfRU1QVFkkKSwgVVJJJCA9IHN1YmV4cChTQ0hFTUUkICsgXCJcXFxcOlwiICsgSElFUl9QQVJUJCArIHN1YmV4cChcIlxcXFw/XCIgKyBRVUVSWSQpICsgXCI/XCIgKyBzdWJleHAoXCJcXFxcI1wiICsgRlJBR01FTlQkKSArIFwiP1wiKSwgUkVMQVRJVkVfUEFSVCQgPSBzdWJleHAoc3ViZXhwKFwiXFxcXC9cXFxcL1wiICsgQVVUSE9SSVRZJCArIFBBVEhfQUJFTVBUWSQpICsgXCJ8XCIgKyBQQVRIX0FCU09MVVRFJCArIFwifFwiICsgUEFUSF9OT1NDSEVNRSQgKyBcInxcIiArIFBBVEhfRU1QVFkkKSwgUkVMQVRJVkUkID0gc3ViZXhwKFJFTEFUSVZFX1BBUlQkICsgc3ViZXhwKFwiXFxcXD9cIiArIFFVRVJZJCkgKyBcIj9cIiArIHN1YmV4cChcIlxcXFwjXCIgKyBGUkFHTUVOVCQpICsgXCI/XCIpLCBVUklfUkVGRVJFTkNFJCA9IHN1YmV4cChVUkkkICsgXCJ8XCIgKyBSRUxBVElWRSQpLCBBQlNPTFVURV9VUkkkID0gc3ViZXhwKFNDSEVNRSQgKyBcIlxcXFw6XCIgKyBISUVSX1BBUlQkICsgc3ViZXhwKFwiXFxcXD9cIiArIFFVRVJZJCkgKyBcIj9cIiksIEdFTkVSSUNfUkVGJCA9IFwiXihcIiArIFNDSEVNRSQgKyBcIilcXFxcOlwiICsgc3ViZXhwKHN1YmV4cChcIlxcXFwvXFxcXC8oXCIgKyBzdWJleHAoXCIoXCIgKyBVU0VSSU5GTyQgKyBcIilAXCIpICsgXCI/KFwiICsgSE9TVCQgKyBcIilcIiArIHN1YmV4cChcIlxcXFw6KFwiICsgUE9SVCQgKyBcIilcIikgKyBcIj8pXCIpICsgXCI/KFwiICsgUEFUSF9BQkVNUFRZJCArIFwifFwiICsgUEFUSF9BQlNPTFVURSQgKyBcInxcIiArIFBBVEhfUk9PVExFU1MkICsgXCJ8XCIgKyBQQVRIX0VNUFRZJCArIFwiKVwiKSArIHN1YmV4cChcIlxcXFw/KFwiICsgUVVFUlkkICsgXCIpXCIpICsgXCI/XCIgKyBzdWJleHAoXCJcXFxcIyhcIiArIEZSQUdNRU5UJCArIFwiKVwiKSArIFwiPyRcIiwgUkVMQVRJVkVfUkVGJCA9IFwiXigpezB9XCIgKyBzdWJleHAoc3ViZXhwKFwiXFxcXC9cXFxcLyhcIiArIHN1YmV4cChcIihcIiArIFVTRVJJTkZPJCArIFwiKUBcIikgKyBcIj8oXCIgKyBIT1NUJCArIFwiKVwiICsgc3ViZXhwKFwiXFxcXDooXCIgKyBQT1JUJCArIFwiKVwiKSArIFwiPylcIikgKyBcIj8oXCIgKyBQQVRIX0FCRU1QVFkkICsgXCJ8XCIgKyBQQVRIX0FCU09MVVRFJCArIFwifFwiICsgUEFUSF9OT1NDSEVNRSQgKyBcInxcIiArIFBBVEhfRU1QVFkkICsgXCIpXCIpICsgc3ViZXhwKFwiXFxcXD8oXCIgKyBRVUVSWSQgKyBcIilcIikgKyBcIj9cIiArIHN1YmV4cChcIlxcXFwjKFwiICsgRlJBR01FTlQkICsgXCIpXCIpICsgXCI/JFwiLCBBQlNPTFVURV9SRUYkID0gXCJeKFwiICsgU0NIRU1FJCArIFwiKVxcXFw6XCIgKyBzdWJleHAoc3ViZXhwKFwiXFxcXC9cXFxcLyhcIiArIHN1YmV4cChcIihcIiArIFVTRVJJTkZPJCArIFwiKUBcIikgKyBcIj8oXCIgKyBIT1NUJCArIFwiKVwiICsgc3ViZXhwKFwiXFxcXDooXCIgKyBQT1JUJCArIFwiKVwiKSArIFwiPylcIikgKyBcIj8oXCIgKyBQQVRIX0FCRU1QVFkkICsgXCJ8XCIgKyBQQVRIX0FCU09MVVRFJCArIFwifFwiICsgUEFUSF9ST09UTEVTUyQgKyBcInxcIiArIFBBVEhfRU1QVFkkICsgXCIpXCIpICsgc3ViZXhwKFwiXFxcXD8oXCIgKyBRVUVSWSQgKyBcIilcIikgKyBcIj8kXCIsIFNBTUVET0NfUkVGJCA9IFwiXlwiICsgc3ViZXhwKFwiXFxcXCMoXCIgKyBGUkFHTUVOVCQgKyBcIilcIikgKyBcIj8kXCIsIEFVVEhPUklUWV9SRUYkID0gXCJeXCIgKyBzdWJleHAoXCIoXCIgKyBVU0VSSU5GTyQgKyBcIilAXCIpICsgXCI/KFwiICsgSE9TVCQgKyBcIilcIiArIHN1YmV4cChcIlxcXFw6KFwiICsgUE9SVCQgKyBcIilcIikgKyBcIj8kXCI7XHJcbiAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgVVJJX1JFRjogVVJJX19WQUxJREFURV9TVVBQT1JUICYmIG5ldyBSZWdFeHAoXCIoXCIgKyBHRU5FUklDX1JFRiQgKyBcIil8KFwiICsgUkVMQVRJVkVfUkVGJCArIFwiKVwiKSxcclxuICAgICAgICAgICAgTk9UX1NDSEVNRTogbmV3IFJlZ0V4cChtZXJnZShcIlteXVwiLCBBTFBIQSQkLCBESUdJVCQkLCBcIltcXFxcK1xcXFwtXFxcXC5dXCIpLCBcImdcIiksXHJcbiAgICAgICAgICAgIE5PVF9VU0VSSU5GTzogbmV3IFJlZ0V4cChtZXJnZShcIlteXFxcXCVcXFxcOl1cIiwgVU5SRVNFUlZFRCQkLCBTVUJfREVMSU1TJCQpLCBcImdcIiksXHJcbiAgICAgICAgICAgIE5PVF9IT1NUOiBuZXcgUmVnRXhwKG1lcmdlKFwiW15cXFxcJV1cIiwgVU5SRVNFUlZFRCQkLCBTVUJfREVMSU1TJCQpLCBcImdcIiksXHJcbiAgICAgICAgICAgIE5PVF9QQVRIOiBuZXcgUmVnRXhwKG1lcmdlKFwiW15cXFxcJVxcXFwvXFxcXDpcXFxcQF1cIiwgVU5SRVNFUlZFRCQkLCBTVUJfREVMSU1TJCQpLCBcImdcIiksXHJcbiAgICAgICAgICAgIE5PVF9QQVRIX05PU0NIRU1FOiBuZXcgUmVnRXhwKG1lcmdlKFwiW15cXFxcJVxcXFwvXFxcXEBdXCIsIFVOUkVTRVJWRUQkJCwgU1VCX0RFTElNUyQkKSwgXCJnXCIpLFxyXG4gICAgICAgICAgICBOT1RfUVVFUlk6IG5ldyBSZWdFeHAobWVyZ2UoXCJbXlxcXFwlXVwiLCBVTlJFU0VSVkVEJCQsIFNVQl9ERUxJTVMkJCwgXCJbXFxcXDpcXFxcQFxcXFwvXFxcXD9dXCIsIElQUklWQVRFJCQpLCBcImdcIiksXHJcbiAgICAgICAgICAgIE5PVF9GUkFHTUVOVDogbmV3IFJlZ0V4cChtZXJnZShcIlteXFxcXCVdXCIsIFVOUkVTRVJWRUQkJCwgU1VCX0RFTElNUyQkLCBcIltcXFxcOlxcXFxAXFxcXC9cXFxcP11cIiksIFwiZ1wiKSxcclxuICAgICAgICAgICAgRVNDQVBFOiBuZXcgUmVnRXhwKG1lcmdlKFwiW15dXCIsIFVOUkVTRVJWRUQkJCwgU1VCX0RFTElNUyQkKSwgXCJnXCIpLFxyXG4gICAgICAgICAgICBVTlJFU0VSVkVEOiBuZXcgUmVnRXhwKFVOUkVTRVJWRUQkJCwgXCJnXCIpLFxyXG4gICAgICAgICAgICBPVEhFUl9DSEFSUzogbmV3IFJlZ0V4cChtZXJnZShcIlteXFxcXCVdXCIsIFVOUkVTRVJWRUQkJCwgUkVTRVJWRUQkJCksIFwiZ1wiKSxcclxuICAgICAgICAgICAgUENUX0VOQ09ERUQ6IG5ldyBSZWdFeHAoUENUX0VOQ09ERUQkLCBcImdcIilcclxuICAgICAgICB9O1xyXG4gICAgfVxyXG4gICAgdmFyIFVSSV9QUk9UT0NPTCA9IGJ1aWxkRXhwcyhmYWxzZSksIElSSV9QUk9UT0NPTCA9IFVSSV9fSVJJX1NVUFBPUlQgPyBidWlsZEV4cHModHJ1ZSkgOiB1bmRlZmluZWQsIFVSSV9QQVJTRSA9IC9eKD86KFteOlxcLz8jXSspOik/KD86XFwvXFwvKCg/OihbXlxcLz8jQF0qKUApPyhbXlxcLz8jOl0qKSg/OlxcOihcXGQqKSk/KSk/KFtePyNdKikoPzpcXD8oW14jXSopKT8oPzojKCg/Oi58XFxuKSopKT8vaSwgUkRTMSA9IC9eXFwuXFwuP1xcLy8sIFJEUzIgPSAvXlxcL1xcLihcXC98JCkvLCBSRFMzID0gL15cXC9cXC5cXC4oXFwvfCQpLywgUkRTNCA9IC9eXFwuXFwuPyQvLCBSRFM1ID0gL15cXC8/KD86LnxcXG4pKj8oPz1cXC98JCkvLCBOT19NQVRDSF9JU19VTkRFRklORUQgPSAoXCJcIikubWF0Y2goLygpezB9LylbMV0gPT09IHVuZGVmaW5lZDtcclxuICAgIGZ1bmN0aW9uIHBjdEVuY0NoYXIoY2hyKSB7XHJcbiAgICAgICAgdmFyIGMgPSBjaHIuY2hhckNvZGVBdCgwKSwgZTtcclxuICAgICAgICBpZiAoYyA8IDE2KVxyXG4gICAgICAgICAgICBlID0gXCIlMFwiICsgYy50b1N0cmluZygxNikudG9VcHBlckNhc2UoKTtcclxuICAgICAgICBlbHNlIGlmIChjIDwgMTI4KVxyXG4gICAgICAgICAgICBlID0gXCIlXCIgKyBjLnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpO1xyXG4gICAgICAgIGVsc2UgaWYgKGMgPCAyMDQ4KVxyXG4gICAgICAgICAgICBlID0gXCIlXCIgKyAoKGMgPj4gNikgfCAxOTIpLnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpICsgXCIlXCIgKyAoKGMgJiA2MykgfCAxMjgpLnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpO1xyXG4gICAgICAgIGVsc2VcclxuICAgICAgICAgICAgZSA9IFwiJVwiICsgKChjID4+IDEyKSB8IDIyNCkudG9TdHJpbmcoMTYpLnRvVXBwZXJDYXNlKCkgKyBcIiVcIiArICgoKGMgPj4gNikgJiA2MykgfCAxMjgpLnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpICsgXCIlXCIgKyAoKGMgJiA2MykgfCAxMjgpLnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpO1xyXG4gICAgICAgIHJldHVybiBlO1xyXG4gICAgfVxyXG4gICAgZnVuY3Rpb24gcGN0RGVjQ2hhcnMoc3RyKSB7XHJcbiAgICAgICAgdmFyIG5ld1N0ciA9IFwiXCIsIGkgPSAwLCBpbCA9IHN0ci5sZW5ndGgsIGMsIGMyLCBjMztcclxuICAgICAgICB3aGlsZSAoaSA8IGlsKSB7XHJcbiAgICAgICAgICAgIGMgPSBwYXJzZUludChzdHIuc3Vic3RyKGkgKyAxLCAyKSwgMTYpO1xyXG4gICAgICAgICAgICBpZiAoYyA8IDEyOCkge1xyXG4gICAgICAgICAgICAgICAgbmV3U3RyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYyk7XHJcbiAgICAgICAgICAgICAgICBpICs9IDM7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSBpZiAoYyA+PSAxOTQgJiYgYyA8IDIyNCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKChpbCAtIGkpID49IDYpIHtcclxuICAgICAgICAgICAgICAgICAgICBjMiA9IHBhcnNlSW50KHN0ci5zdWJzdHIoaSArIDQsIDIpLCAxNik7XHJcbiAgICAgICAgICAgICAgICAgICAgbmV3U3RyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKChjICYgMzEpIDw8IDYpIHwgKGMyICYgNjMpKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIG5ld1N0ciArPSBzdHIuc3Vic3RyKGksIDYpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaSArPSA2O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2UgaWYgKGMgPj0gMjI0KSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoKGlsIC0gaSkgPj0gOSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGMyID0gcGFyc2VJbnQoc3RyLnN1YnN0cihpICsgNCwgMiksIDE2KTtcclxuICAgICAgICAgICAgICAgICAgICBjMyA9IHBhcnNlSW50KHN0ci5zdWJzdHIoaSArIDcsIDIpLCAxNik7XHJcbiAgICAgICAgICAgICAgICAgICAgbmV3U3RyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKChjICYgMTUpIDw8IDEyKSB8ICgoYzIgJiA2MykgPDwgNikgfCAoYzMgJiA2MykpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbmV3U3RyICs9IHN0ci5zdWJzdHIoaSwgOSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpICs9IDk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBuZXdTdHIgKz0gc3RyLnN1YnN0cihpLCAzKTtcclxuICAgICAgICAgICAgICAgIGkgKz0gMztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gbmV3U3RyO1xyXG4gICAgfVxyXG4gICAgZnVuY3Rpb24gdHlwZU9mKG8pIHtcclxuICAgICAgICByZXR1cm4gbyA9PT0gdW5kZWZpbmVkID8gXCJ1bmRlZmluZWRcIiA6IChvID09PSBudWxsID8gXCJudWxsXCIgOiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobykuc3BsaXQoXCIgXCIpLnBvcCgpLnNwbGl0KFwiXVwiKS5zaGlmdCgpLnRvTG93ZXJDYXNlKCkpO1xyXG4gICAgfVxyXG4gICAgZnVuY3Rpb24gdG9VcHBlckNhc2Uoc3RyKSB7XHJcbiAgICAgICAgcmV0dXJuIHN0ci50b1VwcGVyQ2FzZSgpO1xyXG4gICAgfVxyXG4gICAgdmFyIFNDSEVNRVMgPSB7fTtcclxuICAgIGZ1bmN0aW9uIF9ub3JtYWxpemVDb21wb25lbnRFbmNvZGluZyhjb21wb25lbnRzLCBwcm90b2NvbCkge1xyXG4gICAgICAgIGZ1bmN0aW9uIGRlY29kZVVucmVzZXJ2ZWQoc3RyKSB7XHJcbiAgICAgICAgICAgIHZhciBkZWNTdHIgPSBwY3REZWNDaGFycyhzdHIpO1xyXG4gICAgICAgICAgICByZXR1cm4gKCFkZWNTdHIubWF0Y2gocHJvdG9jb2wuVU5SRVNFUlZFRCkgPyBzdHIgOiBkZWNTdHIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoY29tcG9uZW50cy5zY2hlbWUpXHJcbiAgICAgICAgICAgIGNvbXBvbmVudHMuc2NoZW1lID0gU3RyaW5nKGNvbXBvbmVudHMuc2NoZW1lKS5yZXBsYWNlKHByb3RvY29sLlBDVF9FTkNPREVELCBkZWNvZGVVbnJlc2VydmVkKS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UocHJvdG9jb2wuTk9UX1NDSEVNRSwgXCJcIik7XHJcbiAgICAgICAgaWYgKGNvbXBvbmVudHMudXNlcmluZm8gIT09IHVuZGVmaW5lZClcclxuICAgICAgICAgICAgY29tcG9uZW50cy51c2VyaW5mbyA9IFN0cmluZyhjb21wb25lbnRzLnVzZXJpbmZvKS5yZXBsYWNlKHByb3RvY29sLlBDVF9FTkNPREVELCBkZWNvZGVVbnJlc2VydmVkKS5yZXBsYWNlKHByb3RvY29sLk5PVF9VU0VSSU5GTywgcGN0RW5jQ2hhcikucmVwbGFjZShwcm90b2NvbC5QQ1RfRU5DT0RFRCwgdG9VcHBlckNhc2UpO1xyXG4gICAgICAgIGlmIChjb21wb25lbnRzLmhvc3QgIT09IHVuZGVmaW5lZClcclxuICAgICAgICAgICAgY29tcG9uZW50cy5ob3N0ID0gU3RyaW5nKGNvbXBvbmVudHMuaG9zdCkucmVwbGFjZShwcm90b2NvbC5QQ1RfRU5DT0RFRCwgZGVjb2RlVW5yZXNlcnZlZCkudG9Mb3dlckNhc2UoKS5yZXBsYWNlKHByb3RvY29sLk5PVF9IT1NULCBwY3RFbmNDaGFyKS5yZXBsYWNlKHByb3RvY29sLlBDVF9FTkNPREVELCB0b1VwcGVyQ2FzZSk7XHJcbiAgICAgICAgaWYgKGNvbXBvbmVudHMucGF0aCAhPT0gdW5kZWZpbmVkKVxyXG4gICAgICAgICAgICBjb21wb25lbnRzLnBhdGggPSBTdHJpbmcoY29tcG9uZW50cy5wYXRoKS5yZXBsYWNlKHByb3RvY29sLlBDVF9FTkNPREVELCBkZWNvZGVVbnJlc2VydmVkKS5yZXBsYWNlKChjb21wb25lbnRzLnNjaGVtZSA/IHByb3RvY29sLk5PVF9QQVRIIDogcHJvdG9jb2wuTk9UX1BBVEhfTk9TQ0hFTUUpLCBwY3RFbmNDaGFyKS5yZXBsYWNlKHByb3RvY29sLlBDVF9FTkNPREVELCB0b1VwcGVyQ2FzZSk7XHJcbiAgICAgICAgaWYgKGNvbXBvbmVudHMucXVlcnkgIT09IHVuZGVmaW5lZClcclxuICAgICAgICAgICAgY29tcG9uZW50cy5xdWVyeSA9IFN0cmluZyhjb21wb25lbnRzLnF1ZXJ5KS5yZXBsYWNlKHByb3RvY29sLlBDVF9FTkNPREVELCBkZWNvZGVVbnJlc2VydmVkKS5yZXBsYWNlKHByb3RvY29sLk5PVF9RVUVSWSwgcGN0RW5jQ2hhcikucmVwbGFjZShwcm90b2NvbC5QQ1RfRU5DT0RFRCwgdG9VcHBlckNhc2UpO1xyXG4gICAgICAgIGlmIChjb21wb25lbnRzLmZyYWdtZW50ICE9PSB1bmRlZmluZWQpXHJcbiAgICAgICAgICAgIGNvbXBvbmVudHMuZnJhZ21lbnQgPSBTdHJpbmcoY29tcG9uZW50cy5mcmFnbWVudCkucmVwbGFjZShwcm90b2NvbC5QQ1RfRU5DT0RFRCwgZGVjb2RlVW5yZXNlcnZlZCkucmVwbGFjZShwcm90b2NvbC5OT1RfRlJBR01FTlQsIHBjdEVuY0NoYXIpLnJlcGxhY2UocHJvdG9jb2wuUENUX0VOQ09ERUQsIHRvVXBwZXJDYXNlKTtcclxuICAgICAgICByZXR1cm4gY29tcG9uZW50cztcclxuICAgIH1cclxuICAgIDtcclxuICAgIGZ1bmN0aW9uIHBhcnNlKHVyaVN0cmluZywgb3B0aW9ucykge1xyXG4gICAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsgb3B0aW9ucyA9IHt9OyB9XHJcbiAgICAgICAgdmFyIHByb3RvY29sID0gKFVSSV9fSVJJX1NVUFBPUlQgJiYgb3B0aW9ucy5pcmkgIT09IGZhbHNlID8gSVJJX1BST1RPQ09MIDogVVJJX1BST1RPQ09MKSwgbWF0Y2hlcywgcGFyc2VFcnJvciA9IGZhbHNlLCBjb21wb25lbnRzID0ge30sIHNjaGVtZUhhbmRsZXI7XHJcbiAgICAgICAgaWYgKG9wdGlvbnMucmVmZXJlbmNlID09PSBcInN1ZmZpeFwiKVxyXG4gICAgICAgICAgICB1cmlTdHJpbmcgPSAob3B0aW9ucy5zY2hlbWUgPyBvcHRpb25zLnNjaGVtZSArIFwiOlwiIDogXCJcIikgKyBcIi8vXCIgKyB1cmlTdHJpbmc7XHJcbiAgICAgICAgaWYgKFVSSV9fVkFMSURBVEVfU1VQUE9SVCkge1xyXG4gICAgICAgICAgICBtYXRjaGVzID0gdXJpU3RyaW5nLm1hdGNoKHByb3RvY29sLlVSSV9SRUYpO1xyXG4gICAgICAgICAgICBpZiAobWF0Y2hlcykge1xyXG4gICAgICAgICAgICAgICAgaWYgKG1hdGNoZXNbMV0pIHtcclxuICAgICAgICAgICAgICAgICAgICAvL2dlbmVyaWMgVVJJXHJcbiAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcyA9IG1hdGNoZXMuc2xpY2UoMSwgMTApO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy9yZWxhdGl2ZSBVUklcclxuICAgICAgICAgICAgICAgICAgICBtYXRjaGVzID0gbWF0Y2hlcy5zbGljZSgxMCwgMTkpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICghbWF0Y2hlcykge1xyXG4gICAgICAgICAgICAgICAgcGFyc2VFcnJvciA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICBpZiAoIW9wdGlvbnMudG9sZXJhbnQpXHJcbiAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50cy5lcnJvciA9IGNvbXBvbmVudHMuZXJyb3IgfHwgXCJVUkkgaXMgbm90IHN0cmljdGx5IHZhbGlkLlwiO1xyXG4gICAgICAgICAgICAgICAgbWF0Y2hlcyA9IHVyaVN0cmluZy5tYXRjaChVUklfUEFSU0UpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICBtYXRjaGVzID0gdXJpU3RyaW5nLm1hdGNoKFVSSV9QQVJTRSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChtYXRjaGVzKSB7XHJcbiAgICAgICAgICAgIGlmIChOT19NQVRDSF9JU19VTkRFRklORUQpIHtcclxuICAgICAgICAgICAgICAgIC8vc3RvcmUgZWFjaCBjb21wb25lbnRcclxuICAgICAgICAgICAgICAgIGNvbXBvbmVudHMuc2NoZW1lID0gbWF0Y2hlc1sxXTtcclxuICAgICAgICAgICAgICAgIC8vY29tcG9uZW50cy5hdXRob3JpdHkgPSBtYXRjaGVzWzJdO1xyXG4gICAgICAgICAgICAgICAgY29tcG9uZW50cy51c2VyaW5mbyA9IG1hdGNoZXNbM107XHJcbiAgICAgICAgICAgICAgICBjb21wb25lbnRzLmhvc3QgPSBtYXRjaGVzWzRdO1xyXG4gICAgICAgICAgICAgICAgY29tcG9uZW50cy5wb3J0ID0gcGFyc2VJbnQobWF0Y2hlc1s1XSwgMTApO1xyXG4gICAgICAgICAgICAgICAgY29tcG9uZW50cy5wYXRoID0gbWF0Y2hlc1s2XSB8fCBcIlwiO1xyXG4gICAgICAgICAgICAgICAgY29tcG9uZW50cy5xdWVyeSA9IG1hdGNoZXNbN107XHJcbiAgICAgICAgICAgICAgICBjb21wb25lbnRzLmZyYWdtZW50ID0gbWF0Y2hlc1s4XTtcclxuICAgICAgICAgICAgICAgIC8vZml4IHBvcnQgbnVtYmVyXHJcbiAgICAgICAgICAgICAgICBpZiAoaXNOYU4oY29tcG9uZW50cy5wb3J0KSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudHMucG9ydCA9IG1hdGNoZXNbNV07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAvL3N0b3JlIGVhY2ggY29tcG9uZW50XHJcbiAgICAgICAgICAgICAgICBjb21wb25lbnRzLnNjaGVtZSA9IG1hdGNoZXNbMV0gfHwgdW5kZWZpbmVkO1xyXG4gICAgICAgICAgICAgICAgLy9jb21wb25lbnRzLmF1dGhvcml0eSA9ICh1cmlTdHJpbmcuaW5kZXhPZihcIi8vXCIpICE9PSAtMSA/IG1hdGNoZXNbMl0gOiB1bmRlZmluZWQpO1xyXG4gICAgICAgICAgICAgICAgY29tcG9uZW50cy51c2VyaW5mbyA9ICh1cmlTdHJpbmcuaW5kZXhPZihcIkBcIikgIT09IC0xID8gbWF0Y2hlc1szXSA6IHVuZGVmaW5lZCk7XHJcbiAgICAgICAgICAgICAgICBjb21wb25lbnRzLmhvc3QgPSAodXJpU3RyaW5nLmluZGV4T2YoXCIvL1wiKSAhPT0gLTEgPyBtYXRjaGVzWzRdIDogdW5kZWZpbmVkKTtcclxuICAgICAgICAgICAgICAgIGNvbXBvbmVudHMucG9ydCA9IHBhcnNlSW50KG1hdGNoZXNbNV0sIDEwKTtcclxuICAgICAgICAgICAgICAgIGNvbXBvbmVudHMucGF0aCA9IG1hdGNoZXNbNl0gfHwgXCJcIjtcclxuICAgICAgICAgICAgICAgIGNvbXBvbmVudHMucXVlcnkgPSAodXJpU3RyaW5nLmluZGV4T2YoXCI/XCIpICE9PSAtMSA/IG1hdGNoZXNbN10gOiB1bmRlZmluZWQpO1xyXG4gICAgICAgICAgICAgICAgY29tcG9uZW50cy5mcmFnbWVudCA9ICh1cmlTdHJpbmcuaW5kZXhPZihcIiNcIikgIT09IC0xID8gbWF0Y2hlc1s4XSA6IHVuZGVmaW5lZCk7XHJcbiAgICAgICAgICAgICAgICAvL2ZpeCBwb3J0IG51bWJlclxyXG4gICAgICAgICAgICAgICAgaWYgKGlzTmFOKGNvbXBvbmVudHMucG9ydCkpIHtcclxuICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRzLnBvcnQgPSAodXJpU3RyaW5nLm1hdGNoKC9cXC9cXC8oPzoufFxcbikqXFw6KD86XFwvfFxcP3xcXCN8JCkvKSA/IG1hdGNoZXNbNF0gOiB1bmRlZmluZWQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIC8vZGV0ZXJtaW5lIHJlZmVyZW5jZSB0eXBlXHJcbiAgICAgICAgICAgIGlmIChjb21wb25lbnRzLnNjaGVtZSA9PT0gdW5kZWZpbmVkICYmIGNvbXBvbmVudHMudXNlcmluZm8gPT09IHVuZGVmaW5lZCAmJiBjb21wb25lbnRzLmhvc3QgPT09IHVuZGVmaW5lZCAmJiBjb21wb25lbnRzLnBvcnQgPT09IHVuZGVmaW5lZCAmJiAhY29tcG9uZW50cy5wYXRoICYmIGNvbXBvbmVudHMucXVlcnkgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICAgICAgY29tcG9uZW50cy5yZWZlcmVuY2UgPSBcInNhbWUtZG9jdW1lbnRcIjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIGlmIChjb21wb25lbnRzLnNjaGVtZSA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICBjb21wb25lbnRzLnJlZmVyZW5jZSA9IFwicmVsYXRpdmVcIjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIGlmIChjb21wb25lbnRzLmZyYWdtZW50ID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICAgIGNvbXBvbmVudHMucmVmZXJlbmNlID0gXCJhYnNvbHV0ZVwiO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgY29tcG9uZW50cy5yZWZlcmVuY2UgPSBcInVyaVwiO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIC8vY2hlY2sgZm9yIHJlZmVyZW5jZSBlcnJvcnNcclxuICAgICAgICAgICAgaWYgKG9wdGlvbnMucmVmZXJlbmNlICYmIG9wdGlvbnMucmVmZXJlbmNlICE9PSBcInN1ZmZpeFwiICYmIG9wdGlvbnMucmVmZXJlbmNlICE9PSBjb21wb25lbnRzLnJlZmVyZW5jZSkge1xyXG4gICAgICAgICAgICAgICAgY29tcG9uZW50cy5lcnJvciA9IGNvbXBvbmVudHMuZXJyb3IgfHwgXCJVUkkgaXMgbm90IGEgXCIgKyBvcHRpb25zLnJlZmVyZW5jZSArIFwiIHJlZmVyZW5jZS5cIjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAvL2ZpbmQgc2NoZW1lIGhhbmRsZXJcclxuICAgICAgICAgICAgc2NoZW1lSGFuZGxlciA9IFNDSEVNRVNbKG9wdGlvbnMuc2NoZW1lIHx8IGNvbXBvbmVudHMuc2NoZW1lIHx8IFwiXCIpLnRvTG93ZXJDYXNlKCldO1xyXG4gICAgICAgICAgICAvL2NoZWNrIGlmIHNjaGVtZSBjYW4ndCBoYW5kbGUgSVJJc1xyXG4gICAgICAgICAgICBpZiAoVVJJX19JUklfU1VQUE9SVCAmJiB0eXBlb2YgcHVueWNvZGUgIT09IFwidW5kZWZpbmVkXCIgJiYgIW9wdGlvbnMudW5pY29kZVN1cHBvcnQgJiYgKCFzY2hlbWVIYW5kbGVyIHx8ICFzY2hlbWVIYW5kbGVyLnVuaWNvZGVTdXBwb3J0KSkge1xyXG4gICAgICAgICAgICAgICAgLy9pZiBob3N0IGNvbXBvbmVudCBpcyBhIGRvbWFpbiBuYW1lXHJcbiAgICAgICAgICAgICAgICBpZiAoY29tcG9uZW50cy5ob3N0ICYmIChvcHRpb25zLmRvbWFpbkhvc3QgfHwgKHNjaGVtZUhhbmRsZXIgJiYgc2NoZW1lSGFuZGxlci5kb21haW5Ib3N0KSkpIHtcclxuICAgICAgICAgICAgICAgICAgICAvL2NvbnZlcnQgVW5pY29kZSBJRE4gLT4gQVNDSUkgSUROXHJcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50cy5ob3N0ID0gcHVueWNvZGUudG9BU0NJSShjb21wb25lbnRzLmhvc3QucmVwbGFjZShwcm90b2NvbC5QQ1RfRU5DT0RFRCwgcGN0RGVjQ2hhcnMpLnRvTG93ZXJDYXNlKCkpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRzLmVycm9yID0gY29tcG9uZW50cy5lcnJvciB8fCBcIkhvc3QncyBkb21haW4gbmFtZSBjYW4gbm90IGJlIGNvbnZlcnRlZCB0byBBU0NJSSB2aWEgcHVueWNvZGU6IFwiICsgZTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAvL2NvbnZlcnQgSVJJIC0+IFVSSVxyXG4gICAgICAgICAgICAgICAgX25vcm1hbGl6ZUNvbXBvbmVudEVuY29kaW5nKGNvbXBvbmVudHMsIFVSSV9QUk9UT0NPTCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAvL25vcm1hbGl6ZSBlbmNvZGluZ3NcclxuICAgICAgICAgICAgICAgIF9ub3JtYWxpemVDb21wb25lbnRFbmNvZGluZyhjb21wb25lbnRzLCBwcm90b2NvbCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy9wZXJmb3JtIHNjaGVtZSBzcGVjaWZpYyBwYXJzaW5nXHJcbiAgICAgICAgICAgIGlmIChzY2hlbWVIYW5kbGVyICYmIHNjaGVtZUhhbmRsZXIucGFyc2UpIHtcclxuICAgICAgICAgICAgICAgIHNjaGVtZUhhbmRsZXIucGFyc2UoY29tcG9uZW50cywgb3B0aW9ucyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgIHBhcnNlRXJyb3IgPSB0cnVlO1xyXG4gICAgICAgICAgICBjb21wb25lbnRzLmVycm9yID0gY29tcG9uZW50cy5lcnJvciB8fCBcIlVSSSBjYW4gbm90IGJlIHBhcnNlZC5cIjtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGNvbXBvbmVudHM7XHJcbiAgICB9XHJcbiAgICA7XHJcbiAgICBmdW5jdGlvbiBfcmVjb21wb3NlQXV0aG9yaXR5KGNvbXBvbmVudHMsIG9wdGlvbnMpIHtcclxuICAgICAgICB2YXIgdXJpVG9rZW5zID0gW107XHJcbiAgICAgICAgaWYgKGNvbXBvbmVudHMudXNlcmluZm8gIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICB1cmlUb2tlbnMucHVzaChjb21wb25lbnRzLnVzZXJpbmZvKTtcclxuICAgICAgICAgICAgdXJpVG9rZW5zLnB1c2goXCJAXCIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoY29tcG9uZW50cy5ob3N0ICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgdXJpVG9rZW5zLnB1c2goY29tcG9uZW50cy5ob3N0KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKHR5cGVvZiBjb21wb25lbnRzLnBvcnQgPT09IFwibnVtYmVyXCIpIHtcclxuICAgICAgICAgICAgdXJpVG9rZW5zLnB1c2goXCI6XCIpO1xyXG4gICAgICAgICAgICB1cmlUb2tlbnMucHVzaChjb21wb25lbnRzLnBvcnQudG9TdHJpbmcoMTApKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHVyaVRva2Vucy5sZW5ndGggPyB1cmlUb2tlbnMuam9pbihcIlwiKSA6IHVuZGVmaW5lZDtcclxuICAgIH1cclxuICAgIDtcclxuICAgIGZ1bmN0aW9uIHJlbW92ZURvdFNlZ21lbnRzKGlucHV0KSB7XHJcbiAgICAgICAgdmFyIG91dHB1dCA9IFtdLCBzO1xyXG4gICAgICAgIHdoaWxlIChpbnB1dC5sZW5ndGgpIHtcclxuICAgICAgICAgICAgaWYgKGlucHV0Lm1hdGNoKFJEUzEpKSB7XHJcbiAgICAgICAgICAgICAgICBpbnB1dCA9IGlucHV0LnJlcGxhY2UoUkRTMSwgXCJcIik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSBpZiAoaW5wdXQubWF0Y2goUkRTMikpIHtcclxuICAgICAgICAgICAgICAgIGlucHV0ID0gaW5wdXQucmVwbGFjZShSRFMyLCBcIi9cIik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSBpZiAoaW5wdXQubWF0Y2goUkRTMykpIHtcclxuICAgICAgICAgICAgICAgIGlucHV0ID0gaW5wdXQucmVwbGFjZShSRFMzLCBcIi9cIik7XHJcbiAgICAgICAgICAgICAgICBvdXRwdXQucG9wKCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSBpZiAoaW5wdXQgPT09IFwiLlwiIHx8IGlucHV0ID09PSBcIi4uXCIpIHtcclxuICAgICAgICAgICAgICAgIGlucHV0ID0gXCJcIjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHMgPSBpbnB1dC5tYXRjaChSRFM1KVswXTtcclxuICAgICAgICAgICAgICAgIGlucHV0ID0gaW5wdXQuc2xpY2Uocy5sZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgb3V0cHV0LnB1c2gocyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIG91dHB1dC5qb2luKFwiXCIpO1xyXG4gICAgfVxyXG4gICAgO1xyXG4gICAgZnVuY3Rpb24gc2VyaWFsaXplKGNvbXBvbmVudHMsIG9wdGlvbnMpIHtcclxuICAgICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7IG9wdGlvbnMgPSB7fTsgfVxyXG4gICAgICAgIHZhciBwcm90b2NvbCA9IChVUklfX0lSSV9TVVBQT1JUICYmIG9wdGlvbnMuaXJpID8gSVJJX1BST1RPQ09MIDogVVJJX1BST1RPQ09MKSwgdXJpVG9rZW5zID0gW10sIHNjaGVtZUhhbmRsZXIsIGF1dGhvcml0eSwgcztcclxuICAgICAgICAvL2ZpbmQgc2NoZW1lIGhhbmRsZXJcclxuICAgICAgICBzY2hlbWVIYW5kbGVyID0gU0NIRU1FU1sob3B0aW9ucy5zY2hlbWUgfHwgY29tcG9uZW50cy5zY2hlbWUgfHwgXCJcIikudG9Mb3dlckNhc2UoKV07XHJcbiAgICAgICAgLy9wZXJmb3JtIHNjaGVtZSBzcGVjaWZpYyBzZXJpYWxpemF0aW9uXHJcbiAgICAgICAgaWYgKHNjaGVtZUhhbmRsZXIgJiYgc2NoZW1lSGFuZGxlci5zZXJpYWxpemUpXHJcbiAgICAgICAgICAgIHNjaGVtZUhhbmRsZXIuc2VyaWFsaXplKGNvbXBvbmVudHMsIG9wdGlvbnMpO1xyXG4gICAgICAgIC8vaWYgaG9zdCBjb21wb25lbnQgaXMgYSBkb21haW4gbmFtZVxyXG4gICAgICAgIGlmIChVUklfX0lSSV9TVVBQT1JUICYmIHR5cGVvZiBwdW55Y29kZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBjb21wb25lbnRzLmhvc3QgJiYgKG9wdGlvbnMuZG9tYWluSG9zdCB8fCAoc2NoZW1lSGFuZGxlciAmJiBzY2hlbWVIYW5kbGVyLmRvbWFpbkhvc3QpKSkge1xyXG4gICAgICAgICAgICAvL2NvbnZlcnQgSUROIHZpYSBwdW55Y29kZVxyXG4gICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgY29tcG9uZW50cy5ob3N0ID0gKCFvcHRpb25zLmlyaSA/IHB1bnljb2RlLnRvQVNDSUkoY29tcG9uZW50cy5ob3N0LnJlcGxhY2UocHJvdG9jb2wuUENUX0VOQ09ERUQsIHBjdERlY0NoYXJzKS50b0xvd2VyQ2FzZSgpKSA6IHB1bnljb2RlLnRvVW5pY29kZShjb21wb25lbnRzLmhvc3QpKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgY29tcG9uZW50cy5lcnJvciA9IGNvbXBvbmVudHMuZXJyb3IgfHwgXCJIb3N0J3MgZG9tYWluIG5hbWUgY2FuIG5vdCBiZSBjb252ZXJ0ZWQgdG8gXCIgKyAoIW9wdGlvbnMuaXJpID8gXCJBU0NJSVwiIDogXCJVbmljb2RlXCIpICsgXCIgdmlhIHB1bnljb2RlOiBcIiArIGU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgLy9ub3JtYWxpemUgZW5jb2RpbmdcclxuICAgICAgICBfbm9ybWFsaXplQ29tcG9uZW50RW5jb2RpbmcoY29tcG9uZW50cywgcHJvdG9jb2wpO1xyXG4gICAgICAgIGlmIChvcHRpb25zLnJlZmVyZW5jZSAhPT0gXCJzdWZmaXhcIiAmJiBjb21wb25lbnRzLnNjaGVtZSkge1xyXG4gICAgICAgICAgICB1cmlUb2tlbnMucHVzaChjb21wb25lbnRzLnNjaGVtZSk7XHJcbiAgICAgICAgICAgIHVyaVRva2Vucy5wdXNoKFwiOlwiKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgYXV0aG9yaXR5ID0gX3JlY29tcG9zZUF1dGhvcml0eShjb21wb25lbnRzLCBvcHRpb25zKTtcclxuICAgICAgICBpZiAoYXV0aG9yaXR5ICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgaWYgKG9wdGlvbnMucmVmZXJlbmNlICE9PSBcInN1ZmZpeFwiKSB7XHJcbiAgICAgICAgICAgICAgICB1cmlUb2tlbnMucHVzaChcIi8vXCIpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHVyaVRva2Vucy5wdXNoKGF1dGhvcml0eSk7XHJcbiAgICAgICAgICAgIGlmIChjb21wb25lbnRzLnBhdGggJiYgY29tcG9uZW50cy5wYXRoLmNoYXJBdCgwKSAhPT0gXCIvXCIpIHtcclxuICAgICAgICAgICAgICAgIHVyaVRva2Vucy5wdXNoKFwiL1wiKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoY29tcG9uZW50cy5wYXRoICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgcyA9IGNvbXBvbmVudHMucGF0aDtcclxuICAgICAgICAgICAgaWYgKCFvcHRpb25zLmFic29sdXRlUGF0aCAmJiAoIXNjaGVtZUhhbmRsZXIgfHwgIXNjaGVtZUhhbmRsZXIuYWJzb2x1dGVQYXRoKSkge1xyXG4gICAgICAgICAgICAgICAgcyA9IHJlbW92ZURvdFNlZ21lbnRzKHMpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChhdXRob3JpdHkgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICAgICAgcyA9IHMucmVwbGFjZSgvXlxcL1xcLy8sIFwiLyUyRlwiKTsgLy9kb24ndCBhbGxvdyB0aGUgcGF0aCB0byBzdGFydCB3aXRoIFwiLy9cIlxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHVyaVRva2Vucy5wdXNoKHMpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoY29tcG9uZW50cy5xdWVyeSAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgIHVyaVRva2Vucy5wdXNoKFwiP1wiKTtcclxuICAgICAgICAgICAgdXJpVG9rZW5zLnB1c2goY29tcG9uZW50cy5xdWVyeSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChjb21wb25lbnRzLmZyYWdtZW50ICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgdXJpVG9rZW5zLnB1c2goXCIjXCIpO1xyXG4gICAgICAgICAgICB1cmlUb2tlbnMucHVzaChjb21wb25lbnRzLmZyYWdtZW50KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHVyaVRva2Vucy5qb2luKCcnKTsgLy9tZXJnZSB0b2tlbnMgaW50byBhIHN0cmluZ1xyXG4gICAgfVxyXG4gICAgO1xyXG4gICAgZnVuY3Rpb24gcmVzb2x2ZUNvbXBvbmVudHMoYmFzZSwgcmVsYXRpdmUsIG9wdGlvbnMsIHNraXBOb3JtYWxpemF0aW9uKSB7XHJcbiAgICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgeyBvcHRpb25zID0ge307IH1cclxuICAgICAgICB2YXIgdGFyZ2V0ID0ge307XHJcbiAgICAgICAgaWYgKCFza2lwTm9ybWFsaXphdGlvbikge1xyXG4gICAgICAgICAgICBiYXNlID0gcGFyc2Uoc2VyaWFsaXplKGJhc2UsIG9wdGlvbnMpLCBvcHRpb25zKTsgLy9ub3JtYWxpemUgYmFzZSBjb21wb25lbnRzXHJcbiAgICAgICAgICAgIHJlbGF0aXZlID0gcGFyc2Uoc2VyaWFsaXplKHJlbGF0aXZlLCBvcHRpb25zKSwgb3B0aW9ucyk7IC8vbm9ybWFsaXplIHJlbGF0aXZlIGNvbXBvbmVudHNcclxuICAgICAgICB9XHJcbiAgICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XHJcbiAgICAgICAgaWYgKCFvcHRpb25zLnRvbGVyYW50ICYmIHJlbGF0aXZlLnNjaGVtZSkge1xyXG4gICAgICAgICAgICB0YXJnZXQuc2NoZW1lID0gcmVsYXRpdmUuc2NoZW1lO1xyXG4gICAgICAgICAgICAvL3RhcmdldC5hdXRob3JpdHkgPSByZWxhdGl2ZS5hdXRob3JpdHk7XHJcbiAgICAgICAgICAgIHRhcmdldC51c2VyaW5mbyA9IHJlbGF0aXZlLnVzZXJpbmZvO1xyXG4gICAgICAgICAgICB0YXJnZXQuaG9zdCA9IHJlbGF0aXZlLmhvc3Q7XHJcbiAgICAgICAgICAgIHRhcmdldC5wb3J0ID0gcmVsYXRpdmUucG9ydDtcclxuICAgICAgICAgICAgdGFyZ2V0LnBhdGggPSByZW1vdmVEb3RTZWdtZW50cyhyZWxhdGl2ZS5wYXRoKTtcclxuICAgICAgICAgICAgdGFyZ2V0LnF1ZXJ5ID0gcmVsYXRpdmUucXVlcnk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICBpZiAocmVsYXRpdmUudXNlcmluZm8gIT09IHVuZGVmaW5lZCB8fCByZWxhdGl2ZS5ob3N0ICE9PSB1bmRlZmluZWQgfHwgcmVsYXRpdmUucG9ydCAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICAvL3RhcmdldC5hdXRob3JpdHkgPSByZWxhdGl2ZS5hdXRob3JpdHk7XHJcbiAgICAgICAgICAgICAgICB0YXJnZXQudXNlcmluZm8gPSByZWxhdGl2ZS51c2VyaW5mbztcclxuICAgICAgICAgICAgICAgIHRhcmdldC5ob3N0ID0gcmVsYXRpdmUuaG9zdDtcclxuICAgICAgICAgICAgICAgIHRhcmdldC5wb3J0ID0gcmVsYXRpdmUucG9ydDtcclxuICAgICAgICAgICAgICAgIHRhcmdldC5wYXRoID0gcmVtb3ZlRG90U2VnbWVudHMocmVsYXRpdmUucGF0aCk7XHJcbiAgICAgICAgICAgICAgICB0YXJnZXQucXVlcnkgPSByZWxhdGl2ZS5xdWVyeTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGlmICghcmVsYXRpdmUucGF0aCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRhcmdldC5wYXRoID0gYmFzZS5wYXRoO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZWxhdGl2ZS5xdWVyeSAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldC5xdWVyeSA9IHJlbGF0aXZlLnF1ZXJ5O1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0LnF1ZXJ5ID0gYmFzZS5xdWVyeTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAocmVsYXRpdmUucGF0aC5jaGFyQXQoMCkgPT09IFwiL1wiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldC5wYXRoID0gcmVtb3ZlRG90U2VnbWVudHMocmVsYXRpdmUucGF0aCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoKGJhc2UudXNlcmluZm8gIT09IHVuZGVmaW5lZCB8fCBiYXNlLmhvc3QgIT09IHVuZGVmaW5lZCB8fCBiYXNlLnBvcnQgIT09IHVuZGVmaW5lZCkgJiYgIWJhc2UucGF0aCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0LnBhdGggPSBcIi9cIiArIHJlbGF0aXZlLnBhdGg7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoIWJhc2UucGF0aCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0LnBhdGggPSByZWxhdGl2ZS5wYXRoO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0LnBhdGggPSBiYXNlLnBhdGguc2xpY2UoMCwgYmFzZS5wYXRoLmxhc3RJbmRleE9mKFwiL1wiKSArIDEpICsgcmVsYXRpdmUucGF0aDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQucGF0aCA9IHJlbW92ZURvdFNlZ21lbnRzKHRhcmdldC5wYXRoKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0LnF1ZXJ5ID0gcmVsYXRpdmUucXVlcnk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAvL3RhcmdldC5hdXRob3JpdHkgPSBiYXNlLmF1dGhvcml0eTtcclxuICAgICAgICAgICAgICAgIHRhcmdldC51c2VyaW5mbyA9IGJhc2UudXNlcmluZm87XHJcbiAgICAgICAgICAgICAgICB0YXJnZXQuaG9zdCA9IGJhc2UuaG9zdDtcclxuICAgICAgICAgICAgICAgIHRhcmdldC5wb3J0ID0gYmFzZS5wb3J0O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHRhcmdldC5zY2hlbWUgPSBiYXNlLnNjaGVtZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGFyZ2V0LmZyYWdtZW50ID0gcmVsYXRpdmUuZnJhZ21lbnQ7XHJcbiAgICAgICAgcmV0dXJuIHRhcmdldDtcclxuICAgIH1cclxuICAgIDtcclxuICAgIGZ1bmN0aW9uIHJlc29sdmUoYmFzZVVSSSwgcmVsYXRpdmVVUkksIG9wdGlvbnMpIHtcclxuICAgICAgICByZXR1cm4gc2VyaWFsaXplKHJlc29sdmVDb21wb25lbnRzKHBhcnNlKGJhc2VVUkksIG9wdGlvbnMpLCBwYXJzZShyZWxhdGl2ZVVSSSwgb3B0aW9ucyksIG9wdGlvbnMsIHRydWUpLCBvcHRpb25zKTtcclxuICAgIH1cclxuICAgIDtcclxuICAgIGZ1bmN0aW9uIG5vcm1hbGl6ZSh1cmksIG9wdGlvbnMpIHtcclxuICAgICAgICBpZiAodHlwZW9mIHVyaSA9PT0gXCJzdHJpbmdcIikge1xyXG4gICAgICAgICAgICB1cmkgPSBzZXJpYWxpemUocGFyc2UodXJpLCBvcHRpb25zKSwgb3B0aW9ucyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2UgaWYgKHR5cGVPZih1cmkpID09PSBcIm9iamVjdFwiKSB7XHJcbiAgICAgICAgICAgIHVyaSA9IHBhcnNlKHNlcmlhbGl6ZSh1cmksIG9wdGlvbnMpLCBvcHRpb25zKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHVyaTtcclxuICAgIH1cclxuICAgIDtcclxuICAgIGZ1bmN0aW9uIGVxdWFsKHVyaUEsIHVyaUIsIG9wdGlvbnMpIHtcclxuICAgICAgICBpZiAodHlwZW9mIHVyaUEgPT09IFwic3RyaW5nXCIpIHtcclxuICAgICAgICAgICAgdXJpQSA9IHNlcmlhbGl6ZShwYXJzZSh1cmlBLCBvcHRpb25zKSwgb3B0aW9ucyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2UgaWYgKHR5cGVPZih1cmlBKSA9PT0gXCJvYmplY3RcIikge1xyXG4gICAgICAgICAgICB1cmlBID0gc2VyaWFsaXplKHVyaUEsIG9wdGlvbnMpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAodHlwZW9mIHVyaUIgPT09IFwic3RyaW5nXCIpIHtcclxuICAgICAgICAgICAgdXJpQiA9IHNlcmlhbGl6ZShwYXJzZSh1cmlCLCBvcHRpb25zKSwgb3B0aW9ucyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2UgaWYgKHR5cGVPZih1cmlCKSA9PT0gXCJvYmplY3RcIikge1xyXG4gICAgICAgICAgICB1cmlCID0gc2VyaWFsaXplKHVyaUIsIG9wdGlvbnMpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdXJpQSA9PT0gdXJpQjtcclxuICAgIH1cclxuICAgIDtcclxuICAgIGZ1bmN0aW9uIGVzY2FwZUNvbXBvbmVudChzdHIsIG9wdGlvbnMpIHtcclxuICAgICAgICByZXR1cm4gc3RyICYmIHN0ci50b1N0cmluZygpLnJlcGxhY2UoKCFVUklfX0lSSV9TVVBQT1JUIHx8ICFvcHRpb25zIHx8ICFvcHRpb25zLmlyaSA/IFVSSV9QUk9UT0NPTC5FU0NBUEUgOiBJUklfUFJPVE9DT0wuRVNDQVBFKSwgcGN0RW5jQ2hhcik7XHJcbiAgICB9XHJcbiAgICA7XHJcbiAgICBmdW5jdGlvbiB1bmVzY2FwZUNvbXBvbmVudChzdHIsIG9wdGlvbnMpIHtcclxuICAgICAgICByZXR1cm4gc3RyICYmIHN0ci50b1N0cmluZygpLnJlcGxhY2UoKCFVUklfX0lSSV9TVVBQT1JUIHx8ICFvcHRpb25zIHx8ICFvcHRpb25zLmlyaSA/IFVSSV9QUk9UT0NPTC5QQ1RfRU5DT0RFRCA6IElSSV9QUk9UT0NPTC5QQ1RfRU5DT0RFRCksIHBjdERlY0NoYXJzKTtcclxuICAgIH1cclxuICAgIDtcclxuICAgIHJldHVybiB7XHJcbiAgICAgICAgSVJJX1NVUFBPUlQ6IFVSSV9fSVJJX1NVUFBPUlQsXHJcbiAgICAgICAgVkFMSURBVEVfU1VQUE9SVDogVVJJX19WQUxJREFURV9TVVBQT1JULFxyXG4gICAgICAgIHBjdEVuY0NoYXI6IHBjdEVuY0NoYXIsXHJcbiAgICAgICAgcGN0RGVjQ2hhcnM6IHBjdERlY0NoYXJzLFxyXG4gICAgICAgIFNDSEVNRVM6IFNDSEVNRVMsXHJcbiAgICAgICAgcGFyc2U6IHBhcnNlLFxyXG4gICAgICAgIF9yZWNvbXBvc2VBdXRob3JpdHk6IF9yZWNvbXBvc2VBdXRob3JpdHksXHJcbiAgICAgICAgcmVtb3ZlRG90U2VnbWVudHM6IHJlbW92ZURvdFNlZ21lbnRzLFxyXG4gICAgICAgIHNlcmlhbGl6ZTogc2VyaWFsaXplLFxyXG4gICAgICAgIHJlc29sdmVDb21wb25lbnRzOiByZXNvbHZlQ29tcG9uZW50cyxcclxuICAgICAgICByZXNvbHZlOiByZXNvbHZlLFxyXG4gICAgICAgIG5vcm1hbGl6ZTogbm9ybWFsaXplLFxyXG4gICAgICAgIGVxdWFsOiBlcXVhbCxcclxuICAgICAgICBlc2NhcGVDb21wb25lbnQ6IGVzY2FwZUNvbXBvbmVudCxcclxuICAgICAgICB1bmVzY2FwZUNvbXBvbmVudDogdW5lc2NhcGVDb21wb25lbnRcclxuICAgIH07XHJcbn0pKCk7XHJcbmlmICghQ09NUElMRUQgJiYgdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gXCJmdW5jdGlvblwiKSB7XHJcbiAgICB2YXIgcHVueWNvZGUgPSByZXF1aXJlKFwiLi9wdW55Y29kZVwiKTtcclxuICAgIG1vZHVsZS5leHBvcnRzID0gVVJJO1xyXG4gICAgcmVxdWlyZShcIi4vc2NoZW1lc1wiKTtcclxufVxyXG4iXX0= diff --git a/packages/jsfc/test.md b/packages/jsfc/test.md deleted file mode 100644 index fa08113c71b..00000000000 --- a/packages/jsfc/test.md +++ /dev/null @@ -1,228 +0,0 @@ -# TOC - - [merge.js](#mergejs) - - [merge](#mergejs-merge) - - [schema-defaults.js](#schema-defaultsjs) - - [createDefaults](#schema-defaultsjs-createdefaults) - - [defaultForm](#schema-defaultsjs-defaultform) - - - -# merge.js -should contain a function for merging schema and form definitions. - -```js -_merge.merge.should.be.an('function'); -``` - - -## merge -should combine a schema and form definition, regardless of order. - -```js -(0, _merge.merge)(schema, ['name', 'gender']).should.be.deep.equal(stdForm.form); -(0, _merge.merge)(schema, ['gender']).should.be.deep.equal([stdForm.form[1]]); -(0, _merge.merge)(schema, ['gender', 'name']).should.be.deep.equal([stdForm.form[1], stdForm.form[0]]); -``` - -should handle a wildcard * in the form definition. - -```js -(0, _merge.merge)(schema, ['*']).should.be.deep.equal(stdForm.form); -``` - -should allow items that are not in the schema. - -```js -(0, _merge.merge)(schema, ['*', { type: 'fieldset' }]).should.be.deep.equal(stdForm.form.concat([{ type: 'fieldset' }])); -``` - - -# schema-defaults.js -should hold functions for generating a default form schema from defaults it creates. - -```js -_schemaDefaults.defaultForm.should.be.an('function'); -_schemaDefaults.createDefaults.should.be.an('function'); -``` - - -## createDefaults -should create default rules. - -```js -var rules = (0, _schemaDefaults.createDefaults)(); -rules.should.be.an('object'); -``` - - -## defaultForm -should generate default form def from a schema. - -```js -var schema = { - 'type': 'object', - 'properties': { - 'name': { - 'title': 'Name', - 'description': 'Gimme yea name lad', - 'type': 'string' - }, - 'gender': { - 'title': 'Choose', - 'type': 'string', - 'enum': ['undefined', 'null', 'NaN'] - }, - 'overEighteen': { - 'title': 'Are you over 18 years old?', - 'type': 'boolean', - 'default': false - }, - 'attributes': { - 'type': 'object', - 'required': ['eyecolor'], - 'properties': { - 'eyecolor': { 'type': 'string', 'title': 'Eye color' }, - 'haircolor': { 'type': 'string', 'title': 'Hair color' }, - 'shoulders': { - 'type': 'object', - 'title': 'Shoulders', - 'properties': { - 'left': { 'type': 'string' }, - 'right': { 'type': 'string' } - } - } - } - } - } -}; -var form = [{ - 'title': 'Name', - 'description': 'Gimme yea name lad', - 'schema': { - 'title': 'Name', - 'description': 'Gimme yea name lad', - 'type': 'string' - }, - 'ngModelOptions': {}, - 'key': ['name'], - 'type': 'text' -}, { - 'title': 'Choose', - 'schema': { - 'title': 'Choose', - 'type': 'string', - 'enum': ['undefined', 'null', 'NaN'] - }, - 'ngModelOptions': {}, - 'key': ['gender'], - 'type': 'select', - 'titleMap': [{ - 'name': 'undefined', - 'value': 'undefined' - }, { - 'name': 'null', - 'value': 'null' - }, { - 'name': 'NaN', - 'value': 'NaN' - }] -}, { - 'title': 'Are you over 18 years old?', - 'schema': { - 'title': 'Are you over 18 years old?', - 'type': 'boolean', - 'default': false - }, - 'ngModelOptions': {}, - 'key': ['overEighteen'], - 'type': 'checkbox' -}, { - 'title': 'attributes', - 'schema': { - 'type': 'object', - 'required': ['eyecolor'], - 'properties': { - 'eyecolor': { - 'type': 'string', - 'title': 'Eye color' - }, - 'haircolor': { - 'type': 'string', - 'title': 'Hair color' - }, - 'shoulders': { - 'type': 'object', - 'title': 'Shoulders', - 'properties': { - 'left': { - 'type': 'string' - }, - 'right': { - 'type': 'string' - } - } - } - } - }, - 'ngModelOptions': {}, - 'key': ['attributes'], - 'type': 'fieldset', - 'items': [{ - 'title': 'Eye color', - 'required': true, - 'schema': { - 'type': 'string', - 'title': 'Eye color' - }, - 'ngModelOptions': {}, - 'key': ['attributes', 'eyecolor'], - 'type': 'text' - }, { - 'title': 'Hair color', - 'schema': { - 'type': 'string', - 'title': 'Hair color' - }, - 'ngModelOptions': {}, - 'key': ['attributes', 'haircolor'], - 'type': 'text' - }, { - 'title': 'Shoulders', - 'schema': { - 'type': 'object', - 'title': 'Shoulders', - 'properties': { - 'left': { - 'type': 'string' - }, - 'right': { - 'type': 'string' - } - } - }, - 'ngModelOptions': {}, - 'key': ['attributes', 'shoulders'], - 'type': 'fieldset', - 'items': [{ - 'title': 'left', - 'schema': { - 'type': 'string' - }, - 'ngModelOptions': {}, - 'key': ['attributes', 'shoulders', 'left'], - 'type': 'text' - }, { - 'title': 'right', - 'schema': { - 'type': 'string' - }, - 'ngModelOptions': {}, - 'key': ['attributes', 'shoulders', 'right'], - 'type': 'text' - }] - }] -}]; -var f = (0, _schemaDefaults.defaultForm)(schema, (0, _schemaDefaults.createDefaults)()); -f.form.should.be.deep.equal(form); -``` - diff --git a/packages/jsfc/webpack.config.js b/packages/jsfc/webpack.config.js deleted file mode 100644 index 349b3015baa..00000000000 --- a/packages/jsfc/webpack.config.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - output: { - filename: 'index.js', - }, -}; diff --git a/tools/scripts-config-jest/test-setup.js b/tools/scripts-config-jest/test-setup.js index 39adbaaa525..41c68720ae3 100644 --- a/tools/scripts-config-jest/test-setup.js +++ b/tools/scripts-config-jest/test-setup.js @@ -50,6 +50,10 @@ if (!global.URL?.revokeObjectURL) { global.URL.revokeObjectURL = jest.fn(); } +if (!global._) { + global._ = require('lodash'); +} + // Mock fetch try { const fetch = jest.fn( diff --git a/yarn.lock b/yarn.lock index 4ad66705b70..ae8fe7cca8e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10717,18 +10717,7 @@ html-tags@^3.1.0, html-tags@^3.3.1: tapable "^1.1.3" util.promisify "1.0.0" -"html-webpack-plugin-5@npm:html-webpack-plugin@^5": - version "5.6.0" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz#50a8fa6709245608cb00e811eacecb8e0d7b7ea0" - integrity sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw== - dependencies: - "@types/html-minifier-terser" "^6.0.0" - html-minifier-terser "^6.0.2" - lodash "^4.17.21" - pretty-error "^4.0.0" - tapable "^2.0.0" - -html-webpack-plugin@^5.5.0, html-webpack-plugin@^5.6.0: +"html-webpack-plugin-5@npm:html-webpack-plugin@^5", html-webpack-plugin@^5.5.0, html-webpack-plugin@^5.6.0: version "5.6.0" resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz#50a8fa6709245608cb00e811eacecb8e0d7b7ea0" integrity sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw== @@ -12382,7 +12371,7 @@ json-parse-even-better-errors@^3.0.0: resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz#02bb29fb5da90b5444581749c22cedd3597c6cb0" integrity sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg== -json-refs@^3.0.15: +json-refs@3.0.15: version "3.0.15" resolved "https://registry.yarnpkg.com/json-refs/-/json-refs-3.0.15.tgz#1089f4acf263a3152c790479485195cd6449e855" integrity sha512-0vOQd9eLNBL18EGl5yYaO44GhixmImes2wiYn9Z3sag3QnehWrYWlB9AFtMxCL2Bj3fyxgDYkxGFEU/chlYssw== @@ -17651,16 +17640,7 @@ string-replace-loader@^2.3.0: loader-utils "^1.2.3" schema-utils "^2.6.5" -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -17756,7 +17736,7 @@ stringify-entities@^4.0.0: character-entities-html4 "^2.0.0" character-entities-legacy "^3.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -17770,13 +17750,6 @@ strip-ansi@^3.0.1: dependencies: ansi-regex "^2.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -18714,9 +18687,9 @@ typescript-tuple@^2.2.1: typescript-compare "^0.0.2" typescript@^5.0.4, typescript@^5.3.2, typescript@^5.3.3: - version "5.3.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" - integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== + version "5.4.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" + integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== ua-parser-js@^1.0.33: version "1.0.37" @@ -19714,7 +19687,7 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -19732,15 +19705,6 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"